from typing import Optional

import datatypes.magicplan.api.response as api
from datatypes.magicplan.api.response import MagicPlanPlan
from datatypes.magicplan.domain.models import Plan, Floor, Room, Window, Door


def map_plan(mp: MagicPlanPlan) -> Plan:
    return Plan(
        uid=mp.plan.id,
        name=mp.plan.name,
        address=_map_address(mp.plan.address),
        postcode=mp.plan.address.postal_code if mp.plan.address else None,
        floors=[_map_floor(f) for f in mp.plan_detail.plan.floors],
    )


def _map_address(addr: Optional[api.Address]) -> Optional[str]:
    if addr is None:
        return None
    street = " ".join(p for p in [addr.street_number, addr.street] if p) or None
    parts = [p for p in [street, addr.city, addr.country] if p]
    return ", ".join(parts) if parts else None


def _map_floor(f: api.Floor) -> Floor:
    return Floor(
        level=f.level,
        name=f.name,
        rooms=[_map_room(r) for r in f.rooms],
    )


def _map_room(r: api.Room) -> Room:
    width, length = _parse_dimensions(r.dimensions)
    return Room(
        name=r.name,
        width_m=width,
        length_m=length,
        area_m2=round(r.area, 2),
        windows=[
            _map_window(wi) for wi in r.wall_items if wi.symbol.id.startswith("window")
        ],
        doors=[_map_door(wi) for wi in r.wall_items if wi.symbol.id.startswith("door")],
    )


def _parse_dimensions(dimensions: Optional[str]) -> tuple[float, float]:
    if not dimensions:
        return 0.0, 0.0
    parts = dimensions.split(" x ")
    width = round(float(parts[0].split(" m")[0]), 2)
    length = round(float(parts[1].split(" m")[0]), 2)
    return width, length


def _map_window(wi: api.WallItem) -> Window:
    return Window(
        width_m=round(wi.size.x, 2),
        height_m=round(wi.size.z, 2),
        area_m2=round(wi.size.x * wi.size.z, 2),
        opening_type=wi.symbol.id.removeprefix("window"),
    )


def _map_door(wi: api.WallItem) -> Door:
    return Door(width_mm=round(wi.size.x, 2))
