import os
import unittest

import mockredis
from splinter import Browser

from helix import main
from helix.constants import redis_constant
from helix.constants import sql_constant
from helix.constants.anchor_type import AnchorType
from helix.constants.inverter_type import InverterType
from helix.constants.system_type import SystemType
from helix.constants.module_type import ModuleType
from helix.constants.version import version
from helix.models.sql.power_stations import PowerStation
from test.integration.integration_test_helpers import *
from test.test_helpers import test_db_session, reset_db_session


class FullUserFlowTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.test_db_session = test_db_session()

    @classmethod
    def tearDownClass(cls):
        cls.test_db_session.close_all()

    def setUp(self):
        redis_constant.redis_store = mockredis.mock_redis_client()
        sql_constant.sql_session_maker = lambda: self.test_db_session

        self.app = main.app.test_client()
        self.browser = Browser('flask', app=main.app)
        self.browser.visit('/site_characterization/')

    def tearDown(self):
        reset_db_session(self.test_db_session)

    def fill_in_site_characterization_data(self):
        self.browser.fill('project_name', 'Test Project Name')
        self.browser.fill('building_width', '200')
        self.browser.fill('building_height', '30')
        self.browser.fill('building_length', '75.5')
        self.browser.fill('wind_speed', '125')
        self.browser.fill('exposure_category', 'C')
        self.browser.fill('ballast_block_weight', '13')
        self.browser.fill('building_parapet_height', '0')
        self.browser.fill('max_system_pressure', '10')
        self.browser.fill('system_type', SystemType.singleTilt.value)
        self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
        self.browser.fill('design_spectral_response', '1')

    def attach_file(self, file):
        self.browser.visit('/array_summary/')
        self.browser.attach_file('file_upload', file)

    def attach_dxf(self, dxf_file):
        self.browser.visit('/array_summary/')
        self.browser.attach_file('dxf_upload', dxf_file)

    def advance_n_times(self, advance_count):
        for _ in range(advance_count):
            self.browser.find_by_value('Next').first.click()

    def test_uploading_and_downloading_dual_tilt_csv(self):
        """
        This is using data from an old-style file but works because
        the old spacing is within the new spacing's variance tolerance
        """

        with open('test/fixtures/expected_dual_tilt.csv', 'r', newline='') as csv_file:
            csv_content = csv_file.read()
        self.browser.fill('project_name', 'Test Project Name')
        self.browser.fill('building_width', '1000')
        self.browser.fill('building_height', '100')
        self.browser.fill('building_length', '1500')
        self.browser.fill('wind_speed', '110')
        self.browser.fill('exposure_category', 'D')
        self.browser.fill('ballast_block_weight', '20')
        self.browser.fill('building_parapet_height', '0')
        self.browser.fill('max_system_pressure', '17')
        self.browser.fill('system_type', SystemType.dualTilt.value)
        self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
        self.browser.fill('design_spectral_response', '1')

        self.advance_n_times(1)
        self.attach_file('test/fixtures/input_dual_tilt.csv')

        self.advance_n_times(3)
        self.browser.click_link_by_partial_text('Download AutoCAD import file')
        eq_(self.browser.html, csv_content)
        eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')

    def test_clicking_back_at_download_goes_to_power_station_configuration(self):
        self.browser.visit('/download/')

        assert not self.browser.is_text_present('Next')
        assert self.browser.is_text_present('Back')

        self.browser.click_link_by_partial_text('Back')
        assert_step_is_active(self.browser, 4)

    def test_uploading_and_downloading_single_tilt_csv(self):
        with open('test/fixtures/expected_single_tilt.csv', 'r', newline='') as csv_file:
            csv_content = csv_file.read()
        self.browser.fill('project_name', 'Test Project Name')
        self.browser.fill('building_width', '1000')
        self.browser.fill('building_height', '100')
        self.browser.fill('building_length', '1500')
        self.browser.fill('wind_speed', '110')
        self.browser.fill('exposure_category', 'D')
        self.browser.fill('ballast_block_weight', '20')
        self.browser.fill('building_parapet_height', '0')
        self.browser.fill('max_system_pressure', '17')
        self.browser.fill('system_type', SystemType.singleTilt.value)
        self.browser.fill('anchor_type', AnchorType.EcoFasten.value)
        self.browser.fill('design_spectral_response', '1')

        self.advance_n_times(1)
        self.attach_file('test/fixtures/input_single_tilt.csv')

        self.advance_n_times(3)
        self.browser.click_link_by_partial_text('Download AutoCAD import file')
        eq_(self.browser.html, csv_content)
        eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')

    def test_downloading_coordinates_csv(self):
            #with open('test/fixtures/expected_dual_tilt_big_spacing.txt', 'r', newline='') as csv_file:
            with open('test/fixtures/expected_small_dual_tilt.txt', 'r', newline='') as csv_file:
                csv_content = csv_file.read()
            self.browser.fill('project_name', 'Test Project Name')
            self.browser.fill('building_width', '450')
            self.browser.fill('building_height', '35')
            self.browser.fill('building_length', '500')
            self.browser.fill('wind_speed', '110')
            self.browser.fill('exposure_category', 'B')
            self.browser.fill('ballast_block_weight', '14')
            self.browser.fill('building_parapet_height', '5')
            self.browser.fill('max_system_pressure', '10')
            self.browser.fill('system_type', SystemType.dualTilt.value)
            self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip_Plus.value)
            self.browser.fill('design_spectral_response', '1.5')
            self.browser.fill('module_type', ModuleType.Cell96.value)

            self.advance_n_times(1)
            self.attach_file('test/fixtures/input_small_dual_tilt.csv')

            self.advance_n_times(1)
            self.browser.visit('/download/')
            self.browser.click_link_by_partial_text('Download AutoCAD import file')
            print("===")
            print(self.browser.html)
            eq_(self.browser.html, csv_content)
            eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')


#     def test_uploading_dxf_and_downloading_csv(self):
#         self.browser.fill('project_name', 'Test Project Name')
#         self.browser.fill('building_width', '100')
#         self.browser.fill('building_height', '30')
#         self.browser.fill('building_length', '100')
#         self.browser.fill('building_parapet_height', '5')
#         self.browser.fill('wind_speed', '130')
#         self.browser.fill('exposure_category', 'C')
#         self.browser.fill('ballast_block_weight', '14')
#         self.browser.fill('max_system_pressure', '12')
#         self.browser.fill('system_type', SystemType.dualTilt.value)
#         self.browser.fill('anchor_type', AnchorType.OMG_PowerGrip_Plus.value)
#         self.browser.fill('design_spectral_response', '0.5')
# 
#         self.advance_n_times(1)
#         self.attach_dxf('test/fixtures/dxf/input_dual_tilt_96_cell.dxf')
# 
#         self.advance_n_times(1)
#         self.browser.visit('/download/')
#         self.browser.click_link_by_partial_text('Download AutoCAD import file')
#         assert self.browser.html != ''
#         eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_result.txt')

    def test_downloading_documentation(self):
        self.fill_in_site_characterization_data()

        self.advance_n_times(1)
        self.attach_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
        self.advance_n_times(3)
        os.environ['SP_DOCGEN_API_KEY'] = 'DC97-20AF-567E'
        self.browser.click_link_by_partial_text('Download Project Report')
        os.environ['SP_DOCGEN_API_KEY'] = ''

        # with open('test/fixtures/expected_single_tilt_documentation.pdf', 'r', newline='') as pdf_file:
        #     expected_doc = pdf_file.read()
        #
        # eq_(self.browser.html, expected_doc)
        eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_documentation.pdf')

    def test_downloading_BOM_dual_tilt(self):
        assert len(self.browser.find_by_text('Download BOM')) == 0
        self.fill_in_site_characterization_data()
        self.browser.fill('system_type', SystemType.dualTilt.value)

        self.advance_n_times(1)
        self.attach_file('test/fixtures/input_dual_tilt_csv_for_bom.csv')
        self.advance_n_times(3)

        self.browser.click_link_by_partial_text('Download BOM')

        with open('test/fixtures/expected_dual_tilt_bom.csv', 'r', newline='') as csv_file:
            expected_bom = csv_file.read()

        eq_(self.browser.html, expected_bom)
        eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_bom.txt')

    def test_downloading_BOM_single_tilt(self):
        assert len(self.browser.find_by_text('Download BOM')) == 0
        self.fill_in_site_characterization_data()
        self.advance_n_times(1)
        self.attach_file('test/fixtures/input_single_tilt_csv_for_bom.csv')
        self.advance_n_times(2)

        fill_in_power_station(self.browser, name='Test Power Station Name', count=1, inverter_count=3,
                              inverters=[
                                  {
                                      'model': InverterType.SMA.MODEL_15KW,
                                      'strings': 3,
                                      'sunshade': True,
                                      'dc_switch': True
                                  },
                                  {
                                      'model': InverterType.SMA.MODEL_12KW,
                                      'sunshade': True,
                                      'dc_switch': True,
                                      'strings': 4
                                  },
                                  {
                                      'model': InverterType.SMA.MODEL_24KW,
                                      'sunshade': True,
                                      'dc_switch': True,
                                      'strings': 7
                                  }
                              ])
        submit_power_station_form(self.browser)
        first_power_station_id = str(self.test_db_session.query(PowerStation).first().id)

        fill_in_power_station(self.browser, count=5, inverter_count=2,
                              inverters=[
                                  {
                                    'model': InverterType.SMA.MODEL_24KW,
                                    'strings': 8,
                                  },
                                  {
                                      'model': InverterType.SMA.MODEL_12KW,
                                      'strings': 2
                                  }
                              ])
        submit_power_station_form(self.browser)

        fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_15KW, sunshade=True, dc_switch=True, strings=3)
        submit_standalone_inverter_form(self.browser)
        fill_in_standalone_inverter(self.browser, model=InverterType.SMA.MODEL_15KW, sunshade=True, dc_switch=True, strings=3)
        self.browser.fill('attachment_point', first_power_station_id)
        submit_standalone_inverter_form(self.browser)

        self.advance_n_times(1)
        self.browser.click_link_by_partial_text('Download BOM')

        with open('test/fixtures/expected_single_tilt_bom.csv', 'r', newline='') as csv_file:
            expected_bom = csv_file.read()

        eq_(self.browser.html, expected_bom)
        eq_(self.browser._response.headers['Content-Disposition'], 'attachment; filename=test_project_name_bom.txt')
