import enum
import pytz
import datetime
from sqlalchemy import (
    Column,
    BigInteger,
    Text,
    DateTime,
    Enum,
    ForeignKey,
)
from backend.app.db.base import Base
from backend.app.db.models.portfolio import PropertyModel


# -------------------------------------------------------------------
# ENUM DEFINITIONS (equivalent to drizzle pgEnum calls)
# -------------------------------------------------------------------

class InspectionArchetype(enum.Enum):
    BUNGALOW = "Bungalow"
    FLAT = "Flat"
    MAISONETTE = "Maisonette"
    HOUSE = "House"
    NON_DOMESTIC = "non-domestic"


class InspectionArchetype2(enum.Enum):
    DETACHED = "detached"
    MID_TERRACE = "mid-terrace"
    ENCLOSED_MID_TERRACE = "enclosed mid-terrace"
    END_TERRACE = "end-terrace"
    ENCLOSED_END_TERRACE = "enclosed end-terrace"
    SEMI_DETACHED = "semi-detached"


class InspectionsWallConstruction(enum.Enum):
    CAVITY = "cavity"
    SOLID = "solid"
    SYSTEM_BUILT = "system built"
    TIMBER_FRAMED = "timber framed"
    STEEL_FRAMED = "steel framed"
    RE_WALLED_CAVITY = "re-walled cavity"
    MANSARD_PRE_FAB = "mansard pre-fab"
    MANSARD_EWI = "mansard ewi"
    MANSARD_RE_WALLED = "mansard re-walled"


class InspectionsWallInsulation(enum.Enum):
    EMPTY_CAVITY = "empty cavity"
    FILLED_AT_BUILD = "filled at build"
    PARTIAL = "partial"
    RETRO_DRILLED = "retro drilled"
    EWI = "ewi"
    IWI = "iwi"
    SOLID_NON_CAVITY = "solid non-cavity"
    SYSTEM_BUILT = "system built"
    TIMBER_FRAMED = "timber framed"
    STEEL_FRAMED = "steel framed"


class InspectionsInsulationMaterial(enum.Enum):
    EMPTY_50_90 = "empty 50-90"
    EMPTY_100_PLUS = "empty 100+"
    EMPTY_30_40 = "empty 30-40"
    EMPTY_LESS_THAN_30 = "empty less than 30"
    LOOSE_FIBRE_WOOL = "loose fibre/wool"
    EPS_CELO_KING = "eps/celo/king"
    FIBRE_BATTS_WITH_CAVITY = "fibre batts - with cavity"
    FIBRE_BATTS_NO_CAVITY = "fibre batts - no cavity"
    LOOSE_BEAD = "loose bead"
    GLUED_BEAD = "glued bead"
    FORMALDEHYDE = "formaldehyde"
    BUBBLE_WRAP = "bubble wrap"
    POLY_CHUNKS = "poly chunks"


class InspectionBorescoped(enum.Enum):
    YES = "yes"
    NO = "no"
    REFUSED = "refused"


class InspectionsRoofOrientation(enum.Enum):
    NORTH = "north"
    EAST = "east"
    SOUTH = "south"
    WEST = "west"
    NORTH_EAST = "north-east"
    NORTH_WEST = "north-west"
    SOUTH_EAST = "south-east"
    SOUTH_WEST = "south-west"
    N_S_SPLIT = "n/s split"
    E_W_SPLIT = "e/w split"
    NE_SW_SPLIT = "ne/sw split"
    NW_SE_SPLIT = "nw/se split"
    FLAT_ROOF = "flat roof"
    NO_ROOF = "no roof"
    ROOF_TOO_SMALL = "roof too small"
    ALREADY_HAS_SOLAR_PV = "already has solar pv"


class InspectionsTileHung(enum.Enum):
    YES = "yes"
    NO = "no"
    FIRST_FLOOR_FLATS_TILE_HUNG = "first floor flats are tile hung"


class InspectionsRendered(enum.Enum):
    NO_RENDER = "no render"
    INSUFFICIENT_DPC_SPACE = "rendered with “insufficient” space between dpc and render"
    SUFFICIENT_DPC_SPACE = "rendered with “sufficient” space between dpc and render"


class InspectionsCladding(enum.Enum):
    NONE = "none"
    SUFFICIENT_SPACE = "cladded with “sufficient space to fill the wall”"
    INSUFFICIENT_SPACE = "cladded with “insufficient space to fill the wall”"


class InspectionsAccessIssues(enum.Enum):
    SEE_NOTES = "see notes"
    DAMP_ISSUES = "damp issues"
    FOLIAGE_ON_WALLS = "foliage on walls"
    BUSHES_AGAINST_WALL = "bushes against wall"
    TREES_AROUND_ABOVE = "trees around/anove property"
    HIGH_RISE = "high rise block flats/maisonettes"
    CONSERVATORY = "conservatory"
    LEAN_TO = "lean-to"
    GARAGE = "garage"
    EXTENSION = "extension"
    DECKING = "decking"
    SHED_AGAINST_WALL = "shed against wall"


class InspectionModel(Base):
    __tablename__ = "inspections"

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    property_id = Column(BigInteger, ForeignKey(PropertyModel.id), nullable=False)

    archetype = Column(
        Enum(
            InspectionArchetype,
            name="inspection_archetype",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    archetype_2 = Column(
        Enum(
            InspectionArchetype2,
            name="inspection_archetype_2",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    wall_construction = Column(
        Enum(
            InspectionsWallConstruction,
            name="inspections_wall_construction",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    insulation = Column(
        Enum(
            InspectionsWallInsulation,
            name="inspections_wall_insulation",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    insulation_material = Column(
        Enum(
            InspectionsInsulationMaterial,
            name="inspections_insulation_material",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    borescoped = Column(
        Enum(
            InspectionBorescoped,
            name="inspection_borescoped",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    roof_orientation = Column(
        Enum(
            InspectionsRoofOrientation,
            name="inspections_roof_orientation",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    tile_hung = Column(
        Enum(
            InspectionsTileHung,
            name="inspections_tile_hung",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    rendered = Column(
        Enum(
            InspectionsRendered,
            name="inspections_rendered",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    cladding = Column(
        Enum(
            InspectionsCladding,
            name="inspections_cladding",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    access_issues = Column(
        Enum(
            InspectionsAccessIssues,
            name="inspections_access_issues",
            values_callable=lambda e: [m.value for m in e],
            create_type=False,
        ),
        nullable=True,
    )

    notes = Column(Text)
    surveyor_name = Column(Text)

    created_at = Column(
        DateTime, nullable=False, default=datetime.datetime.now(pytz.utc)
    )
    uploaded_at = Column(
        DateTime, nullable=False, default=datetime.datetime.now(pytz.utc)
    )
