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"}
        ]

[((10, 17, 10, 56), 'dmcontent.content_loader.ContentLoader', 'ContentLoader', ({(10, 31, 10, 55): '"""tests/fixtures/content"""'}, {}), "('tests/fixtures/content')", False, 'from dmcontent.content_loader import ContentLoader\n'), ((71, 5, 79, 5), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(72, 8, 72, 46): "['framework', 'lot', 'user', 'result']", (73, 8, 78, 9): "[('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)])", False, 'import pytest\n'), ((85, 5, 93, 5), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(86, 8, 86, 47): "['status', 'allow_withdrawn', 'result']", (87, 8, 92, 9): "[('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)])", False, 'import pytest\n'), ((100, 5, 105, 5), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(101, 8, 101, 34): '"""allowed_statuses, result"""', (101, 36, 104, 9): "[(['live', 'closed'], True), (['closed'], False)]"}, {}), "('allowed_statuses, result', [(['live', 'closed'], \n    True), (['closed'], False)])", False, 'import pytest\n'), ((18, 26, 18, 37), 'mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'import mock\n'), ((25, 25, 27, 86), 'app.main.helpers.buyers_helpers.get_framework_and_lot', 'helpers.buyers_helpers.get_framework_and_lot', ({(25, 70, 25, 106): '"""digital-outcomes-and-specialists-4"""', (26, 70, 26, 91): '"""digital-specialists"""', (27, 70, 27, 85): 'data_api_client'}, {}), "(\n    'digital-outcomes-and-specialists-4', 'digital-specialists',\n    data_api_client)", True, 'import app.main.helpers as helpers\n'), ((36, 26, 36, 37), 'mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'import mock\n'), ((54, 26, 54, 37), 'mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'import mock\n'), ((153, 51, 153, 110), 'app.main.helpers.buyers_helpers.count_unanswered_questions', 'helpers.buyers_helpers.count_unanswered_questions', ({(153, 101, 153, 109): 'sections'}, {}), '(sections)', True, 'import app.main.helpers as helpers\n'), ((175, 26, 175, 37), 'mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'import mock\n'), ((200, 26, 200, 37), 'mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'import mock\n'), ((45, 13, 45, 36), 'pytest.raises', 'pytest.raises', ({(45, 27, 45, 35): 'NotFound'}, {}), '(NotFound)', False, 'import pytest\n'), ((46, 12, 51, 13), 'app.main.helpers.buyers_helpers.get_framework_and_lot', 'helpers.buyers_helpers.get_framework_and_lot', (), '', True, 'import app.main.helpers as helpers\n'), ((63, 13, 63, 36), 'pytest.raises', 'pytest.raises', ({(63, 27, 63, 35): 'NotFound'}, {}), '(NotFound)', False, 'import pytest\n'), ((64, 12, 69, 13), 'app.main.helpers.buyers_helpers.get_framework_and_lot', 'helpers.buyers_helpers.get_framework_and_lot', (), '', True, 'import app.main.helpers as helpers\n'), ((83, 15, 83, 83), 'app.main.helpers.buyers_helpers.is_brief_correct', 'helpers.buyers_helpers.is_brief_correct', ({(83, 55, 83, 60): 'brief', (83, 62, 83, 71): 'framework', (83, 73, 83, 76): 'lot', (83, 78, 83, 82): 'user'}, {}), '(brief, framework, lot, user)', True, 'import app.main.helpers as helpers\n'), ((96, 15, 98, 9), 'app.main.helpers.buyers_helpers.is_brief_correct', 'helpers.buyers_helpers.is_brief_correct', (), '', True, 'import app.main.helpers as helpers\n'), ((108, 15, 110, 9), 'app.main.helpers.buyers_helpers.is_brief_correct', 'helpers.buyers_helpers.is_brief_correct', (), '', True, 'import app.main.helpers as helpers\n'), ((114, 15, 114, 79), 'app.main.helpers.buyers_helpers.is_brief_associated_with_user', 'helpers.buyers_helpers.is_brief_associated_with_user', ({(114, 68, 114, 73): 'brief', (114, 75, 114, 78): '(123)'}, {}), '(brief, 123)', True, 'import app.main.helpers as helpers\n'), ((115, 15, 115, 79), 'app.main.helpers.buyers_helpers.is_brief_associated_with_user', 'helpers.buyers_helpers.is_brief_associated_with_user', ({(115, 68, 115, 73): 'brief', (115, 75, 115, 78): '(234)'}, {}), '(brief, 234)', True, 'import app.main.helpers as helpers\n'), ((165, 15, 165, 93), 'app.main.helpers.buyers_helpers.add_unanswered_counts_to_briefs', 'helpers.buyers_helpers.add_unanswered_counts_to_briefs', ({(165, 70, 165, 76): 'briefs', (165, 78, 165, 92): 'content_loader'}, {}), '(briefs, content_loader)', True, 'import app.main.helpers as helpers\n'), ((189, 15, 189, 92), 'app.main.helpers.buyers_helpers.get_sorted_responses_for_brief', 'helpers.buyers_helpers.get_sorted_responses_for_brief', ({(189, 69, 189, 74): 'brief', (189, 76, 189, 91): 'data_api_client'}, {}), '(brief, data_api_client)', True, 'import app.main.helpers as helpers\n'), ((210, 15, 210, 92), 'app.main.helpers.buyers_helpers.get_sorted_responses_for_brief', 'helpers.buyers_helpers.get_sorted_responses_for_brief', ({(210, 69, 210, 74): 'brief', (210, 76, 210, 91): 'data_api_client'}, {}), '(brief, data_api_client)', True, 'import app.main.helpers as helpers\n'), ((17, 23, 17, 77), 'dmtestutils.api_model_stubs.LotStub', 'LotStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((19, 53, 23, 9), 'dmtestutils.api_model_stubs.FrameworkStub', 'FrameworkStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((81, 16, 81, 106), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((95, 16, 95, 106), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((107, 16, 107, 106), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((113, 16, 113, 38), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((138, 19, 138, 93), 'app.main.helpers.buyers_helpers.section_has_at_least_one_required_question', 'helpers.buyers_helpers.section_has_at_least_one_required_question', ({(138, 85, 138, 92): 'section'}, {}), '(section)', True, 'import app.main.helpers as helpers\n'), ((118, 58, 118, 83), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((119, 58, 119, 82), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((122, 57, 122, 86), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((123, 57, 123, 81), 'dmtestutils.api_model_stubs.BriefStub', 'BriefStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((41, 16, 41, 70), 'dmtestutils.api_model_stubs.LotStub', 'LotStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n'), ((59, 16, 59, 71), 'dmtestutils.api_model_stubs.LotStub', 'LotStub', (), '', False, 'from dmtestutils.api_model_stubs import BriefStub, FrameworkStub, LotStub\n')]