import mock
import pytest
from werkzeug.exceptions import NotFound

import app.main.helpers as helpers
from dmcontent.content_loader import ContentLoader

from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub

content_loader = ContentLoader('tests/fixtures/content')
content_loader.load_manifest('dos', 'data', 'edit_brief')
questions_builder = content_loader.get_manifest('dos', 'edit_brief')


class TestBuyersHelpers(object):
    def test_get_framework_and_lot(self):
        provided_lot = LotStub(slug='digital-specialists', allows_brief=True).response()
        data_api_client = mock.Mock()
        data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[provided_lot],
        ).single_result_response()

        framework, lot = helpers.buyers_helpers.get_framework_and_lot('digital-outcomes-and-specialists-4',
                                                                      'digital-specialists',
                                                                      data_api_client)

        assert framework['status'] == "live"
        assert framework['name'] == 'Digital Outcomes and Specialists 4'
        assert framework['slug'] == 'digital-outcomes-and-specialists-4'
        assert framework['clarificationQuestionsOpen'] is True
        assert lot == provided_lot

    def test_get_framework_and_lot_404s_for_wrong_framework_status(self):
        data_api_client = mock.Mock()
        data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='open',
            lots=[
                LotStub(slug='digital-specialists', allows_brief=True).response()
            ]
        ).single_result_response()

        with pytest.raises(NotFound):
            helpers.buyers_helpers.get_framework_and_lot(
                'digital-outcomes-and-specialists-4',
                'digital-specialists',
                data_api_client,
                allowed_statuses=['live'],
            )

    def test_get_framework_and_lot_404s_if_allows_brief_required(self):
        data_api_client = mock.Mock()
        data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[
                LotStub(slug='digital-specialists', allows_brief=False).response()
            ]
        ).single_result_response()

        with pytest.raises(NotFound):
            helpers.buyers_helpers.get_framework_and_lot(
                'digital-outcomes-and-specialists-4',
                'digital-specialists',
                data_api_client,
                must_allow_brief=True,
            )

    @pytest.mark.parametrize(
        ['framework', 'lot', 'user', 'result'],
        [
            ('digital-outcomes-and-specialists-4', 'digital-specialists', 123, True),
            ('not-digital-outcomes-and-specialists', 'digital-specialists', 123, False),
            ('digital-outcomes-and-specialists-4', 'not-digital-specialists', 123, False),
            ('digital-outcomes-and-specialists-4', 'digital-specialists', 124, False),
        ]
    )
    def test_is_brief_correct(self, framework, lot, user, result):
        brief = BriefStub(framework_slug='digital-outcomes-and-specialists-4', user_id=123, status='live').response()

        assert helpers.buyers_helpers.is_brief_correct(brief, framework, lot, user) is result

    @pytest.mark.parametrize(
        ['status', 'allow_withdrawn', 'result'],
        [
            ('withdrawn', True, True),
            ('withdrawn', False, False),
            ('live', True, True),
            ('live', False, True),
        ]
    )
    def test_if_brief_correct_allow_withdrawn(self, status, allow_withdrawn, result):
        brief = BriefStub(framework_slug='digital-outcomes-and-specialists-4', user_id=123, status=status).response()
        assert helpers.buyers_helpers.is_brief_correct(
            brief, 'digital-outcomes-and-specialists-4', 'digital-specialists', 123, allow_withdrawn=allow_withdrawn
        ) is result

    @pytest.mark.parametrize(
        'allowed_statuses, result', [
            (['live', 'closed'], True),
            (['closed'], False)
        ]
    )
    def test_is_brief_correct_allowed_statuses(self, allowed_statuses, result):
        brief = BriefStub(framework_slug='digital-outcomes-and-specialists-4', user_id=123, status='live').response()
        assert helpers.buyers_helpers.is_brief_correct(
            brief, 'digital-outcomes-and-specialists-4', 'digital-specialists', 123, allowed_statuses=allowed_statuses
        ) is result

    def test_is_brief_associated_with_user(self):
        brief = BriefStub(user_id=123).response()
        assert helpers.buyers_helpers.is_brief_associated_with_user(brief, 123) is True
        assert helpers.buyers_helpers.is_brief_associated_with_user(brief, 234) is False

    def test_brief_can_be_edited(self):
        assert helpers.buyers_helpers.brief_can_be_edited(BriefStub(status='draft').response()) is True
        assert helpers.buyers_helpers.brief_can_be_edited(BriefStub(status='live').response()) is False

    def test_brief_is_withdrawn(self):
        assert helpers.buyers_helpers.brief_is_withdrawn(BriefStub(status='withdrawn').response()) is True
        assert helpers.buyers_helpers.brief_is_withdrawn(BriefStub(status='live').response()) is False

    def test_section_has_at_least_one_required_question(self):
        content = content_loader.get_manifest('dos', 'edit_brief').filter(
            {'lot': 'digital-specialists'}
        )

        sections_with_required_questions = {
            'section-1': True,
            'section-2': True,
            'section-4': False,
            'section-5': True
        }

        for section in content.sections:
            assert helpers.buyers_helpers.section_has_at_least_one_required_question(section) \
                == sections_with_required_questions[section.slug]

    def test_count_unanswered_questions(self):
        brief = {
            'status': 'draft',
            'frameworkSlug': 'dos',
            'lotSlug': 'digital-specialists',
            'required1': True
        }
        content = content_loader.get_manifest('dos', 'edit_brief').filter(
            {'lot': 'digital-specialists'}
        )
        sections = content.summary(brief)

        unanswered_required, unanswered_optional = helpers.buyers_helpers.count_unanswered_questions(sections)
        assert unanswered_required == 2
        assert unanswered_optional == 2

    def test_add_unanswered_counts_to_briefs(self):
        briefs = [{
            'status': 'draft',
            'frameworkSlug': 'dos',
            'lotSlug': 'digital-specialists',
            'required1': True
        }]

        assert helpers.buyers_helpers.add_unanswered_counts_to_briefs(briefs, content_loader) == [{
            'status': 'draft',
            'frameworkSlug': 'dos',
            'lotSlug': 'digital-specialists',
            'required1': True,
            'unanswered_required': 2,
            'unanswered_optional': 2
        }]

    def test_get_sorted_responses_for_brief(self):
        data_api_client = mock.Mock()
        data_api_client.find_brief_responses.return_value = {
            "briefResponses": [
                {"id": "five", "niceToHaveRequirements": [True, True, True, True, True]},
                {"id": "zero", "niceToHaveRequirements": [False, False, False, False, False]},
                {"id": "three", "niceToHaveRequirements": [True, True, False, False, True]},
                {"id": "five", "niceToHaveRequirements": [True, True, True, True, True]},
                {"id": "four", "niceToHaveRequirements": [True, True, True, True, False]},
                {"id": "one", "niceToHaveRequirements": [False, False, False, True, False]},
                {"id": "four", "niceToHaveRequirements": [True, True, True, True, False]},
            ]
        }
        brief = {"id": 1, "niceToHaveRequirements": ["Nice", "to", "have", "yes", "please"]}

        assert helpers.buyers_helpers.get_sorted_responses_for_brief(brief, data_api_client) == [
            {'id': 'five', 'niceToHaveRequirements': [True, True, True, True, True]},
            {'id': 'five', 'niceToHaveRequirements': [True, True, True, True, True]},
            {'id': 'four', 'niceToHaveRequirements': [True, True, True, True, False]},
            {'id': 'four', 'niceToHaveRequirements': [True, True, True, True, False]},
            {'id': 'three', 'niceToHaveRequirements': [True, True, False, False, True]},
            {"id": "one", "niceToHaveRequirements": [False, False, False, True, False]},
            {'id': 'zero', 'niceToHaveRequirements': [False, False, False, False, False]}
        ]

    def test_get_sorted_responses_does_not_sort_if_no_nice_to_haves(self):
        data_api_client = mock.Mock()
        data_api_client.find_brief_responses.return_value = {
            "briefResponses": [
                {"id": "five"},
                {"id": "zero"},
                {"id": "three"},
                {"id": "five"}
            ]
        }
        brief = {"id": 1, "niceToHaveRequirements": []}
        assert helpers.buyers_helpers.get_sorted_responses_for_brief(brief, data_api_client) == [
            {"id": "five"},
            {"id": "zero"},
            {"id": "three"},
            {"id": "five"}
        ]

[((247, 286), 'dmcontent.content_loader.ContentLoader', 'ContentLoader', (['"""tests/fixtures/content"""'], {}), "('tests/fixtures/content')\n", (260, 286), False, 'from dmcontent.content_loader import ContentLoader\n'), ((2802, 3195), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (["['framework', 'lot', 'user', 'result']", "[('digital-outcomes-and-specialists-4', 'digital-specialists', 123, True),\n    ('not-digital-outcomes-and-specialists', 'digital-specialists', 123, \n    False), ('digital-outcomes-and-specialists-4',\n    'not-digital-specialists', 123, False), (\n    'digital-outcomes-and-specialists-4', 'digital-specialists', 124, False)]"], {}), "(['framework', 'lot', 'user', 'result'], [(\n    'digital-outcomes-and-specialists-4', 'digital-specialists', 123, True),\n    ('not-digital-outcomes-and-specialists', 'digital-specialists', 123, \n    False), ('digital-outcomes-and-specialists-4',\n    'not-digital-specialists', 123, False), (\n    'digital-outcomes-and-specialists-4', 'digital-specialists', 124, False)])\n", (2825, 3195), False, 'import pytest\n'), ((3540, 3717), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (["['status', 'allow_withdrawn', 'result']", "[('withdrawn', True, True), ('withdrawn', False, False), ('live', True, \n    True), ('live', False, True)]"], {}), "(['status', 'allow_withdrawn', 'result'], [(\n    'withdrawn', True, True), ('withdrawn', False, False), ('live', True, \n    True), ('live', False, True)])\n", (3563, 3717), False, 'import pytest\n'), ((4192, 4299), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""allowed_statuses, result"""', "[(['live', 'closed'], True), (['closed'], False)]"], {}), "('allowed_statuses, result', [(['live', 'closed'], \n    True), (['closed'], False)])\n", (4215, 4299), False, 'import pytest\n'), ((606, 617), 'mock.Mock', 'mock.Mock', ([], {}), '()\n', (615, 617), False, 'import mock\n'), ((862, 993), 'app.main.helpers.buyers_helpers.get_framework_and_lot', 'helpers.buyers_helpers.get_framework_and_lot', (['"""digital-outcomes-and-specialists-4"""', '"""digital-specialists"""', 'data_api_client'], {}), "(\n    'digital-outcomes-and-specialists-4', 'digital-specialists',\n    data_api_client)\n", (906, 993), True, 'import app.main.helpers as helpers\n'), ((1516, 1527), 'mock.Mock', 'mock.Mock', ([], {}), '()\n', (1525, 1527), False, 'import mock\n'), ((2207, 2218), 'mock.Mock', 'mock.Mock', ([], {}), '()\n', (2216, 2218), False, 'import mock\n'), ((6530, 6589), 'app.main.helpers.buyers_helpers.count_unanswered_questions', 'helpers.buyers_helpers.count_unanswered_questions', (['sections'], {}), '(sections)\n', (6579, 6589), True, 'import app.main.helpers as helpers\n'), ((7306, 7317), 'mock.Mock', 'mock.Mock', ([], {}), '()\n', (7315, 7317), False, 'import mock\n'), ((8997, 9008), 'mock.Mock', 'mock.Mock', ([], {}), '()\n', (9006, 9008), False, 'import mock\n'), ((1842, 1865), 'pytest.raises', 'pytest.raises', (['NotFound'], {}), '(NotFound)\n', (1855, 1865), False, 'import pytest\n'), ((1879, 2037), 'app.main.helpers.buyers_helpers.get_framework_and_lot', 'helpers.buyers_helpers.get_framework_and_lot', (['"""digital-outcomes-and-specialists-4"""', '"""digital-specialists"""', 'data_api_client'], {'allowed_statuses': "['live']"}), "(\n    'digital-outcomes-and-specialists-4', 'digital-specialists',\n    data_api_client, allowed_statuses=['live'])\n", (1923, 2037), True, 'import app.main.helpers as helpers\n'), ((2534, 2557), 'pytest.raises', 'pytest.raises', (['NotFound'], {}), '(NotFound)\n', (2547, 2557), False, 'import pytest\n'), ((2571, 2725), 'app.main.helpers.buyers_helpers.get_framework_and_lot', 'helpers.buyers_helpers.get_framework_and_lot', (['"""digital-outcomes-and-specialists-4"""', '"""digital-specialists"""', 'data_api_client'], {'must_allow_brief': '(True)'}), "(\n    'digital-outcomes-and-specialists-4', 'digital-specialists',\n    data_api_client, must_allow_brief=True)\n", (2615, 2725), True, 'import app.main.helpers as helpers\n'), ((3455, 3523), 'app.main.helpers.buyers_helpers.is_brief_correct', 'helpers.buyers_helpers.is_brief_correct', (['brief', 'framework', 'lot', 'user'], {}), '(brief, framework, lot, user)\n', (3494, 3523), True, 'import app.main.helpers as helpers\n'), ((4008, 4161), 'app.main.helpers.buyers_helpers.is_brief_correct', 'helpers.buyers_helpers.is_brief_correct', (['brief', '"""digital-outcomes-and-specialists-4"""', '"""digital-specialists"""', '(123)'], {'allow_withdrawn': 'allow_withdrawn'}), "(brief,\n    'digital-outcomes-and-specialists-4', 'digital-specialists', 123,\n    allow_withdrawn=allow_withdrawn)\n", (4047, 4161), True, 'import app.main.helpers as helpers\n'), ((4556, 4711), 'app.main.helpers.buyers_helpers.is_brief_correct', 'helpers.buyers_helpers.is_brief_correct', (['brief', '"""digital-outcomes-and-specialists-4"""', '"""digital-specialists"""', '(123)'], {'allowed_statuses': 'allowed_statuses'}), "(brief,\n    'digital-outcomes-and-specialists-4', 'digital-specialists', 123,\n    allowed_statuses=allowed_statuses)\n", (4595, 4711), True, 'import app.main.helpers as helpers\n'), ((4852, 4916), 'app.main.helpers.buyers_helpers.is_brief_associated_with_user', 'helpers.buyers_helpers.is_brief_associated_with_user', (['brief', '(123)'], {}), '(brief, 123)\n', (4904, 4916), True, 'import app.main.helpers as helpers\n'), ((4940, 5004), 'app.main.helpers.buyers_helpers.is_brief_associated_with_user', 'helpers.buyers_helpers.is_brief_associated_with_user', (['brief', '(234)'], {}), '(brief, 234)\n', (4992, 5004), True, 'import app.main.helpers as helpers\n'), ((6913, 6991), 'app.main.helpers.buyers_helpers.add_unanswered_counts_to_briefs', 'helpers.buyers_helpers.add_unanswered_counts_to_briefs', (['briefs', 'content_loader'], {}), '(briefs, content_loader)\n', (6967, 6991), True, 'import app.main.helpers as helpers\n'), ((8188, 8265), 'app.main.helpers.buyers_helpers.get_sorted_responses_for_brief', 'helpers.buyers_helpers.get_sorted_responses_for_brief', (['brief', 'data_api_client'], {}), '(brief, data_api_client)\n', (8241, 8265), True, 'import app.main.helpers as helpers\n'), ((9326, 9403), 'app.main.helpers.buyers_helpers.get_sorted_responses_for_brief', 'helpers.buyers_helpers.get_sorted_responses_for_brief', (['brief', 'data_api_client'], {}), '(brief, data_api_client)\n', (9379, 9403), True, 'import app.main.helpers as helpers\n'), ((514, 568), 'dmtestutils.api_model_stubs.LotStub', 'LotStub', ([], {'slug': '"""digital-specialists"""', 'allows_brief': '(True)'}), "(slug='digital-specialists', allows_brief=True)\n", (521, 568), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((671, 767), 'dmtestutils.api_model_stubs.FrameworkStub', 'FrameworkStub', ([], {'slug': '"""digital-outcomes-and-specialists-4"""', 'status': '"""live"""', 'lots': '[provided_lot]'}), "(slug='digital-outcomes-and-specialists-4', status='live',\n    lots=[provided_lot])\n", (684, 767), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((3337, 3431), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'framework_slug': '"""digital-outcomes-and-specialists-4"""', 'user_id': '(123)', 'status': '"""live"""'}), "(framework_slug='digital-outcomes-and-specialists-4', user_id=123,\n    status='live')\n", (3346, 3431), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((3891, 3985), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'framework_slug': '"""digital-outcomes-and-specialists-4"""', 'user_id': '(123)', 'status': 'status'}), "(framework_slug='digital-outcomes-and-specialists-4', user_id=123,\n    status=status)\n", (3900, 3985), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((4439, 4533), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'framework_slug': '"""digital-outcomes-and-specialists-4"""', 'user_id': '(123)', 'status': '"""live"""'}), "(framework_slug='digital-outcomes-and-specialists-4', user_id=123,\n    status='live')\n", (4448, 4533), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((4803, 4825), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'user_id': '(123)'}), '(user_id=123)\n', (4812, 4825), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((5946, 6020), 'app.main.helpers.buyers_helpers.section_has_at_least_one_required_question', 'helpers.buyers_helpers.section_has_at_least_one_required_question', (['section'], {}), '(section)\n', (6011, 6020), True, 'import app.main.helpers as helpers\n'), ((5113, 5138), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'status': '"""draft"""'}), "(status='draft')\n", (5122, 5138), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((5217, 5241), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'status': '"""live"""'}), "(status='live')\n", (5226, 5241), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((5360, 5389), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'status': '"""withdrawn"""'}), "(status='withdrawn')\n", (5369, 5389), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((5467, 5491), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', ([], {'status': '"""live"""'}), "(status='live')\n", (5476, 5491), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((1713, 1767), 'dmtestutils.api_model_stubs.LotStub', 'LotStub', ([], {'slug': '"""digital-specialists"""', 'allows_brief': '(True)'}), "(slug='digital-specialists', allows_brief=True)\n", (1720, 1767), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((2404, 2459), 'dmtestutils.api_model_stubs.LotStub', 'LotStub', ([], {'slug': '"""digital-specialists"""', 'allows_brief': '(False)'}), "(slug='digital-specialists', allows_brief=False)\n", (2411, 2459), False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n')]