from typing import Optional

from sqlmodel import Session

from backend.app.db.models.epc_property import (
    EpcBuildingPartModel,
    EpcEnergyElementModel,
    EpcFlatDetailsModel,
    EpcFloorDimensionModel,
    EpcMainHeatingDetailModel,
    EpcPropertyEnergyPerformanceModel,
    EpcPropertyModel,
    EpcWindowModel,
)
from datatypes.epc.domain.epc_property_data import EpcPropertyData


def save_epc_property_data(
    session: Session,
    data: EpcPropertyData,
    uploaded_file_id: Optional[int] = None,
    property_id: Optional[int] = None,
    portfolio_id: Optional[int] = None,
) -> EpcPropertyModel:
    epc_prop = EpcPropertyModel.from_epc_property_data(
        data, property_id=property_id, portfolio_id=portfolio_id
    )
    epc_prop.uploaded_file_id = uploaded_file_id
    session.add(epc_prop)
    session.flush()
    assert epc_prop.id is not None
    epc_property_id: int = epc_prop.id

    session.add(
        EpcPropertyEnergyPerformanceModel.from_epc_property_data(
            data, epc_property_id=epc_property_id
        )
    )

    for detail in data.sap_heating.main_heating_details:
        session.add(EpcMainHeatingDetailModel.from_domain(detail, epc_property_id))

    for part in data.sap_building_parts:
        bp = EpcBuildingPartModel.from_domain(part, epc_property_id)
        session.add(bp)
        session.flush()
        assert bp.id is not None
        for dim in part.sap_floor_dimensions:
            session.add(EpcFloorDimensionModel.from_domain(dim, bp.id))

    for window in data.sap_windows:
        session.add(EpcWindowModel.from_domain(window, epc_property_id))

    for el in data.roofs:
        session.add(EpcEnergyElementModel.from_domain(el, "roof", epc_property_id))
    for el in data.walls:
        session.add(EpcEnergyElementModel.from_domain(el, "wall", epc_property_id))
    for el in data.floors:
        session.add(EpcEnergyElementModel.from_domain(el, "floor", epc_property_id))
    for el in data.main_heating:
        session.add(EpcEnergyElementModel.from_domain(el, "main_heating", epc_property_id))

    for el, etype in [
        (data.window, "window"),
        (data.lighting, "lighting"),
        (data.hot_water, "hot_water"),
        (data.secondary_heating, "secondary_heating"),
        (data.main_heating_controls, "main_heating_controls"),
    ]:
        if el is not None:
            session.add(EpcEnergyElementModel.from_domain(el, etype, epc_property_id))

    if data.sap_flat_details is not None:
        session.add(EpcFlatDetailsModel.from_domain(data.sap_flat_details, epc_property_id))

    return epc_prop
