import json
import os
from datetime import date
from typing import Any, Dict

import pytest

from datatypes.epc.domain.epc_property_data import (
    EpcPropertyData,
    InstantaneousWwhrs,
    MainHeatingDetail,
    SapBuildingPart,
    SapEnergySource,
    SapFloorDimension,
    SapHeating,
    SapVentilation,
    SapWindow,
    ShowerOutlet,
    ShowerOutlets,
)
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
from datatypes.epc.schema.tests.helpers import from_dict
from datatypes.epc.surveys.pashub_rdsap_site_notes import PasHubRdSapSiteNotes

FIXTURES = os.path.join(
    os.path.dirname(__file__),
    "../../surveys/tests/fixtures",
)


def load(filename: str) -> Dict[str, Any]:
    with open(os.path.join(FIXTURES, filename)) as f:
        return json.load(f)  # type: ignore[no-any-return]


class TestFromSiteNotesExample1:
    """
    Fixture: pashub_rdsap_site_notes_example1.json
    No extensions, regular boiler with cylinder, natural ventilation.
    """

    @pytest.fixture
    def survey(self) -> PasHubRdSapSiteNotes:
        return from_dict(
            PasHubRdSapSiteNotes, load("pashub_rdsap_site_notes_example1.json")
        )

    @pytest.fixture
    def result(self, survey: PasHubRdSapSiteNotes) -> EpcPropertyData:
        return EpcPropertyDataMapper.from_site_notes(survey)

    # --- property details ---

    def test_dwelling_type(self, result: EpcPropertyData) -> None:
        # general.property_type + general.detachment_type → "Mid-terrace house"
        assert result.dwelling_type == "Mid-terrace house"

    def test_tenure(self, result: EpcPropertyData) -> None:
        # general.tenure: "Rented Social"
        assert result.tenure == "Rented Social"

    def test_transaction_type(self, result: EpcPropertyData) -> None:
        # general.transaction_type: "None of the Above"
        assert result.transaction_type == "None of the Above"

    def test_inspection_date(self, result: EpcPropertyData) -> None:
        # general.inspection_date: "2026-03-31"
        assert result.inspection_date == date(2026, 3, 31)

    def test_built_form(self, result: EpcPropertyData) -> None:
        # general.detachment_type: "Mid-terrace"
        assert result.built_form == "Mid-terrace"

    def test_property_type(self, result: EpcPropertyData) -> None:
        # general.property_type: "House"
        assert result.property_type == "House"

    # --- energy elements are not available from site notes ---

    def test_roofs_empty(self, result: EpcPropertyData) -> None:
        assert result.roofs == []

    def test_walls_empty(self, result: EpcPropertyData) -> None:
        assert result.walls == []

    def test_floors_empty(self, result: EpcPropertyData) -> None:
        assert result.floors == []

    def test_main_heating_elements_empty(self, result: EpcPropertyData) -> None:
        assert result.main_heating == []

    def test_window_element_absent(self, result: EpcPropertyData) -> None:
        assert result.window is None

    def test_lighting_element_absent(self, result: EpcPropertyData) -> None:
        assert result.lighting is None

    def test_hot_water_element_absent(self, result: EpcPropertyData) -> None:
        assert result.hot_water is None

    # --- energy source ---

    def test_mains_gas_available(self, result: EpcPropertyData) -> None:
        # general.mains_gas_available: true
        assert result.sap_energy_source.mains_gas is True

    def test_electricity_smart_meter(self, result: EpcPropertyData) -> None:
        # general.electricity_smart_meter: true
        assert result.sap_energy_source.electricity_smart_meter_present is True

    def test_gas_smart_meter(self, result: EpcPropertyData) -> None:
        # general.gas_smart_meter: true
        assert result.sap_energy_source.gas_smart_meter_present is True

    def test_meter_type(self, result: EpcPropertyData) -> None:
        # general.electric_meter_type: "Single"
        assert result.sap_energy_source.meter_type == "Single"

    def test_dwelling_export_capable(self, result: EpcPropertyData) -> None:
        # general.dwelling_export_capable: true
        assert result.sap_energy_source.is_dwelling_export_capable is True

    def test_wind_turbines_terrain_type(self, result: EpcPropertyData) -> None:
        # general.terrain_type: "Suburban"
        assert result.sap_energy_source.wind_turbines_terrain_type == "Suburban"

    def test_no_wind_turbines(self, result: EpcPropertyData) -> None:
        # renewables.wind_turbines: false → count 0
        assert result.sap_energy_source.wind_turbines_count == 0

    def test_no_pv_batteries(self, result: EpcPropertyData) -> None:
        # renewables.number_of_pv_batteries: 0
        assert result.sap_energy_source.pv_battery_count == 0

    # --- renewables ---

    def test_no_solar_hot_water(self, result: EpcPropertyData) -> None:
        # renewables.solar_hot_water: false
        assert result.solar_water_heating is False

    # --- ventilation ---

    def test_no_fixed_air_conditioning(self, result: EpcPropertyData) -> None:
        # ventilation.has_fixed_air_conditioning: false
        assert result.has_fixed_air_conditioning is False

    # --- conservatory ---

    def test_no_conservatory(self, result: EpcPropertyData) -> None:
        # conservatories.has_conservatory: false
        assert result.has_conservatory is False

    # --- hot water / cylinder ---

    def test_has_hot_water_cylinder(self, result: EpcPropertyData) -> None:
        # water_heating.cylinder_size is present → cylinder exists
        assert result.has_hot_water_cylinder is True

    # --- main heating ---

    def test_main_heating_fuel(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.fuel: "Mains gas"
        assert result.sap_heating.main_heating_details[0].main_fuel_type == "Mains gas"

    def test_main_heating_emitter(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.emitter: "Radiators"
        assert (
            result.sap_heating.main_heating_details[0].heat_emitter_type == "Radiators"
        )

    def test_main_heating_no_fghrs(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.flue_gas_heat_recovery_system: false
        assert result.sap_heating.main_heating_details[0].has_fghrs is False

    def test_main_heating_fan_flue_present(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.fan_assist: true
        assert result.sap_heating.main_heating_details[0].fan_flue_present is True

    def test_no_secondary_heating(self, result: EpcPropertyData) -> None:
        # secondary_heating.secondary_fuel: "No Secondary Heating" → no secondary fuel type
        assert result.sap_heating.secondary_fuel_type is None

    # --- windows ---

    def test_window_count(self, result: EpcPropertyData) -> None:
        # 4 windows in fixture
        assert len(result.sap_windows) == 4

    def test_window_height(self, result: EpcPropertyData) -> None:
        assert result.sap_windows[0].window_height == 1.36

    def test_window_width(self, result: EpcPropertyData) -> None:
        assert result.sap_windows[0].window_width == 1.0

    def test_window_draught_proofed(self, result: EpcPropertyData) -> None:
        # windows[0].draught_proofed: true
        assert result.sap_windows[0].draught_proofed is True

    def test_window_orientation(self, result: EpcPropertyData) -> None:
        assert result.sap_windows[0].orientation == "South East"

    def test_window_glazing_type(self, result: EpcPropertyData) -> None:
        assert (
            result.sap_windows[0].glazing_type == "Double glazing, Unknown install date"
        )

    # --- building parts ---

    def test_building_parts_count(self, result: EpcPropertyData) -> None:
        # no extensions → one building part for main building
        assert len(result.sap_building_parts) == 1

    def test_building_part_identifier(self, result: EpcPropertyData) -> None:
        assert result.sap_building_parts[0].identifier == "main"

    def test_construction_age_band(self, result: EpcPropertyData) -> None:
        # main_building.age_range: "I: 1996 - 2002" → letter "I"
        assert result.sap_building_parts[0].construction_age_band == "I"

    def test_wall_construction(self, result: EpcPropertyData) -> None:
        # main_building.walls_construction_type: "Cavity"
        assert result.sap_building_parts[0].wall_construction == "Cavity"

    def test_wall_insulation_type(self, result: EpcPropertyData) -> None:
        # main_building.walls_insulation_type: "As built"
        assert result.sap_building_parts[0].wall_insulation_type == "As built"

    def test_wall_thickness_measured(self, result: EpcPropertyData) -> None:
        # main_building.wall_thickness_mm: 280 → thickness was measured
        assert result.sap_building_parts[0].wall_thickness_measured is True

    def test_wall_thickness_mm(self, result: EpcPropertyData) -> None:
        assert result.sap_building_parts[0].wall_thickness_mm == 280

    # --- floor dimensions ---

    def test_floor_count(self, result: EpcPropertyData) -> None:
        # 2 floors in main building
        assert len(result.sap_building_parts[0].sap_floor_dimensions) == 2

    def test_floor_area(self, result: EpcPropertyData) -> None:
        # building_measurements.main_building.floors[0].area_m2: 24.78
        assert (
            result.sap_building_parts[0].sap_floor_dimensions[0].total_floor_area_m2
            == 24.78
        )

    def test_floor_height(self, result: EpcPropertyData) -> None:
        # floors[0].height_m: 2.37
        assert (
            result.sap_building_parts[0].sap_floor_dimensions[0].room_height_m == 2.37
        )

    def test_heat_loss_perimeter(self, result: EpcPropertyData) -> None:
        # floors[0].heat_loss_perimeter_m: 14.21
        assert (
            result.sap_building_parts[0].sap_floor_dimensions[0].heat_loss_perimeter_m
            == 14.21
        )

    def test_party_wall_length(self, result: EpcPropertyData) -> None:
        # floors[0].pwl_m: 6.15
        assert (
            result.sap_building_parts[0].sap_floor_dimensions[0].party_wall_length_m
            == 6.15
        )

    def test_total_floor_area(self, result: EpcPropertyData) -> None:
        # sum of all floor areas: 24.78 + 24.78 = 49.56
        assert result.total_floor_area_m2 == 49.56

    # --- room counts ---

    def test_habitable_rooms(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_habitable_rooms: 2
        assert result.habitable_rooms_count == 2

    def test_external_doors(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_external_doors: 2
        assert result.door_count == 2

    def test_open_chimneys(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_open_chimneys: 0
        assert result.open_chimneys_count == 0

    def test_blocked_chimneys(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_blocked_chimneys: 0
        assert result.blocked_chimneys_count == 0

    def test_insulated_doors(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_insulated_external_doors: 0
        assert result.insulated_door_count == 0

    def test_draughtproofed_doors(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_draughtproofed_external_doors: 2
        assert result.draughtproofed_door_count == 2

    def test_extensions_count(self, result: EpcPropertyData) -> None:
        # general.number_of_extensions: 0
        assert result.extensions_count == 0

    def test_heated_rooms_count(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_heated_rooms: 0
        # no equivalent in site notes defaults to 0
        assert result.heated_rooms_count == 0

    def test_wet_rooms_count_defaults_to_zero(self, result: EpcPropertyData) -> None:
        # no equivalent in site notes; mapper must default to 0
        assert result.wet_rooms_count == 0

    # --- lighting ---

    def test_led_bulbs(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_fixed_led_bulbs: 5
        assert result.led_fixed_lighting_bulbs_count == 5

    def test_cfl_bulbs(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_fixed_cfl_bulbs: 4
        assert result.cfl_fixed_lighting_bulbs_count == 4

    def test_incandescent_bulbs(self, result: EpcPropertyData) -> None:
        # room_count_elements.number_of_fixed_incandescent_bulbs: 0
        assert result.incandescent_fixed_lighting_bulbs_count == 0

    # --- api-only fields absent ---

    def test_assessment_type_absent(self, result: EpcPropertyData) -> None:
        assert result.assessment_type is None

    def test_sap_version_absent(self, result: EpcPropertyData) -> None:
        assert result.sap_version is None

    def test_uprn_absent(self, result: EpcPropertyData) -> None:
        assert result.uprn is None

    def test_address_line_1(self, result: EpcPropertyData) -> None:
        assert result.address_line_1 == "1, Test Street"

    def test_postcode(self, result: EpcPropertyData) -> None:
        assert result.postcode == "TE1 1ST"

    def test_post_town(self, result: EpcPropertyData) -> None:
        assert result.post_town == "Test Town"

    def test_status_absent(self, result: EpcPropertyData) -> None:
        assert result.status is None

    # --- full object equality ---

    def test_full_mapping(self, survey: PasHubRdSapSiteNotes) -> None:
        result = EpcPropertyDataMapper.from_site_notes(survey)
        expected = EpcPropertyData(
            # General
            assessment_type=None,
            sap_version=None,
            dwelling_type="Mid-terrace house",
            uprn=None,
            address_line_1="1, Test Street",
            postcode="TE1 1ST",
            post_town="Test Town",
            inspection_date=date(2026, 3, 31),
            status=None,
            tenure="Rented Social",
            transaction_type="None of the Above",
            # Elements (not available from site notes)
            roofs=[],
            walls=[],
            floors=[],
            main_heating=[],
            window=None,
            lighting=None,
            hot_water=None,
            door_count=2,
            # Heating
            sap_heating=SapHeating(
                instantaneous_wwhrs=InstantaneousWwhrs(),
                main_heating_details=[
                    MainHeatingDetail(
                        has_fghrs=False,
                        main_fuel_type="Mains gas",
                        heat_emitter_type="Radiators",
                        emitter_temperature="Unknown",
                        fan_flue_present=True,
                        main_heating_control="Programmer, room thermostat and TRVs",
                        condensing=True,
                        weather_compensator=False,
                        central_heating_pump_age_str="Unknown",
                    )
                ],
                has_fixed_air_conditioning=False,
                cylinder_size="Normal (90-130 litres)",
                cylinder_insulation_type="Factory fitted",
                cylinder_insulation_thickness_mm=12,
                shower_outlets=ShowerOutlets(
                    shower_outlet=ShowerOutlet(shower_outlet_type="Non-Electric Shower"),
                ),
            ),
            # Windows
            sap_windows=[
                SapWindow(
                    frame_material="Wooden or PVC",
                    glazing_gap="16 mm or more",
                    orientation="South East",
                    window_type="Window",
                    glazing_type="Double glazing, Unknown install date",
                    window_width=1.0,
                    window_height=1.36,
                    draught_proofed=True,
                    window_location="Main Building",
                    window_wall_type="External wall",
                    permanent_shutters_present=False,
                ),
                SapWindow(
                    frame_material="Wooden or PVC",
                    glazing_gap="16 mm or more",
                    orientation="South East",
                    window_type="Window",
                    glazing_type="Double glazing, Unknown install date",
                    window_width=0.96,
                    window_height=1.33,
                    draught_proofed=True,
                    window_location="Main Building",
                    window_wall_type="External wall",
                    permanent_shutters_present=False,
                ),
                SapWindow(
                    frame_material="Wooden or PVC",
                    glazing_gap="16 mm or more",
                    orientation="North West",
                    window_type="Window",
                    glazing_type="Double glazing, Unknown install date",
                    window_width=0.96,
                    window_height=1.04,
                    draught_proofed=True,
                    window_location="Main Building",
                    window_wall_type="External wall",
                    permanent_shutters_present=False,
                ),
                SapWindow(
                    frame_material="Wooden or PVC",
                    glazing_gap="16 mm or more",
                    orientation="North West",
                    window_type="Window",
                    glazing_type="Double glazing, Unknown install date",
                    window_width=0.97,
                    window_height=1.02,
                    draught_proofed=True,
                    window_location="Main Building",
                    window_wall_type="External wall",
                    permanent_shutters_present=False,
                ),
            ],
            # Energy source
            sap_energy_source=SapEnergySource(
                mains_gas=True,
                meter_type="Single",
                pv_battery_count=0,
                wind_turbines_count=0,
                gas_smart_meter_present=True,
                is_dwelling_export_capable=True,
                wind_turbines_terrain_type="Suburban",
                electricity_smart_meter_present=True,
            ),
            # Building parts
            sap_building_parts=[
                SapBuildingPart(
                    identifier="main",
                    construction_age_band="I",
                    wall_construction="Cavity",
                    wall_insulation_type="As built",
                    wall_thickness_measured=True,
                    party_wall_construction="Cavity Masonry, Unfilled",
                    sap_floor_dimensions=[
                        SapFloorDimension(
                            room_height_m=2.37,
                            total_floor_area_m2=24.78,
                            party_wall_length_m=6.15,
                            heat_loss_perimeter_m=14.21,
                            floor=1,
                        ),
                        SapFloorDimension(
                            room_height_m=2.35,
                            total_floor_area_m2=24.78,
                            party_wall_length_m=6.15,
                            heat_loss_perimeter_m=14.21,
                            floor=0,
                        ),
                    ],
                    wall_thickness_mm=280,
                    roof_insulation_location="Joists",
                    roof_insulation_thickness=100,
                    floor_type="Ground Floor",
                    floor_construction_type="Suspended, not timber",
                    floor_insulation_type_str="As Built",
                    floor_u_value_known=False,
                )
            ],
            solar_water_heating=False,
            has_hot_water_cylinder=True,
            has_fixed_air_conditioning=False,
            # Counts
            wet_rooms_count=0,  # no equivalent in site notes
            extensions_count=0,
            heated_rooms_count=0,
            open_chimneys_count=0,
            habitable_rooms_count=2,
            insulated_door_count=0,
            cfl_fixed_lighting_bulbs_count=4,
            led_fixed_lighting_bulbs_count=5,
            incandescent_fixed_lighting_bulbs_count=0,
            total_floor_area_m2=49.56,
            # Optional fields populated from site notes
            built_form="Mid-terrace",
            property_type="House",
            has_conservatory=False,
            blocked_chimneys_count=0,
            draughtproofed_door_count=2,
            report_reference="49D422A9-0779-44DD-9665-464D35DFF1A8",
            number_of_storeys=2,
            any_unheated_rooms=True,
            waste_water_heat_recovery="None",
            hydro=False,
            photovoltaic_array=False,
            sap_ventilation=SapVentilation(
                ventilation_type="Natural",
                open_flues_count=0,
                closed_flues_count=0,
                boiler_flues_count=0,
                other_flues_count=0,
                extract_fans_count=2,
                passive_vents_count=0,
                flueless_gas_fires_count=0,
                pressure_test="No test",
                draught_lobby=False,
            ),
        )
        assert result == expected


class TestFromSiteNotesVentilation:
    """
    Fixture: pashub_rdsap_site_notes_example1.json
    Ventilation: Natural, 2 extract fans, no flues, no test, no draught lobby.
    """

    @pytest.fixture
    def survey(self) -> PasHubRdSapSiteNotes:
        return from_dict(
            PasHubRdSapSiteNotes, load("pashub_rdsap_site_notes_example1.json")
        )

    @pytest.fixture
    def result(self, survey: PasHubRdSapSiteNotes) -> EpcPropertyData:
        return EpcPropertyDataMapper.from_site_notes(survey)

    def test_sap_ventilation_present(self, result: EpcPropertyData) -> None:
        assert result.sap_ventilation is not None

    def test_ventilation_type(self, result: EpcPropertyData) -> None:
        # ventilation.ventilation_type: "Natural"
        assert result.sap_ventilation.ventilation_type == "Natural"

    def test_open_flues_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_open_flues: 0
        assert result.sap_ventilation.open_flues_count == 0

    def test_closed_flues_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_closed_flues: 0
        assert result.sap_ventilation.closed_flues_count == 0

    def test_boiler_flues_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_boiler_flues: 0
        assert result.sap_ventilation.boiler_flues_count == 0

    def test_other_flues_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_other_flues: 0
        assert result.sap_ventilation.other_flues_count == 0

    def test_extract_fans_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_extract_fans: 2
        assert result.sap_ventilation.extract_fans_count == 2

    def test_passive_vents_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_passive_vents: 0
        assert result.sap_ventilation.passive_vents_count == 0

    def test_flueless_gas_fires_count(self, result: EpcPropertyData) -> None:
        # ventilation.number_of_flueless_gas_fires: 0
        assert result.sap_ventilation.flueless_gas_fires_count == 0

    def test_pressure_test(self, result: EpcPropertyData) -> None:
        # ventilation.pressure_test: "No test"
        assert result.sap_ventilation.pressure_test == "No test"

    def test_draught_lobby(self, result: EpcPropertyData) -> None:
        # ventilation.draught_lobby: false
        assert result.sap_ventilation.draught_lobby is False


class TestFromSiteNotesFloorConstruction:
    """
    Fixture: pashub_rdsap_site_notes_example1.json
    Floor: Suspended not timber, As Built insulation, Ground Floor type.
    """

    @pytest.fixture
    def survey(self) -> PasHubRdSapSiteNotes:
        return from_dict(
            PasHubRdSapSiteNotes, load("pashub_rdsap_site_notes_example1.json")
        )

    @pytest.fixture
    def result(self, survey: PasHubRdSapSiteNotes) -> EpcPropertyData:
        return EpcPropertyDataMapper.from_site_notes(survey)

    def test_floor_type(self, result: EpcPropertyData) -> None:
        # building_construction.floor.floor_type: "Ground Floor"
        assert result.sap_building_parts[0].floor_type == "Ground Floor"

    def test_floor_construction_type(self, result: EpcPropertyData) -> None:
        # building_construction.floor.floor_construction: "Suspended, not timber"
        assert result.sap_building_parts[0].floor_construction_type == "Suspended, not timber"

    def test_floor_insulation_type_str(self, result: EpcPropertyData) -> None:
        # building_construction.floor.floor_insulation_type: "As Built"
        assert result.sap_building_parts[0].floor_insulation_type_str == "As Built"

    def test_floor_u_value_known(self, result: EpcPropertyData) -> None:
        # building_construction.floor.floor_u_value_known: false
        assert result.sap_building_parts[0].floor_u_value_known is False


class TestFromSiteNotesHeatingBoiler:
    """
    Fixture: pashub_rdsap_site_notes_example1.json
    Boiler: Vaillant ecoFIT sustain, condensing, no weather compensator, pump age unknown.
    """

    @pytest.fixture
    def survey(self) -> PasHubRdSapSiteNotes:
        return from_dict(
            PasHubRdSapSiteNotes, load("pashub_rdsap_site_notes_example1.json")
        )

    @pytest.fixture
    def result(self, survey: PasHubRdSapSiteNotes) -> EpcPropertyData:
        return EpcPropertyDataMapper.from_site_notes(survey)

    def test_condensing(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.condensing: true
        assert result.sap_heating.main_heating_details[0].condensing is True

    def test_weather_compensator(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.weather_compensator: false
        assert result.sap_heating.main_heating_details[0].weather_compensator is False

    def test_central_heating_pump_age_str(self, result: EpcPropertyData) -> None:
        # heating_and_hot_water.main_heating.central_heating_pump_age: "Unknown"
        assert result.sap_heating.main_heating_details[0].central_heating_pump_age_str == "Unknown"


class TestFromSiteNotesMiscTopLevel:
    """
    Fixture: pashub_rdsap_site_notes_example1.json
    Misc fields: 2 storeys, unheated rooms present, no hydro, no PV array, no WWHR.
    """

    @pytest.fixture
    def survey(self) -> PasHubRdSapSiteNotes:
        return from_dict(
            PasHubRdSapSiteNotes, load("pashub_rdsap_site_notes_example1.json")
        )

    @pytest.fixture
    def result(self, survey: PasHubRdSapSiteNotes) -> EpcPropertyData:
        return EpcPropertyDataMapper.from_site_notes(survey)

    def test_number_of_storeys(self, result: EpcPropertyData) -> None:
        # general.number_of_storeys: 2
        assert result.number_of_storeys == 2

    def test_any_unheated_rooms(self, result: EpcPropertyData) -> None:
        # room_count_elements.any_unheated_rooms: true
        assert result.any_unheated_rooms is True

    def test_waste_water_heat_recovery(self, result: EpcPropertyData) -> None:
        # room_count_elements.waste_water_heat_recovery: "None"
        assert result.waste_water_heat_recovery == "None"

    def test_hydro(self, result: EpcPropertyData) -> None:
        # renewables.hydro: false
        assert result.hydro is False

    def test_photovoltaic_array(self, result: EpcPropertyData) -> None:
        # renewables.photovoltaic_array: false
        assert result.photovoltaic_array is False


class TestUnmeasurableWallThickness:
    """wall_thickness_mm=None in site notes → wall_thickness_measured=False in domain."""

    @pytest.fixture
    def result(self) -> EpcPropertyData:
        survey = from_dict(
            PasHubRdSapSiteNotes,
            load("pashub_rdsap_site_notes_example_unmeasurable_wall.json"),
        )
        return EpcPropertyDataMapper.from_site_notes(survey)

    def test_wall_thickness_measured_is_false(self, result: EpcPropertyData) -> None:
        assert result.sap_building_parts[0].wall_thickness_measured is False

    def test_wall_thickness_mm_is_none(self, result: EpcPropertyData) -> None:
        assert result.sap_building_parts[0].wall_thickness_mm is None
