# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2016-2021 Anaconda, Inc.
#
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
# -----------------------------------------------------------------------------
"""Tests for login dialog."""
from qtpy.QtCore import Qt  # analysis:ignore
import pytest
from unittest import mock, TestCase
import pytestqt.qtbot as qtbot  # analysis:ignore

import anaconda_navigator.widgets.dialogs.tests.login.mixins as mixins
skip = pytest.mark.skip


@pytest.mark.usefixtures("main_dialog_bot")
class TestMainLoginDialog(TestCase):
    def test_main_dialog_clicked_login_buttons(self):
        self.qtbot.wait_for_window_shown(self.widget)
        for login_card in (
            self.widget.anaconda_client_login_card, self.widget.commercial_edition_login_card,
            self.widget.enterprise_edition_login_card
        ):

            login_page_mock = mock.Mock()
            login_card.login_page = login_page_mock
            with self.qtbot.wait_signal(self.widget.sig_login_type_clicked, raising=True):
                self.qtbot.mouseClick(login_card.button_login, Qt.LeftButton)


@pytest.mark.usefixtures("commercial_dialog_bot")
class TestCommercialLogin(TestCase):
    @mock.patch('anaconda_navigator.widgets.dialogs.login.token_set')
    def test_set_token(self, token_set_mock):
        self.widget.input_line.setText("TOKEN_MOCK")

        with mock.patch.object(self.widget, 'check_text'), mock.patch.object(self.widget, 'accept'), \
                mock.patch.object(self.widget, 'anaconda_api'), mock.patch.object(self.widget.config, 'set'), \
                self.qtbot.wait_signal(self.widget.button_apply.clicked, raising=True):

            self.widget.check_text.return_value = True
            self.qtbot.mouseClick(self.widget.button_apply, Qt.LeftButton)

            token_set_mock.assert_called_with("TOKEN_MOCK")
            self.widget.accept.assert_called()
            self.widget.check_text.assert_called()
            self.widget.anaconda_api.client_reload.assert_called()
            self.widget.config.set.assert_called()

    @mock.patch('anaconda_navigator.widgets.dialogs.login.token_set')
    def test_set_token_failed(self, token_set_mock):
        with mock.patch.object(self.widget, 'check_text'), mock.patch.object(self.widget, 'accept'), \
                mock.patch.object(self.widget, 'anaconda_api'), mock.patch.object(self.widget.config, 'set'), \
                self.qtbot.wait_signal(self.widget.button_apply.clicked, raising=True):
            self.widget.check_text.return_value = False
            self.qtbot.mouseClick(self.widget.button_apply, Qt.LeftButton)

            self.widget.check_text.assert_called()
            token_set_mock.assert_not_called()
            self.widget.accept.assert_not_called()
            self.widget.anaconda_api.client_reload.assert_not_called()
            self.widget.config.set.assert_not_called()

    @mock.patch('anaconda_navigator.widgets.dialogs.login.validate_token')
    def test_check_text(self, validate_token_mock):
        self.widget.input_line.setText("TOKEN_MOCK")
        self.assertTrue(self.widget.check_text())
        validate_token_mock.assert_called()


@pytest.mark.usefixtures("anaconda_org_dialog_bot")
class TestAnacondaOrgLogin(TestCase, mixins.TestBaseLoginPage):
    pass


@pytest.mark.usefixtures("enterprise_login_page_dialog_bot")
class TestEnterpriseLoginPage(mixins.TestBaseLoginPage, TestCase):
    pass


@pytest.mark.usefixtures("enterprise_domain_set_dialog_bot")
class TestEnterpriseSetDomainPage(mixins.TestBaseSetDomainPage, TestCase):
    pass


@pytest.mark.usefixtures("team_domain_set_dialog_bot")
class TestTeamSetDomainPage(mixins.TestBaseSetDomainPage, TestCase):
    pass


@pytest.mark.usefixtures("team_login_page_dialog_bot")
class TestTeamLoginPage(mixins.TestBaseLoginPage, TestCase):
    @mock.patch('anaconda_navigator.widgets.dialogs.login.TeamEditionAddChannelsPage')
    def test_login_finished(self, channels_page_mock):
        worker, output, error = mock.Mock(), '["token", "refresh_token"]', ""

        with mock.patch.object(self.widget, 'accept'), mock.patch.object(self.widget, 'check_text'):
            self.widget._finished(worker, output, error)
            self.widget.accept.assert_called()
            self.widget.check_text.assert_called()
            channels_page_mock.assert_called()

    def test_login_finished_with_error(self):
        worker, output, error = mock.Mock(), '{"token": "Token", "message": "Unauthorized"}', ""

        with mock.patch.object(self.widget, '_track_error'), mock.patch.object(self.widget, 'check_text'):
            self.widget._finished(worker, output, error)
            self.assertEqual(self.widget.label_message.text(), '<i>Invalid Credentials!</i>')
            self.widget._track_error.assert_called()
            self.widget.check_text.assert_called()

    def test_login_finished_with_exception(self):
        worker, output, error = mock.Mock(), '{BROKEN]', ""

        with mock.patch.object(self.widget, '_track_error'), mock.patch.object(self.widget, 'check_text'):
            self.widget._finished(worker, output, error)
            self.assertEqual(self.widget.label_message.text(), '<i>Unhandled error happened!</i>')
            self.widget._track_error.assert_called()
            self.widget.check_text.assert_called()


@skip
@pytest.mark.usefixtures("team_add_channels_page_dialog_bot")
class TestTeamAddChannelsPage(TestCase):
    def test_skip(self):
        with self.qtbot.wait_signal(self.widget.button_skip.clicked,
                                    raising=True), mock.patch.object(self.widget.anaconda_api, 'create_login_data'
                                                                     ), mock.patch.object(self.widget, 'close_window'):
            self.qtbot.mouseClick(self.widget.button_skip, Qt.LeftButton)
            self.widget.close_window.assert_called()
            self.widget.anaconda_api.create_login_data.assert_called()

    def test_add_channels(self):
        with self.qtbot.wait_signal(self.widget.button_add.clicked, raising=True), mock.patch.object(
                self.widget.anaconda_api, 'create_login_data'), mock.patch.object(self.widget, 'close_window'), \
                mock.patch.object(self.widget.channels_table, 'get_selected_channels'):

            self.widget.channels_table.get_selected_channels.return_value = (['default_channel'], ['channel'])
            self.qtbot.mouseClick(self.widget.button_add, Qt.LeftButton)
            self.widget.close_window.assert_called()
            self.widget.anaconda_api.create_login_data.assert_called()

    def test_add_channels_fallback(self):
        with self.qtbot.wait_signal(self.widget.button_add.clicked, raising=True), mock.patch.object(
                self.widget.anaconda_api, 'create_login_data'), mock.patch.object(self.widget, 'close_window'), \
                mock.patch.object(self.widget.channels_table, 'get_selected_channels'):

            self.widget.channels_table.get_selected_channels.return_value = ([], ['channel'])
            self.qtbot.mouseClick(self.widget.button_add, Qt.LeftButton)
            self.widget.close_window.assert_not_called()
            self.widget.anaconda_api.create_login_data.assert_not_called()
