"""
Construction Domain Constraints — Building Code Verification
Pluggable constraint library for construction compliance.
"""

from pramana.core.vedic import VedicEngine, SutraResult, Sutra


# IBC (International Building Code) simplified constraints
IBC_CONSTRAINTS = {
    "occupancy_limits": {
        "A-1": {"assembly_fixed_seats": 1000, "min_exits": 4},
        "A-2": {"assembly_food": 300, "min_exits": 2},
        "B": {"business": 100, "min_exits": 2},
        "E": {"educational": 50, "min_exits": 2},
        "F-1": {"factory_moderate": 200, "min_exits": 2},
        "H": {"hazardous": 50, "min_exits": 3},
        "I": {"institutional": 50, "min_exits": 2},
        "M": {"mercantile": 100, "min_exits": 2},
        "R-1": {"residential_transient": 50, "min_exits": 2},
        "R-2": {"residential_permanent": 50, "min_exits": 2},
        "S-1": {"storage_moderate": 200, "min_exits": 2},
    },
    "fire_safety": {
        "sprinklers_required_sqft": 5000,
        "max_travel_distance_ft": 250,
        "fire_rating_hours": {"walls": 2, "floors": 1.5, "roof": 1},
    },
    "ada": {
        "min_accessible_entrances": 1,
        "min_accessible_restrooms_pct": 0.05,
        "max_ramp_slope": 0.083,  # 1:12
        "min_door_width_inches": 32,
    },
}

# OSHA construction safety
OSHA_CONSTRAINTS = {
    "fall_protection_height_ft": 6,
    "guardrail_height_inches": 42,
    "max_ladder_angle_degrees": 75.5,
    "hard_hat_required": True,
    "max_noise_db_8hr": 90,
    "max_silica_peg_m3": 50,
}


def check_building_code(building_data: dict,
                        occupancy_type: str = "B") -> list:
    """
    Run building code compliance checks.

    Args:
        building_data: Dict with building specs
            {
                "sqft": 15000,
                "occupancy": 200,
                "exits": 3,
                "sprinklers": True,
                "travel_distance_ft": 180,
                "accessible_entrances": 1,
                "door_widths": [36, 36, 32],
                ...
            }
        occupancy_type: IBC occupancy classification

    Returns:
        List of SutraResult checks
    """
    engine = VedicEngine()
    results = []

    # 1. Completeness check (Puranapurana)
    required = [
        "sqft", "occupancy", "exits", "sprinklers",
        "travel_distance_ft", "accessible_entrances"
    ]
    results.append(engine.puranapurana(building_data, required))

    # 2. Occupancy limits (Urdhva Tiryak — multi-dimensional)
    occ_limits = IBC_CONSTRAINTS["occupancy_limits"].get(occupancy_type, {})
    if occ_limits and "exits" in building_data:
        dims = {"occupancy": building_data.get("occupancy", 0)}
        limits = {}
        for key, val in occ_limits.items():
            if isinstance(val, int):
                limits["occupancy"] = val
        if "min_exits" in occ_limits:
            if building_data.get("exits", 0) < occ_limits["min_exits"]:
                results.append(SutraResult(
                    sutra=Sutra.URDHVA_TIRYAK.value,
                    passed=False,
                    score=building_data["exits"] / occ_limits["min_exits"],
                    detail=f"Exits: {building_data['exits']} "
                           f"(minimum: {occ_limits['min_exits']})",
                    violations=[
                        f"Insufficient exits: {building_data['exits']} "
                        f"< required {occ_limits['min_exits']}"
                    ]
                ))

    # 3. Fire safety (Nikhilam — complement check)
    fire = IBC_CONSTRAINTS["fire_safety"]
    sqft = building_data.get("sqft", 0)
    if sqft >= fire["sprinklers_required_sqft"]:
        sprinkler_ok = building_data.get("sprinklers", False)
        results.append(SutraResult(
            sutra=Sutra.NIKHILAM.value,
            passed=sprinkler_ok,
            score=1.0 if sprinkler_ok else 0.0,
            detail=f"Sprinklers required for {sqft} sqft "
                   f"(threshold: {fire['sprinklers_required_sqft']})",
            violations=[] if sprinkler_ok else [
                "Sprinkler system required but not installed"
            ]
        ))

    # 4. Travel distance (Yavadunam — gap analysis)
    travel = building_data.get("travel_distance_ft", 0)
    max_travel = fire["max_travel_distance_ft"]
    if travel > 0:
        results.append(engine.yavadunam(
            actual={"travel_distance": travel},
            target={"travel_distance": max_travel},
            max_gap={"travel_distance": max_travel}
        ))

    # 5. ADA compliance (Puranapurana + dimension checks)
    ada = IBC_CONSTRAINTS["ada"]
    if "accessible_entrances" in building_data:
        ada_ok = (building_data["accessible_entrances"]
                  >= ada["min_accessible_entrances"])
        results.append(SutraResult(
            sutra=Sutra.PURANAPURANA.value,
            passed=ada_ok,
            score=1.0 if ada_ok else 0.0,
            detail=f"Accessible entrances: "
                   f"{building_data['accessible_entrances']} "
                   f"(min: {ada['min_accessible_entrances']})",
            violations=[] if ada_ok else [
                "Insufficient accessible entrances for ADA compliance"
            ]
        ))

    if "door_widths" in building_data:
        narrow = [w for w in building_data["door_widths"]
                  if w < ada["min_door_width_inches"]]
        results.append(SutraResult(
            sutra=Sutra.CHALANA.value,
            passed=len(narrow) == 0,
            score=1.0 - len(narrow) / max(len(building_data["door_widths"]), 1),
            detail=f"Door widths checked: {len(building_data['door_widths'])}",
            violations=[
                f"Door width {w}\" below ADA minimum "
                f"{ada['min_door_width_inches']}\""
                for w in narrow
            ]
        ))

    return results


def check_osha_safety(site_data: dict) -> list:
    """
    Run OSHA construction safety checks.

    Args:
        site_data: Dict with site conditions
            {
                "working_height_ft": 12,
                "fall_protection": True,
                "guardrail_height_inches": 42,
                "noise_level_db": 85,
                "hard_hats": True,
                ...
            }
    """
    results = []

    # Fall protection
    height = site_data.get("working_height_ft", 0)
    if height >= OSHA_CONSTRAINTS["fall_protection_height_ft"]:
        has_protection = site_data.get("fall_protection", False)
        results.append(SutraResult(
            sutra=Sutra.NIKHILAM.value,
            passed=has_protection,
            score=1.0 if has_protection else 0.0,
            detail=f"Working at {height}ft — fall protection "
                   f"{'present' if has_protection else 'MISSING'}",
            violations=[] if has_protection else [
                f"Fall protection required at {height}ft "
                f"(OSHA threshold: {OSHA_CONSTRAINTS['fall_protection_height_ft']}ft)"
            ]
        ))

    # Noise
    noise = site_data.get("noise_level_db", 0)
    if noise > 0:
        max_noise = OSHA_CONSTRAINTS["max_noise_db_8hr"]
        results.append(SutraResult(
            sutra=Sutra.YAVADUNAM.value,
            passed=noise <= max_noise,
            score=max(0, 1.0 - (noise - max_noise) / max_noise) if noise > max_noise else 1.0,
            detail=f"Noise: {noise}dB (max 8hr: {max_noise}dB)",
            violations=[] if noise <= max_noise else [
                f"Noise {noise}dB exceeds OSHA 8hr limit of {max_noise}dB"
            ]
        ))

    # Hard hats
    if "hard_hats" in site_data:
        results.append(SutraResult(
            sutra=Sutra.PURANAPURANA.value,
            passed=site_data["hard_hats"],
            score=1.0 if site_data["hard_hats"] else 0.0,
            detail="Hard hat compliance",
            violations=[] if site_data["hard_hats"] else [
                "Hard hats required on construction site"
            ]
        ))

    return results
