import json
import os

from django.test import LiveServerTestCase
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

from core.models import UserAccount
from functional_tests.util import login, create_browser, reset_browser_after_test
from util import factory_boys as fact


def expect_file_to_be_present(path):
    def condition(*args):
        try:
            with open(path):
                pass
        except FileNotFoundError:
            return False
        return True
    return condition


JSON_EXPORT_FILE = os.path.join(os.path.dirname(__file__), 'export.json')


class ExportTestModal(LiveServerTestCase):
    browser: webdriver.Firefox = None
    username = None
    password = None
    role = None

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.browser = create_browser()

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        cls.browser.quit()

    def setUp(self):
        self.username = 'reviewer'
        self.password = 'p'
        self.role = UserAccount.REVIEWER
        fact.UserAccountFactory(
            username=self.username,
            password=self.password,
            role=self.role
        )

    def tearDown(self):
        reset_browser_after_test(self.browser, self.live_server_url)

    def _login(self):
        login(self.browser, self.live_server_url, self.username, self.password)

    def test_export_red_uncorrected_submissions(self):
        def export_btn_is_red(*args):
            exports_btn = self.browser.find_element_by_id('export-btn')
            return 'red' in exports_btn.get_attribute('class')

        fact.SubmissionFactory()
        self._login()
        WebDriverWait(self.browser, 10).until(export_btn_is_red)

    def test_export_warning_tooltip_uncorrected_submissions(self):
        fact.SubmissionFactory()
        self._login()
        tooltip_uncorrected = self.browser.find_element_by_id('uncorrected-tooltip')
        self.assertNotEqual(None, tooltip_uncorrected)
        self.assertRaises(Exception, self.browser.find_element_by_id, 'corrected-tooltip')

    def test_export_green_all_corrected(self):
        self._login()
        exports_btn = self.browser.find_element_by_id('export-btn')
        self.assertIn('green', exports_btn.get_attribute('class'))

    def test_export_all_good_tooltip_all_corrected(self):
        self._login()
        tooltip_corrected = self.browser.find_element_by_id('corrected-tooltip')
        self.assertNotEqual(None, tooltip_corrected)
        self.assertRaises(Exception, self.browser.find_element_by_id, 'uncorrected-tooltip')

    def test_export_list_popup_contains_correct_items(self):
        self._login()
        export_btn = self.browser.find_element_by_id('export-btn')
        export_btn.click()
        export_menu = self.browser.find_element_by_class_name('menuable__content__active')
        export_list = export_menu.find_element_by_class_name('v-list')
        list_elements = export_list.find_elements_by_tag_name('div')
        self.assertEqual(2, len(list_elements))
        self.assertEqual('Export student scores',
                         list_elements[0].find_element_by_tag_name('a').text)
        self.assertEqual('Export whole instance data',
                         list_elements[1].find_element_by_tag_name('a').text)

    def test_export_student_scores_as_json(self):
        self._login()
        fact.StudentInfoFactory()
        export_btn = self.browser.find_element_by_id('export-btn')
        export_btn.click()
        export_scores = self.browser.find_element_by_id('export-list0')
        export_scores.click()
        data_export_modal = self.browser.find_element_by_id('data-export-modal')
        export_type_select = data_export_modal.find_element_by_id('type-select')
        export_type_select.click()
        export_type_json = data_export_modal.find_element_by_xpath("//*[contains(text(), 'json')]")
        export_type_json.click()
        data_export_btn = data_export_modal.find_element_by_id('export-data-download-btn')
        data_export_btn.click()
        WebDriverWait(self.browser, 10).until(expect_file_to_be_present(JSON_EXPORT_FILE))
        with open(JSON_EXPORT_FILE) as f:
            data = json.load(f)
        self.assertEqual('B.Inf.4242 Test Module', data[0]['Exam'])
        os.remove(JSON_EXPORT_FILE)

    def test_export_instance(self):
        self._login()
        fact.SubmissionFactory()
        self.browser.find_element_by_id('export-btn').click()
        self.browser.find_element_by_id('export-list1').click()
        instance_export_modal = self.browser.find_element_by_id('instance-export-modal')
        instance_export_modal.find_element_by_id('instance-export-dl').click()
        WebDriverWait(self.browser, 10).until(expect_file_to_be_present(JSON_EXPORT_FILE))
        with open(JSON_EXPORT_FILE) as f:
            data = json.load(f)
        self.assertEqual('B.Inf.4242 Test Module', data['examTypes'][0]['moduleReference'])
        os.remove(JSON_EXPORT_FILE)