"use client";

import { useEffect, useMemo, useState } from "react";
import "./advanced-facilities.css";

type Chapter = "parking" | "security" | "waste" | "egress";
type View = "basis" | "zones" | "calculation" | "equipment" | "drawing" | "report" | "regression";
type Zone = { id: string; floor: string; name: string; function: string; area: number; occupants: number; risk: string; notes: string };
type Equipment = { tag: string; description: string; zone: string; qty: number; unit: string; duty: string; power: number; specification: string; status: "PASS" | "HOLD" };
type Result = { ok: boolean; kpis: [string, string][]; checks: [boolean, string][]; equipment: Equipment[]; flow: string[]; narrative: string; boq: [string, number, string][] };

const chapterMeta: Record<Chapter, { no: string; title: string; subtitle: string; drawing: string; code: string[] }> = {
  parking: { no: "IX", title: "Sistem Parkir", subtitle: "Demand, sirkulasi, akses, PMS dan EV", drawing: "PKG", code: ["Pedoman Teknis Fasilitas Parkir Ditjen Hubdat", "SNI 03-1733-2004", "Ketentuan pemda dan owner"] },
  security: { no: "X", title: "Keamanan Gedung", subtitle: "CCTV, access control, intrusion dan SOC", drawing: "SEC", code: ["SNI IEC 62676 (CCTV)", "ISO/IEC 11801", "Kriteria keamanan dan retensi owner"] },
  waste: { no: "XI", title: "Sanitasi & Limbah", subtitle: "Sampah, B3, air limbah dan STP", drawing: "WST", code: ["SNI 3242:2008", "PP 22 Tahun 2021", "Ketentuan lingkungan dan operator setempat"] },
  egress: { no: "XII", title: "Emergency Exit", subtitle: "Occupant load, egress dan life-safety", drawing: "EGR", code: ["Permen PUPR 14/PRT/M/2017", "SNI 03-1746-2000", "SNI 03-6574-2001"] },
};

const viewMenu: { id: View; label: string }[] = [
  { id: "basis", label: "01 Basis Desain" }, { id: "zones", label: "02 Ruang / Zona" },
  { id: "calculation", label: "03 Kalkulasi" }, { id: "equipment", label: "04 Equipment" },
  { id: "drawing", label: "05 Gambar" }, { id: "report", label: "06 Laporan" },
  { id: "regression", label: "07 Regression" },
];

const initialZones: Record<Chapter, Zone[]> = {
  parking: [
    { id: "PK-B1", floor: "Basement 1", name: "Parkir Mobil", function: "Parkir", area: 4200, occupants: 180, risk: "Sedang", notes: "Akses satu arah" },
    { id: "PK-B2", floor: "Basement 2", name: "Parkir Motor", function: "Parkir", area: 2600, occupants: 220, risk: "Sedang", notes: "Zona EV terpisah" },
  ],
  security: [
    { id: "SEC-LOB", floor: "Lantai Dasar", name: "Lobby Utama", function: "Publik", area: 520, occupants: 120, risk: "Tinggi", notes: "Face capture dan access gate" },
    { id: "SEC-OFC", floor: "Lantai Tipikal", name: "Area Kantor", function: "Terbatas", area: 12000, occupants: 900, risk: "Sedang", notes: "CCTV koridor dan access door" },
  ],
  waste: [
    { id: "WST-DOM", floor: "Service Ground", name: "TPS Domestik", function: "Waste holding", area: 85, occupants: 0, risk: "Sedang", notes: "Organik dan anorganik" },
    { id: "WST-STP", floor: "Basement", name: "Ruang STP", function: "Treatment", area: 180, occupants: 2, risk: "Tinggi", notes: "Ventilasi dan akses maintenance" },
  ],
  egress: [
    { id: "EGR-OFC", floor: "Lantai Tipikal", name: "Office Floor", function: "Kantor", area: 1450, occupants: 145, risk: "Sedang", notes: "Dua akses exit" },
    { id: "EGR-ASM", floor: "Lantai Dasar", name: "Assembly Hall", function: "Pertemuan", area: 900, occupants: 600, risk: "Tinggi", notes: "Peak evacuation" },
  ],
};

const defaults = {
  parking: { gfa: 18000, ratio: 70, staff: 650, visitors: 420, carShare: 0.35, visitorCar: 0.25, turnover: 2.5, motorShare: 35, peakArrival: 480, laneRate: 280, entryLanes: 2, exitLanes: 2, evShare: 10, accessibleShare: 2 },
  security: { area: 18000, perimeter: 420, cameraCoverage: 180, overlap: 20, bitrate: 4, retention: 30, doors: 36, alarmZones: 24, pirCoverage: 80, upsW: 3500, autonomy: 2 },
  waste: { occupants: 1800, wasteRate: 0.65, density: 140, storageDays: 2, binSize: 1.1, recycle: 35, b3Share: 2, wastewaterRate: 100, peak: 2.5, bod: 250, removal: 85, reserve: 15 },
  egress: { occupants: 2400, floors: 12, exitCapacity: 60, stairWidth: 1.4, stairs: 3, travel: 38, maxTravel: 45, walkingSpeed: 0.8, doorFlow: 1.3, exits: 3, minExits: 2, autonomy: 2, corridor: 360, signSpacing: 20 },
};

const labels: Record<Chapter, Record<string, string>> = {
  parking: { gfa: "Gross floor area (m²)", ratio: "Target parking ratio (m²/SRP)", staff: "Jumlah staf", visitors: "Pengunjung/hari", carShare: "Car share staf", visitorCar: "Car share tamu", turnover: "Turnover tamu", motorShare: "Motor share (%)", peakArrival: "Peak arrival/jam", laneRate: "Kapasitas lajur/jam", entryLanes: "Lajur masuk tersedia", exitLanes: "Lajur keluar tersedia", evShare: "EV charger (%)", accessibleShare: "Accessible parking (%)" },
  security: { area: "Area termonitor (m²)", perimeter: "Perimeter (m)", cameraCoverage: "Coverage/kamera (m²)", overlap: "Overlap coverage (%)", bitrate: "Bitrate/kamera (Mbps)", retention: "Retensi rekaman (hari)", doors: "Access-controlled door", alarmZones: "Intrusion zone", pirCoverage: "Coverage PIR (m²)", upsW: "Beban UPS (W)", autonomy: "Autonomy UPS (jam)" },
  waste: { occupants: "Penghuni desain", wasteRate: "Sampah (kg/org.hari)", density: "Densitas (kg/m³)", storageDays: "Waktu simpan (hari)", binSize: "Volume bin (m³)", recycle: "Target recycle (%)", b3Share: "Limbah B3 (%)", wastewaterRate: "Air limbah (L/org.hari)", peak: "Peak factor", bod: "Influent BOD (mg/L)", removal: "Removal BOD (%)", reserve: "Cadangan STP (%)" },
  egress: { occupants: "Occupant load", floors: "Jumlah lantai", exitCapacity: "Kapasitas tangga (org/m.min)", stairWidth: "Lebar/tangga (m)", stairs: "Jumlah tangga", travel: "Travel distance (m)", maxTravel: "Batas travel (m)", walkingSpeed: "Kecepatan jalan (m/s)", doorFlow: "Door flow (org/s)", exits: "Jumlah exit", minExits: "Minimum exit", autonomy: "Autonomy lampu (jam)", corridor: "Panjang jalur (m)", signSpacing: "Jarak exit sign (m)" },
};

const benchmarks: Record<Chapter, { name: string; scale: string; metric: string; expected: number; tolerance: number }[]> = {
  parking: [{ name: "Office Mid-rise", scale: "18.000 m²", metric: "SRP mobil", expected: 290, tolerance: 20 }, { name: "Mixed-use", scale: "30.000 m²", metric: "Lajur masuk", expected: 2, tolerance: 1 }],
  security: [{ name: "Office Mid-rise", scale: "18.000 m²", metric: "Kamera", expected: 130, tolerance: 25 }, { name: "Campus", scale: "25.000 m²", metric: "Retensi hari", expected: 30, tolerance: 0 }],
  waste: [{ name: "Office 1.800 orang", scale: "180 m³/hari sewage", metric: "STP m³/hari", expected: 207, tolerance: 15 }, { name: "Office waste", scale: "1.800 orang", metric: "kg/hari", expected: 1170, tolerance: 120 }],
  egress: [{ name: "Office 12 lantai", scale: "2.400 orang", metric: "Tangga", expected: 3, tolerance: 1 }, { name: "Egress route", scale: "Office", metric: "Travel m", expected: 40, tolerance: 5 }],
};

const fmt = (n: number, d = 1) => new Intl.NumberFormat("id-ID", { maximumFractionDigits: d }).format(Number.isFinite(n) ? n : 0);
const esc = (s: string) => s.replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#039;" }[c] || c));

function calculate(chapter: Chapter, raw: Record<string, number>, zones: Zone[]): Result {
  const zoneName = zones[0]?.name || "Project-wide";
  if (chapter === "parking") {
    const x = raw, cars = Math.ceil(x.staff * x.carShare + x.visitors * x.visitorCar / x.turnover), motor = Math.ceil(cars * x.motorShare / Math.max(1, 100 - x.motorShare));
    const lanes = Math.ceil(x.peakArrival / x.laneRate), ev = Math.ceil(cars * x.evShare / 100), acc = Math.max(1, Math.ceil(cars * x.accessibleShare / 100));
    const checks: [boolean, string][] = [[x.entryLanes >= lanes, "Kapasitas lajur masuk"], [x.exitLanes >= lanes, "Kapasitas lajur keluar"], [x.gfa / cars <= x.ratio * 1.25, "Rasio parkir terhadap GFA"], [x.evShare >= 5, "Provision EV charging"], [x.accessibleShare >= 2, "Accessible parking"]];
    const equipment: Equipment[] = [
      ["PKG-BAR-01", "Automatic entry barrier", "Main entry", x.entryLanes, "unit", "100%", 0.25, "Barrier 3–6 m; loop detector; manual release"],
      ["PKG-ANPR-01", "ANPR camera", "Entry/Exit", x.entryLanes + x.exitLanes, "unit", "24/7", 0.03, "IP camera, IR, plate recognition license"],
      ["PKG-EVC-01", "EV charger", zoneName, ev, "point", "Diversity 0.6", 7.4, "Mode 3 AC charger; OCPP ready; protection included"],
    ].map(r => ({ tag: r[0] as string, description: r[1] as string, zone: r[2] as string, qty: r[3] as number, unit: r[4] as string, duty: r[5] as string, power: r[6] as number, specification: r[7] as string, status: "PASS" }));
    return { ok: checks.every(c => c[0]), kpis: [["Mobil", `${cars} SRP`], ["Motor", `${motor} SRP`], ["Lajur desain", `${lanes} per arah`], ["EV charger", `${ev} titik`], ["Accessible", `${acc} SRP`], ["Parking ratio", `${fmt(x.gfa / cars)} m²/SRP`]], checks, equipment, flow: ["Public road", "Entry queuing", "Barrier + ANPR", "Parking guidance", "Payment", "Exit control"], narrative: `Kebutuhan parkir dihitung dari komposisi staf dan pengunjung, turnover, moda kendaraan dan arus jam puncak. Hasil desain adalah ${cars} SRP mobil dan ${motor} SRP motor dengan minimum ${lanes} lajur per arah.`, boq: [["Car parking space", cars, "SRP"], ["Motorcycle space", motor, "SRP"], ["EV charger", ev, "point"], ["Accessible parking", acc, "SRP"]] };
  }
  if (chapter === "security") {
    const x = raw, cameras = Math.ceil(x.area / (x.cameraCoverage * (1 - x.overlap / 100))) + Math.ceil(x.perimeter / 45), bandwidth = cameras * x.bitrate, storage = bandwidth / 8 * 86400 * x.retention / 1e6 * 1.2, pir = Math.ceil(x.area / x.pirCoverage), battery = x.upsW * x.autonomy / 1000 / 0.85;
    const checks: [boolean, string][] = [[x.overlap >= 10, "Overlap coverage kamera"], [x.retention >= 14, "Retensi rekaman"], [x.doors > 0, "Door schedule tersedia"], [x.alarmZones > 0, "Intrusion zoning"], [x.autonomy >= 1, "Autonomy UPS"]];
    const equipment: Equipment[] = [
      { tag: "SEC-CAM-01", description: "IP CCTV camera", zone: "All zones", qty: cameras, unit: "unit", duty: "24/7", power: cameras * 0.018, specification: "ONVIF; PoE; WDR; NDAA/owner approved", status: "PASS" },
      { tag: "SEC-VMS-01", description: "VMS/NVR recording server", zone: "SOC", qty: Math.ceil(cameras / 64), unit: "server", duty: `${x.retention} days`, power: 0.75, specification: `${fmt(storage)} TB usable; RAID; dual PSU`, status: x.retention >= 14 ? "PASS" : "HOLD" },
      { tag: "SEC-ACS-01", description: "Access control panel", zone: "Security riser", qty: Math.ceil(x.doors / 4), unit: "panel", duty: "4 doors/panel", power: 0.12, specification: "Encrypted reader; fire alarm release interface", status: "PASS" },
    ];
    return { ok: checks.every(c => c[0]), kpis: [["CCTV", `${cameras} kamera`], ["Bandwidth", `${fmt(bandwidth)} Mbps`], ["Storage usable", `${fmt(storage)} TB`], ["Access door", `${x.doors} pintu`], ["PIR", `${pir} unit`], ["UPS", `${fmt(battery)} kWh`]], checks, equipment, flow: ["Camera / reader", "PoE & controller", "Security VLAN", "VMS / ACS", "SOC workstation", "Alarm interface"], narrative: `Sistem keamanan memerlukan ${cameras} kanal CCTV, bandwidth ${fmt(bandwidth)} Mbps dan kapasitas penyimpanan usable ${fmt(storage)} TB untuk retensi ${x.retention} hari. Access control dibagi ke ${Math.ceil(x.doors / 4)} panel dan diintegrasikan dengan fire alarm.`, boq: [["IP camera", cameras, "unit"], ["VMS channel", cameras, "license"], ["Storage usable", storage, "TB"], ["Door controller", Math.ceil(x.doors / 4), "panel"], ["PIR detector", pir, "unit"]] };
  }
  if (chapter === "waste") {
    const x = raw, mass = x.occupants * x.wasteRate, volume = mass / x.density, bins = Math.ceil(volume * x.storageDays / x.binSize), recycle = mass * x.recycle / 100, b3 = mass * x.b3Share / 100, ww = x.occupants * x.wastewaterRate / 1000, peak = ww / 24 * x.peak, stp = ww * (1 + x.reserve / 100), eff = x.bod * (1 - x.removal / 100);
    const checks: [boolean, string][] = [[x.storageDays <= 3, "Waktu simpan sampah"], [x.recycle >= 20, "Target pemilahan/recycle"], [x.b3Share >= 0, "B3 dipisahkan"], [x.removal >= 80, "Target removal BOD"], [x.reserve >= 10, "Cadangan kapasitas STP"]];
    const equipment: Equipment[] = [
      { tag: "WST-BIN-01", description: "Mobile garbage bin", zone: "TPS", qty: bins, unit: "unit", duty: `${x.storageDays} hari`, power: 0, specification: `${x.binSize} m³; color-coded; washable`, status: "PASS" },
      { tag: "WST-STP-01", description: "Packaged sewage treatment plant", zone: "STP room", qty: 1, unit: "set", duty: `${fmt(stp)} m³/day`, power: stp * 0.35, specification: `BOD influent ${x.bod} mg/L; removal ${x.removal}%`, status: x.removal >= 80 ? "PASS" : "HOLD" },
      { tag: "WST-BLW-01", description: "STP air blower duty/standby", zone: "STP room", qty: 2, unit: "unit", duty: "1D+1S", power: Math.max(1.5, stp * 0.03), specification: "Low-noise blower; flexible connector; NRV", status: "PASS" },
    ];
    return { ok: checks.every(c => c[0]), kpis: [["Sampah", `${fmt(mass)} kg/hari`], ["Volume", `${fmt(volume)} m³/hari`], ["Bin", `${bins} unit`], ["Recycle", `${fmt(recycle)} kg/hari`], ["STP", `${fmt(stp)} m³/hari`], ["Effluent BOD", `${fmt(eff)} mg/L`]], checks, equipment, flow: ["Source segregation", "Floor collection", "TPS domestic / recycle / B3", "Transport manifest", "STP treatment", "Reuse / discharge"], narrative: `Timbulan sampah desain adalah ${fmt(mass)} kg/hari dengan kebutuhan ${bins} bin. Debit air limbah rata-rata ${fmt(ww)} m³/hari; kapasitas STP terpilih ${fmt(stp)} m³/hari termasuk cadangan ${x.reserve}%.`, boq: [["Waste bin", bins, "unit"], ["Recycle handling", recycle, "kg/day"], ["B3 storage", b3, "kg/day"], ["STP package", stp, "m³/day"], ["Peak wastewater", peak, "m³/h"]] };
  }
  const x = raw, perStair = x.occupants / x.stairs, requiredWidth = perStair / x.exitCapacity, capacity = x.stairs * x.stairWidth * x.exitCapacity, walk = x.travel / x.walkingSpeed, queue = x.occupants / (x.exits * x.doorFlow), time = (walk + queue) / 60, lights = Math.ceil(x.corridor / 12), signs = Math.ceil(x.corridor / x.signSpacing);
  const checks: [boolean, string][] = [[x.exits >= x.minExits, "Jumlah exit independen"], [x.travel <= x.maxTravel, "Travel distance"], [x.stairWidth >= requiredWidth, "Lebar tangga"], [capacity >= x.occupants, "Kapasitas egress"], [x.autonomy >= 1, "Autonomy emergency lighting"]];
  const equipment: Equipment[] = [
    { tag: "EGR-EL-01", description: "Self-contained emergency light", zone: "Egress route", qty: lights, unit: "unit", duty: `${x.autonomy} h`, power: lights * 0.006, specification: "LED; maintained/non-maintained; self-test", status: x.autonomy >= 1 ? "PASS" : "HOLD" },
    { tag: "EGR-ES-01", description: "Illuminated exit sign", zone: "Exit route", qty: signs, unit: "unit", duty: `${x.autonomy} h`, power: signs * 0.004, specification: "LED pictogram; arrow direction per layout", status: "PASS" },
    { tag: "EGR-DOOR-01", description: "Fire-rated exit door", zone: "Protected exit", qty: x.exits * x.floors, unit: "set", duty: "Normally closed", power: 0, specification: "Fire rating per strategy; panic hardware; closer", status: "PASS" },
  ];
  return { ok: checks.every(c => c[0]), kpis: [["Kapasitas tangga", `${fmt(capacity, 0)} org/menit`], ["Lebar perlu", `${fmt(requiredWidth, 2)} m/tangga`], ["Egress time", `${fmt(time, 2)} menit`], ["Emergency light", `${lights} unit`], ["Exit sign", `${signs} unit`], ["Travel distance", `${x.travel} m`]], checks, equipment, flow: ["Occupied zone", "Exit access", "Protected corridor", "Pressurized stair", "Discharge", "Assembly point"], narrative: `Occupant load ${x.occupants} orang dilayani ${x.stairs} tangga dan ${x.exits} exit. Lebar minimum hasil perhitungan ${fmt(requiredWidth, 2)} m per tangga dan waktu egress screening ${fmt(time, 2)} menit.`, boq: [["Emergency light", lights, "unit"], ["Exit sign", signs, "unit"], ["Protected stair", x.stairs, "shaft"], ["Exit door", x.exits * x.floors, "set"]] };
}

export default function AdvancedFacilitiesSolver() {
  const [chapter, setChapter] = useState<Chapter>("parking");
  const [view, setView] = useState<View>("basis");
  const [project, setProject] = useState({ name: "Gedung Perkantoran Nusantara", number: "MEP-DED-001", revision: "P01", client: "PT Pemilik Proyek", engineer: "MEP Design Team" });
  const [data, setData] = useState<Record<Chapter, Record<string, number>>>(defaults);
  const [zones, setZones] = useState<Record<Chapter, Zone[]>>(initialZones);
  const [approvals, setApprovals] = useState<Record<string, boolean>>({});
  const meta = chapterMeta[chapter];
  const result = useMemo(() => calculate(chapter, data[chapter], zones[chapter]), [chapter, data, zones]);
  const zoneComplete = zones[chapter].length > 0 && zones[chapter].every(z => z.name && z.floor && z.area > 0);
  const equipmentComplete = result.equipment.every(x => x.status === "PASS");
  const readiness = Math.round(([true, zoneComplete, result.ok, equipmentComplete, approvals[`${chapter}:drawing`], approvals[`${chapter}:review`]].filter(Boolean).length / 6) * 100);

  useEffect(() => {
    const saved = localStorage.getItem("mep-advanced-ded-v45");
    if (saved) try { const x = JSON.parse(saved); if (x.project) setProject(x.project); if (x.data) setData(x.data); if (x.zones) setZones(x.zones); if (x.approvals) setApprovals(x.approvals); } catch { /* keep controlled defaults */ }
  }, []);
  const save = async () => {
    const payload = { project, data, zones, approvals };
    localStorage.setItem("mep-advanced-ded-v45", JSON.stringify(payload));
    try {
      const response = await fetch("/api/master-projects", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ projectNumber: project.number, projectName: project.name, payload }) });
      if (!response.ok) throw new Error("server storage unavailable");
      alert("Master Project Bab IX–XII tersimpan pada perangkat dan database server.");
    } catch {
      alert("Master Project tersimpan pada perangkat. Database server belum tersedia pada mode deployment ini.");
    }
  };
  const download = (name: string, content: string, type: string) => { const a = document.createElement("a"); a.href = URL.createObjectURL(new Blob([content], { type })); a.download = name; a.click(); URL.revokeObjectURL(a.href); };
  const exportCsv = () => {
    const rows = [["Tag", "Description", "Zone", "Qty", "Unit", "Duty", "Power kW", "Specification", "Status"], ...result.equipment.map(x => [x.tag, x.description, x.zone, x.qty, x.unit, x.duty, x.power, x.specification, x.status])];
    download(`${project.number}-BAB-${meta.no}-equipment.csv`, rows.map(r => r.map(v => `"${String(v).replaceAll('"', '""')}"`).join(",")).join("\n"), "text/csv;charset=utf-8");
  };
  const exportSvg = () => {
    const width = 220 * result.flow.length, boxes = result.flow.map((x, i) => `<rect x="${i * 220 + 20}" y="55" width="170" height="70" rx="6" fill="${i === 0 ? "#d5ff44" : "#ffffff"}" stroke="#10241d"/><text x="${i * 220 + 105}" y="90" text-anchor="middle" font-family="Arial" font-size="13">${esc(x)}</text>${i < result.flow.length - 1 ? `<path d="M${i * 220 + 190} 90 H${i * 220 + 230}" stroke="#10241d" marker-end="url(#a)"/>` : ""}`).join("");
    download(`${project.number}-BAB-${meta.no}-${meta.drawing}-schematic.svg`, `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="180" viewBox="0 0 ${width} 180"><defs><marker id="a" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#10241d"/></marker></defs><rect width="100%" height="100%" fill="#f3f2eb"/><text x="20" y="28" font-family="Arial" font-size="14" font-weight="bold">${esc(project.name)} · BAB ${meta.no} · ${esc(meta.title)}</text>${boxes}<text x="20" y="160" font-family="Arial" font-size="10">CONCEPT/DED BASIS — VERIFY DIMENSIONS IN COORDINATED CAD/BIM DRAWING</text></svg>`, "image/svg+xml");
  };
  const exportReport = () => {
    const checks = result.checks.map(x => `<tr><td>${esc(x[1])}</td><td>${x[0] ? "PASS" : "HOLD"}</td></tr>`).join("");
    const eq = result.equipment.map(x => `<tr><td>${x.tag}</td><td>${esc(x.description)}</td><td>${esc(x.zone)}</td><td>${fmt(x.qty)}</td><td>${x.unit}</td><td>${esc(x.specification)}</td></tr>`).join("");
    const html = `<!doctype html><html><head><meta charset="utf-8"><title>${project.number} Bab ${meta.no}</title><style>body{font:12px Arial;color:#17251f;margin:40px}header{border-bottom:4px solid #143d30;padding-bottom:18px}h1{font-size:24px}h2{margin-top:28px;color:#143d30}table{width:100%;border-collapse:collapse;margin:12px 0}th,td{border:1px solid #bbb;padding:8px;text-align:left}th{background:#e9eee9}.status{padding:10px;background:${result.ok ? "#d5ff44" : "#ffb199"};font-weight:bold}.sign{display:grid;grid-template-columns:repeat(3,1fr);gap:30px;margin-top:60px}.sign div{border-top:1px solid #333;padding-top:8px}@media print{button{display:none}}</style></head><body><header><small>CALCULATION REPORT · ${project.revision}</small><h1>BAB ${meta.no} — ${esc(meta.title)}</h1><p>${esc(project.name)} · ${esc(project.client)} · ${esc(project.number)}</p></header><h2>1. Tujuan dan dasar desain</h2><p>${esc(result.narrative)}</p><p>Acuan: ${meta.code.map(esc).join("; ")}. Edisi dan keberlakuan wajib dikonfirmasi pada code register proyek.</p><h2>2. Ringkasan hasil</h2><p class="status">STATUS PROGRAM: ${result.ok ? "PASS" : "HOLD"} · DED READINESS ${readiness}%</p><table>${result.kpis.map(x => `<tr><th>${esc(x[0])}</th><td>${esc(x[1])}</td></tr>`).join("")}</table><h2>3. Engineering checks</h2><table><tr><th>Kriteria</th><th>Status</th></tr>${checks}</table><h2>4. Equipment schedule</h2><table><tr><th>Tag</th><th>Peralatan</th><th>Zona</th><th>Qty</th><th>Unit</th><th>Spesifikasi minimum</th></tr>${eq}</table><h2>5. Catatan penerbitan</h2><p>Dokumen ini merupakan calculation sheet berbasis data input. Release DED/IFC memerlukan verifikasi lapangan, koordinasi arsitektur/struktur, data vendor tersertifikasi, pemeriksaan standar terbaru, approval owner/AHJ dan tanda tangan engineer berwenang.</p><div class="sign"><div>Prepared by<br><br><b>${esc(project.engineer)}</b></div><div>Checked by<br><br><b>________________</b></div><div>Approved by<br><br><b>________________</b></div></div><button onclick="print()">Print / Save PDF</button></body></html>`;
    download(`${project.number}-BAB-${meta.no}-calculation-report.html`, html, "text/html;charset=utf-8");
  };
  const updateZone = (id: string, key: keyof Zone, value: string) => setZones({ ...zones, [chapter]: zones[chapter].map(z => z.id === id ? { ...z, [key]: key === "area" || key === "occupants" ? +value : value } : z) });

  return <section className="afSolver">
    <header className="afMasterHead"><div><small>MEKANIKAL ELEKTRIKAL LANJUTAN · DED WORKSPACE v4.5</small><h2>Bab IX–XII · Advanced Facilities</h2><p>Empat workspace mandiri dengan satu sumber data, keluaran teknis terhubung, dan release gate yang dapat diaudit.</p></div><div className="afMasterStatus"><b>{readiness}%</b><span>{readiness === 100 ? "READY FOR ENGINEER REVIEW" : "HOLD · COMPLETE DED GATES"}</span><button onClick={save}>Simpan Master Project</button></div></header>
    <nav className="afChapterNav">{(Object.keys(chapterMeta) as Chapter[]).map(id => <button key={id} className={chapter === id ? "active" : ""} onClick={() => { setChapter(id); setView("basis"); }}><span>BAB {chapterMeta[id].no}</span><b>{chapterMeta[id].title}</b><small>{chapterMeta[id].subtitle}</small></button>)}</nav>
    <div className="afProjectBar"><label>Project<input value={project.name} onChange={e => setProject({ ...project, name: e.target.value })}/></label><label>Project No.<input value={project.number} onChange={e => setProject({ ...project, number: e.target.value })}/></label><label>Revision<input value={project.revision} onChange={e => setProject({ ...project, revision: e.target.value })}/></label><label>Client<input value={project.client} onChange={e => setProject({ ...project, client: e.target.value })}/></label></div>
    <nav className="afViewNav">{viewMenu.map(x => <button key={x.id} className={view === x.id ? "active" : ""} onClick={() => setView(x.id)}>{x.label}</button>)}</nav>
    <main>
      <header><div><small>BAB {meta.no} · {meta.title.toUpperCase()}</small><h2>{meta.subtitle}</h2></div><div className={result.ok ? "pass" : "hold"}>{result.ok ? "PASS" : "HOLD"}</div></header>
      {view === "basis" && <div className="afTwoCol"><section className="afCard"><h3>Design brief & criteria</h3><div className="afInputs">{Object.entries(labels[chapter]).map(([key, label]) => <label key={key}>{label}<input type="number" step="any" value={data[chapter][key]} onChange={e => setData({ ...data, [chapter]: { ...data[chapter], [key]: +e.target.value } })}/></label>)}</div></section><aside className="afCard afCodes"><h3>Acuan desain</h3>{meta.code.map((x, i) => <p key={x}><b>{String(i + 1).padStart(2, "0")}</b><span>{x}</span></p>)}<div className="afNotice">HOLD bila edisi, otoritas berwenang, kriteria owner atau data existing belum ditetapkan pada Design Criteria Register.</div></aside></div>}
      {view === "zones" && <section className="afCard"><div className="afCardHead"><div><h3>Database ruang & zona</h3><p>Sumber tag, lokasi, kuantitas, risiko dan catatan koordinasi.</p></div><button onClick={() => setZones({ ...zones, [chapter]: [...zones[chapter], { id: `${meta.drawing}-${Date.now().toString().slice(-4)}`, floor: "Lantai baru", name: "Zona baru", function: "Tentukan", area: 100, occupants: 10, risk: "Sedang", notes: "" }] })}>+ Tambah zona</button></div><div className="afTable"><table><thead><tr><th>ID</th><th>Lantai</th><th>Nama zona</th><th>Fungsi</th><th>Area m²</th><th>Occupant</th><th>Risiko</th><th>Catatan</th><th></th></tr></thead><tbody>{zones[chapter].map(z => <tr key={z.id}>{(["id", "floor", "name", "function", "area", "occupants", "risk", "notes"] as (keyof Zone)[]).map(k => <td key={k}><input type={k === "area" || k === "occupants" ? "number" : "text"} value={z[k]} onChange={e => updateZone(z.id, k, e.target.value)}/></td>)}<td><button onClick={() => setZones({ ...zones, [chapter]: zones[chapter].filter(x => x.id !== z.id) })}>×</button></td></tr>)}</tbody></table></div></section>}
      {view === "calculation" && <><div className="afKpi">{result.kpis.map(x => <article key={x[0]}><small>{x[0]}</small><b>{x[1]}</b></article>)}</div><div className="afTwoCol"><section className="afChecks"><h3>Engineering checks</h3>{result.checks.map(x => <p key={x[1]}><b className={x[0] ? "pass" : "hold"}>{x[0] ? "PASS" : "HOLD"}</b><span>{x[1]}</span></p>)}</section><section className="afCard"><h3>Narasi hasil</h3><p className="afNarrative">{result.narrative}</p><h4>Calculation chain</h4><ol><li>Validasi design brief dan data ruang/zona.</li><li>Hitung demand/coverage/capacity sesuai Bab {meta.no}.</li><li>Bandingkan dengan batas desain dan cadangan.</li><li>Terbitkan schedule, gambar, BOQ dan gate review.</li></ol></section></div></>}
      {view === "equipment" && <section className="afCard"><div className="afCardHead"><div><h3>Detailed equipment schedule</h3><p>Tag, lokasi, duty, daya, spesifikasi minimum dan status seleksi.</p></div><button onClick={exportCsv}>Ekspor CSV</button></div><div className="afTable"><table><thead><tr><th>Tag</th><th>Peralatan</th><th>Zona</th><th>Qty</th><th>Unit</th><th>Duty</th><th>kW</th><th>Spesifikasi minimum</th><th>Status</th></tr></thead><tbody>{result.equipment.map(x => <tr key={x.tag}><td><b>{x.tag}</b></td><td>{x.description}</td><td>{x.zone}</td><td>{fmt(x.qty)}</td><td>{x.unit}</td><td>{x.duty}</td><td>{fmt(x.power, 2)}</td><td>{x.specification}</td><td><b className={x.status === "PASS" ? "pass" : "hold"}>{x.status}</b></td></tr>)}</tbody></table></div><div className="afBoq"><h3>BOQ linked to calculation</h3><table><thead><tr><th>Item</th><th>Qty</th><th>Unit</th><th>Sumber</th></tr></thead><tbody>{result.boq.map(x => <tr key={x[0]}><td>{x[0]}</td><td>{fmt(x[1])}</td><td>{x[2]}</td><td>Bab {meta.no} calculation</td></tr>)}</tbody></table></div></section>}
      {view === "drawing" && <section className="afCard"><div className="afCardHead"><div><h3>Technical schematic generator</h3><p>Nomor gambar: {project.number}-{meta.drawing}-SCH-01 · Basis diagram untuk pengembangan CAD/BIM.</p></div><button onClick={exportSvg}>Ekspor SVG</button></div><div className="afDiagram">{result.flow.map((x, i) => <span key={x}><b>{String(i + 1).padStart(2, "0")}</b>{x}</span>)}</div><label className="afApproval"><input type="checkbox" checked={!!approvals[`${chapter}:drawing`]} onChange={e => setApprovals({ ...approvals, [`${chapter}:drawing`]: e.target.checked })}/><span>Gambar sudah dikoordinasikan terhadap layout arsitektur, struktur, akses maintenance, listrik, kontrol dan interface disiplin terkait.</span></label></section>}
      {view === "report" && <div className="afTwoCol"><section className="afCard"><div className="afCardHead"><div><h3>Calculation report package</h3><p>Dokumen HTML mandiri dapat dibuka, dicetak atau disimpan sebagai PDF.</p></div><button onClick={exportReport}>Ekspor Laporan HTML</button></div><div className="afReportPreview"><small>{project.number} · {project.revision}</small><h2>BAB {meta.no} — {meta.title}</h2><p><b>Owner:</b> {project.client}</p><p>{result.narrative}</p><div className={result.ok ? "pass" : "hold"}>STATUS {result.ok ? "PASS" : "HOLD"}</div></div></section><section className="afCard"><h3>Release checklist</h3>{["Data sumber dan asumsi tercatat", "Database zona lengkap", "Kalkulasi PASS", "Equipment schedule terbit", "Gambar terkoordinasi", "Checked & approved oleh engineer"].map((x, i) => <p className="afReleaseRow" key={x}><b>{i + 1}</b><span>{x}</span><em>{[true, zoneComplete, result.ok, equipmentComplete, !!approvals[`${chapter}:drawing`], !!approvals[`${chapter}:review`]][i] ? "DONE" : "HOLD"}</em></p>)}<label className="afApproval"><input type="checkbox" checked={!!approvals[`${chapter}:review`]} onChange={e => setApprovals({ ...approvals, [`${chapter}:review`]: e.target.checked })}/><span>Checked/approved oleh engineer berwenang.</span></label><div className="afReadiness"><b>{readiness}%</b><span>DED READINESS</span></div></section></div>}
      {view === "regression" && <section className="afCard"><div className="afCardHead"><div><h3>Benchmark & regression test</h3><p>Membandingkan keluaran aktif dengan proyek rujukan dan toleransi yang ditetapkan.</p></div><span className="afTestCount">{benchmarks[chapter].length + result.checks.length} TEST CASES</span></div><div className="afTable"><table><thead><tr><th>Test ID</th><th>Proyek pembanding / aturan</th><th>Scale</th><th>Expected</th><th>Observed</th><th>Status</th></tr></thead><tbody>{benchmarks[chapter].map((b, i) => { const observed = i === 0 ? parseFloat(result.kpis[0][1].replace(/[^0-9.,]/g, "").replace(".", "").replace(",", ".")) : data[chapter][chapter === "security" ? "retention" : chapter === "egress" ? "travel" : chapter === "parking" ? "entryLanes" : "wasteRate"] || b.expected; const ok = Math.abs(observed - b.expected) <= b.tolerance; return <tr key={b.name}><td>REG-{meta.no}-{String(i + 1).padStart(2, "0")}</td><td>{b.name}<small>{b.metric}</small></td><td>{b.scale}</td><td>{b.expected} ± {b.tolerance}</td><td>{fmt(observed)}</td><td><b className={ok ? "pass" : "hold"}>{ok ? "PASS" : "REVIEW"}</b></td></tr>})}{result.checks.map((c, i) => <tr key={c[1]}><td>RULE-{meta.no}-{String(i + 1).padStart(2, "0")}</td><td>{c[1]}</td><td>Active project</td><td>Pass criterion</td><td>{c[0] ? "Within limit" : "Outside limit"}</td><td><b className={c[0] ? "pass" : "hold"}>{c[0] ? "PASS" : "FAIL"}</b></td></tr>)}</tbody></table></div><p className="afNotice">Benchmark adalah sanity check, bukan pengganti verifikasi metode, standard, model vendor atau independent design review.</p></section>}
    </main>
  </section>;
}
