import enum
from datetime import datetime
from backend.app.db.base import Base
from sqlalchemy import Column, Integer, BigInteger, Text, Float, DateTime, Boolean, Date, ForeignKey
from sqlalchemy.dialects.postgresql import ENUM as PgEnum


class EnergyAssessment(Base):
    __tablename__ = 'energy_assessments'
    id = Column(BigInteger, primary_key=True, autoincrement=True)
    uprn = Column(BigInteger, nullable=False)
    uprn_source = Column(Text, nullable=False)
    property_type = Column(Text, nullable=False)
    building_reference_number = Column(Text)
    current_energy_efficiency = Column(Text, nullable=False)
    current_energy_rating = Column(Text, nullable=False)
    address1 = Column(Text, nullable=False)
    address2 = Column(Text, nullable=False)
    address3 = Column(Text)
    posttown = Column(Text, nullable=False)
    postcode = Column(Text, nullable=False)
    address = Column(Text, nullable=False)
    county = Column(Text)
    constituency = Column(Text)
    constituency_label = Column(Text)
    low_energy_fixed_light_count = Column(Text, nullable=False)
    construction_age_band = Column(Text, nullable=False)
    mainheat_energy_eff = Column(Text, nullable=False)
    windows_env_eff = Column(Text, nullable=False)
    lighting_energy_eff = Column(Text, nullable=False)
    environment_impact_potential = Column(Text, nullable=False)
    mainheatcont_description = Column(Text, nullable=False)
    sheating_energy_eff = Column(Text, nullable=False)
    local_authority = Column(Text, nullable=False)
    local_authority_label = Column(Text, nullable=False)
    fixed_lighting_outlets_count = Column(Text, nullable=False)
    energy_tariff = Column(Text, nullable=False)
    mechanical_ventilation = Column(Text, nullable=False)
    solar_water_heating_flag = Column(Text, nullable=False)
    co2_emissions_potential = Column(Text, nullable=False)
    number_heated_rooms = Column(Text, nullable=False)
    floor_description = Column(Text, nullable=False)
    energy_consumption_potential = Column(Text, nullable=False)
    built_form = Column(Text, nullable=False)
    number_open_fireplaces = Column(Text, nullable=False)
    windows_description = Column(Text, nullable=False)
    glazed_area = Column(Text, nullable=False)
    inspection_date = Column(DateTime(timezone=True), nullable=False)
    mains_gas_flag = Column(Text, nullable=False)
    co2_emiss_curr_per_floor_area = Column(Text, nullable=False)
    heat_loss_corridor = Column(Text, nullable=False)
    unheated_corridor_length = Column(Text)
    flat_storey_count = Column(Text)
    roof_energy_eff = Column(Text, nullable=False)
    total_floor_area = Column(Text, nullable=False)
    environment_impact_current = Column(Text, nullable=False)
    roof_description = Column(Text, nullable=False)
    floor_energy_eff = Column(Text, nullable=False)
    number_habitable_rooms = Column(Text, nullable=False)
    hot_water_env_eff = Column(Text, nullable=False)
    mainheatc_energy_eff = Column(Text, nullable=False)
    main_fuel = Column(Text, nullable=False)
    lighting_env_eff = Column(Text, nullable=False)
    windows_energy_eff = Column(Text, nullable=False)
    floor_env_eff = Column(Text, nullable=False)
    sheating_env_eff = Column(Text, nullable=False)
    lighting_description = Column(Text, nullable=False)
    roof_env_eff = Column(Text, nullable=False)
    walls_energy_eff = Column(Text, nullable=False)
    photo_supply = Column(Text, nullable=False)
    lighting_cost_potential = Column(Text, nullable=False)
    mainheat_env_eff = Column(Text, nullable=False)
    multi_glaze_proportion = Column(Text, nullable=False)
    main_heating_controls = Column(Text, nullable=False)
    flat_top_storey = Column(Text)
    secondheat_description = Column(Text, nullable=False)
    walls_env_eff = Column(Text, nullable=False)
    transaction_type = Column(Text, nullable=False)
    extension_count = Column(Text, nullable=False)
    mainheatc_env_eff = Column(Text, nullable=False)
    lmk_key = Column(Text)
    wind_turbine_count = Column(Text, nullable=False)
    tenure = Column(Text, nullable=False)
    floor_level = Column(Text, nullable=False)
    potential_energy_efficiency = Column(Text, nullable=False)
    potential_energy_rating = Column(Text, nullable=False)
    hot_water_energy_eff = Column(Text, nullable=False)
    low_energy_lighting = Column(Text, nullable=False)
    walls_description = Column(Text, nullable=False)
    hotwater_description = Column(Text, nullable=False)
    co2_emissions_current = Column(Text, nullable=False)
    heating_cost_current = Column(Text, nullable=False)
    heating_cost_potential = Column(Text, nullable=False)
    hot_water_cost_current = Column(Text, nullable=False)
    hot_water_cost_potential = Column(Text, nullable=False)
    lighting_cost_current = Column(Text, nullable=False)
    energy_consumption_current = Column(Text, nullable=False)
    lodgement_date = Column(Date, nullable=False)
    lodgement_datetime = Column(DateTime(timezone=False), nullable=False)
    mainheat_description = Column(Text, nullable=False)
    floor_height = Column(Float, nullable=False)
    glazed_type = Column(Text, nullable=False)
    file_location = Column(Text, nullable=False)
    surveyor_name = Column(Text, nullable=False)
    surveyor_company = Column(Text, nullable=False)
    space_heating_kwh = Column(Text, nullable=False)
    water_heating_kwh = Column(Text, nullable=False)
    number_of_doors = Column(Integer, nullable=False)
    number_of_insulated_doors = Column(Integer, nullable=False)
    number_of_floors = Column(Integer, nullable=False)
    insulation_wall_area = Column(Float, nullable=False)
    heat_loss_perimeter = Column(Float, nullable=False)
    party_wall_length = Column(Float, nullable=False)
    perimeter = Column(Float, nullable=False)
    rooms_with_bath_and_or_shower = Column(Integer)
    rooms_with_mixer_shower_no_bath = Column(Integer)
    room_with_bath_and_mixer_shower = Column(Integer)
    percent_draftproofed = Column(Integer)
    has_hot_water_cylinder = Column(Boolean)
    cylinder_insulation_type = Column(Text)
    cylinder_insulation_thickness = Column(Integer)
    cylinder_thermostat = Column(Boolean)
    main_dwelling_ground_floor_area = Column(Float)
    number_of_windows = Column(Integer)
    windows_area = Column(Float)

    EPC_KEYS = [
        'low_energy_fixed_light_count', 'address', 'uprn_source', 'floor_height', 'heating_cost_potential',
        'unheated_corridor_length', 'hot_water_cost_potential', 'construction_age_band', 'potential_energy_rating',
        'mainheat_energy_eff', 'windows_env_eff', 'lighting_energy_eff', 'environment_impact_potential', 'glazed_type',
        'heating_cost_current', 'address3', 'mainheatcont_description', 'sheating_energy_eff', 'property_type',
        'local_authority_label', 'fixed_lighting_outlets_count', 'energy_tariff', 'mechanical_ventilation',
        'hot_water_cost_current', 'county', 'postcode', 'solar_water_heating_flag', 'constituency',
        'co2_emissions_potential', 'number_heated_rooms', 'floor_description', 'energy_consumption_potential',
        'local_authority', 'built_form', 'number_open_fireplaces', 'windows_description', 'glazed_area',
        'inspection_date', 'mains_gas_flag', 'co2_emiss_curr_per_floor_area', 'address1', 'heat_loss_corridor',
        'flat_storey_count', 'constituency_label', 'roof_energy_eff', 'total_floor_area', 'building_reference_number',
        'environment_impact_current', 'co2_emissions_current', 'roof_description', 'floor_energy_eff',
        'number_habitable_rooms', 'address2', 'hot_water_env_eff', 'posttown', 'mainheatc_energy_eff', 'main_fuel',
        'lighting_env_eff', 'windows_energy_eff', 'floor_env_eff', 'sheating_env_eff', 'lighting_description',
        'roof_env_eff', 'walls_energy_eff', 'photo_supply', 'lighting_cost_potential', 'mainheat_env_eff',
        'multi_glaze_proportion', 'main_heating_controls', 'lodgement_datetime', 'flat_top_storey',
        'current_energy_rating', 'secondheat_description', 'walls_env_eff', 'transaction_type', 'uprn',
        'current_energy_efficiency', 'energy_consumption_current', 'mainheat_description', 'lighting_cost_current',
        'lodgement_date', 'extension_count', 'mainheatc_env_eff', 'lmk_key', 'wind_turbine_count', 'tenure',
        'floor_level', 'potential_energy_efficiency', 'hot_water_energy_eff', 'low_energy_lighting',
        'walls_description', 'hotwater_description'
    ]

    def to_dict(self):
        """
        Convert the SQLAlchemy object to a dictionary.
        """

        epc = {key.replace("_", "-"): getattr(self, key) for key in self.EPC_KEYS}
        # Get everything else
        condition = {
            column.name: getattr(self, column.name)
            for column in self.__table__.columns if column.name not in self.EPC_KEYS
        }

        return {"epc": epc, "condition": condition}

    @staticmethod
    def empty_response():
        return {"epc": {}, "condition": {}}


class EnergyAssessmentScenarios(Base):
    __tablename__ = 'energy_assessment_scenarios'
    id = Column(BigInteger, primary_key=True, autoincrement=True)
    scenario_name = Column(Text, nullable=False)
    energy_assessment_id = Column(BigInteger, ForeignKey('energy_assessments.id'), nullable=False)


class DocumentTypeEnum(enum.Enum):
    EPR = "EPR"
    ConditionReport = "Condition Report"
    EvidenceReport = "Evidence Report"
    SummaryInformation = "Summary Information"
    FloorPlan = "Floor Plan"
    ScenarioDraftEPC = "Scenario Draft EPC"
    ScenarioSiteNotes = "Scenario Site Notes"


class EnergyAssessmentDocuments(Base):
    __tablename__ = 'energy_assessment_documents'
    id = Column(BigInteger, primary_key=True, autoincrement=True)
    uprn = Column(BigInteger, nullable=False)
    energy_assessment_id = Column(BigInteger, ForeignKey('energy_assessments.id'), nullable=False)
    document_type = Column(PgEnum(DocumentTypeEnum, name="document_type"), nullable=False)
    document_location = Column(Text, nullable=False)
    uploaded_at = Column(DateTime(timezone=True), nullable=False, default=datetime.utcnow)
    scenario_id = Column(BigInteger, ForeignKey('energy_assessment_scenarios.id'), nullable=True)

    @staticmethod
    def empty_response():
        return {
            "id": None,
            "uprn": None,
            "document_type": None,
            "document_location": None,
            "uploaded_at": None,
            "scenario_id": None
        }
