from dataclasses import dataclass
from datetime import date
from typing import List, Optional


@dataclass
class InspectionMetadata:
    inspection_surveyor: str
    email_address: str
    report_reference: str
    created_on: str
    date_of_inspection: date
    property_address: str
    property_photo: Optional[bool] = None


@dataclass
class General:
    epc_checked_before_assessment: bool
    epc_exists_at_point_of_assessment: bool
    inspection_date: date
    transaction_type: str
    tenure: str
    property_type: str
    detachment_type: str
    number_of_storeys: int
    terrain_type: str
    number_of_extensions: int
    electricity_smart_meter: bool
    electric_meter_type: str
    dwelling_export_capable: bool
    mains_gas_available: bool
    gas_smart_meter: bool
    gas_meter_accessible: bool
    measurements_location: str


@dataclass
class MainBuildingConstruction:
    age_range: str
    age_indicators: str
    walls_construction_type: str
    cavity_construction_indicators: str
    walls_insulation_type: str
    thermal_conductivity_of_wall_insulation: str
    wall_u_value_known: bool
    wall_thickness_mm: Optional[int]
    party_wall_construction_type: str
    filled_cavity_indicators: Optional[str] = None


@dataclass
class ExtensionConstruction:
    id: int
    age_range: str
    age_indicators: str
    walls_construction_type: str
    cavity_construction_indicators: str
    walls_insulation_type: str
    thermal_conductivity_of_wall_insulation: str
    wall_u_value_known: bool
    wall_thickness_mm: Optional[int]
    party_wall_construction_type: str
    filled_cavity_indicators: Optional[str] = None


@dataclass
class FloorConstruction:
    floor_type: str
    floor_construction: str
    floor_insulation_type: str
    floor_u_value_known: bool


@dataclass
class BuildingConstruction:
    main_building: MainBuildingConstruction
    floor: FloorConstruction
    extensions: Optional[List[ExtensionConstruction]] = None


@dataclass
class FloorMeasurement:
    name: str
    area_m2: float
    height_m: float
    heat_loss_perimeter_m: float
    pwl_m: float


@dataclass
class MainBuildingMeasurements:
    floors: List[FloorMeasurement]


@dataclass
class ExtensionMeasurements:
    id: int
    floors: List[FloorMeasurement]


@dataclass
class BuildingMeasurements:
    main_building: MainBuildingMeasurements
    extensions: Optional[List[ExtensionMeasurements]] = None


@dataclass
class RoofSpaceDetail:
    construction_type: str
    insulation_at: str
    roof_u_value_known: bool
    cavity_wall_construction_indicators: str
    rooms_in_roof: bool
    # Numeric thickness (mm) when known; string (e.g. "As built") when not measured
    insulation_thickness_mm: Optional[int] = None
    insulation_thickness: Optional[str] = None


@dataclass
class ExtensionRoofSpace:
    id: int
    construction_type: str
    insulation_at: str
    roof_u_value_known: bool
    cavity_wall_construction_indicators: str
    rooms_in_roof: bool
    insulation_thickness_mm: Optional[int] = None
    insulation_thickness: Optional[str] = None


@dataclass
class RoofSpace:
    main_building: RoofSpaceDetail
    extensions: Optional[List[ExtensionRoofSpace]] = None


@dataclass
class Window:
    id: int
    location: str
    wall_type: str
    glazing_type: str
    window_type: str
    frame_type: str
    glazing_gap: str
    draught_proofed: bool
    permanent_shutters: bool
    height_m: float
    width_m: float
    orientation: str


@dataclass
class MainHeating:
    selection_method: str
    system_type: str
    product_id: int
    manufacturer: str
    model: str
    orig_manufacturer: str
    fuel: str
    summer_efficiency: float
    type: str
    condensing: bool
    year: str
    mount: str
    open_flue: str
    fan_assist: bool
    status: str
    central_heating_pump_age: str
    controls: str
    flue_gas_heat_recovery_system: bool
    weather_compensator: bool
    emitter: str
    emitter_temperature: str


@dataclass
class SecondaryHeating:
    secondary_fuel: str
    secondary_system: Optional[str] = None


@dataclass
class WaterHeating:
    type: str
    system: str
    cylinder_size: str
    cylinder_measured_heat_loss: Optional[str] = None
    insulation_type: Optional[str] = None
    insulation_thickness_mm: Optional[int] = None
    has_thermostat: Optional[bool] = None
    immersion_type: Optional[str] = None


@dataclass
class HeatingAndHotWater:
    main_heating: MainHeating
    secondary_heating: SecondaryHeating
    water_heating: WaterHeating


@dataclass
class Ventilation:
    ventilation_type: str
    has_fixed_air_conditioning: bool
    number_of_open_flues: int
    number_of_closed_flues: int
    number_of_boiler_flues: int
    number_of_other_flues: int
    number_of_extract_fans: int
    number_of_passive_vents: int
    number_of_flueless_gas_fires: int
    pressure_test: str
    draught_lobby: bool
    ventilation_in_pcdf_database: Optional[bool] = None


@dataclass
class Conservatories:
    has_conservatory: bool


@dataclass
class Renewables:
    wind_turbines: bool
    solar_hot_water: bool
    photovoltaic_array: bool
    number_of_pv_batteries: int
    hydro: bool
    pv_connection: Optional[str] = None
    percent_roof_covered_pv: Optional[int] = None


@dataclass
class RoomCountElements:
    number_of_habitable_rooms: int
    any_unheated_rooms: bool
    number_of_external_doors: int
    number_of_insulated_external_doors: int
    number_of_draughtproofed_external_doors: int
    number_of_open_chimneys: int
    number_of_blocked_chimneys: int
    number_of_fixed_incandescent_bulbs: int
    exact_led_cfl_count_known: bool
    number_of_fixed_led_bulbs: int
    number_of_fixed_cfl_bulbs: int
    waste_water_heat_recovery: str
    number_of_heated_rooms: Optional[int] = None


@dataclass
class Shower:
    id: int
    outlet_type: str


@dataclass
class WaterUse:
    number_of_baths: int
    number_of_special_features: int
    showers: List[Shower]


@dataclass
class CustomerResponse:
    customer_present: bool
    willing_to_answer_satisfaction_survey: bool


@dataclass
class SurveyAddendum:
    addendum: str
    related_party_disclosure: str
    hard_to_treat_cavity_access_issues: bool
    hard_to_treat_cavity_high_exposure: bool
    hard_to_treat_cavity_narrow_cavities: bool


@dataclass
class PasHubRdSapSiteNotes:
    inspection_metadata: InspectionMetadata
    general: General
    building_construction: BuildingConstruction
    building_measurements: BuildingMeasurements
    roof_space: RoofSpace
    windows: List[Window]
    heating_and_hot_water: HeatingAndHotWater
    ventilation: Ventilation
    conservatories: Conservatories
    renewables: Renewables
    room_count_elements: RoomCountElements
    water_use: WaterUse
    customer_response: CustomerResponse
    addendum: SurveyAddendum
