"use client";

import { useEffect, useState, useCallback, useRef } from "react";
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
import {
  fetchCapacitySummary, fetchCracStatus, fetchAlarms, fetchLeakStatus,
  fetchFloorLayout, saveFloorLayout,
  type CapacitySummary, type CracStatus, type Alarm, type LeakSensorStatus,
} from "@/lib/api";
import { RackDetailSheet } from "@/components/dashboard/rack-detail-sheet";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  Wind, WifiOff, Thermometer, Zap, CheckCircle2, AlertTriangle,
  Droplets, Cable, Flame, Snowflake, Settings2, Plus, Trash2,
  GripVertical, ChevronDown, ChevronUp,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { useThresholds } from "@/lib/threshold-context";

const SITE_ID = "sg-01";

// ── Layout type ───────────────────────────────────────────────────────────────

type RowLayout  = { label: string; racks: string[] };
type RoomLayout = { label: string; crac_id: string; rows: RowLayout[] };
type FloorLayout = Record<string, RoomLayout>;

const DEFAULT_LAYOUT: FloorLayout = {
  "hall-a": {
    label: "Hall A",
    crac_id: "crac-01",
    rows: [
      { label: "Row 1", racks: Array.from({ length: 20 }, (_, i) => `SG1A01.${String(i + 1).padStart(2, "0")}`) },
      { label: "Row 2", racks: Array.from({ length: 20 }, (_, i) => `SG1A02.${String(i + 1).padStart(2, "0")}`) },
    ],
  },
  "hall-b": {
    label: "Hall B",
    crac_id: "crac-02",
    rows: [
      { label: "Row 1", racks: Array.from({ length: 20 }, (_, i) => `SG1B01.${String(i + 1).padStart(2, "0")}`) },
      { label: "Row 2", racks: Array.from({ length: 20 }, (_, i) => `SG1B02.${String(i + 1).padStart(2, "0")}`) },
    ],
  },
};

// Derive feed from row index: even index → "A", odd → "B"
function getFeed(layout: FloorLayout, rackId: string): "A" | "B" | undefined {
  for (const room of Object.values(layout)) {
    for (let i = 0; i < room.rows.length; i++) {
      if (room.rows[i].racks.includes(rackId)) return i % 2 === 0 ? "A" : "B";
    }
  }
  return undefined;
}

// ── Colour helpers ────────────────────────────────────────────────────────────

function tempBg(temp: number | null, warn = 26, crit = 28) {
  if (temp === null)        return "oklch(0.22 0.02 265)";
  if (temp >= crit + 4)    return "oklch(0.55 0.22 25)";
  if (temp >= crit)        return "oklch(0.65 0.20 45)";
  if (temp >= warn)        return "oklch(0.72 0.18 84)";
  if (temp >= warn - 2)    return "oklch(0.78 0.14 140)";
  if (temp >= warn - 4)    return "oklch(0.68 0.14 162)";
  return "oklch(0.60 0.15 212)";
}

function powerBg(pct: number | null) {
  if (pct === null) return "oklch(0.22 0.02 265)";
  if (pct >= 90)    return "oklch(0.55 0.22 25)";
  if (pct >= 75)    return "oklch(0.65 0.20 45)";
  if (pct >= 55)    return "oklch(0.72 0.18 84)";
  if (pct >= 35)    return "oklch(0.68 0.14 162)";
  return "oklch(0.60 0.15 212)";
}

type Overlay = "temp" | "power" | "alarms" | "feed" | "crac";

function alarmBg(count: number): string {
  if (count === 0) return "oklch(0.22 0.02 265)";
  if (count >= 3)  return "oklch(0.55 0.22 25)";
  if (count >= 1)  return "oklch(0.65 0.20 45)";
  return "oklch(0.68 0.14 162)";
}

function feedBg(feed: "A" | "B" | undefined): string {
  if (feed === "A") return "oklch(0.55 0.18 255)";
  if (feed === "B") return "oklch(0.60 0.18 40)";
  return "oklch(0.22 0.02 265)";
}

const CRAC_ZONE_COLORS = [
  "oklch(0.55 0.18 255)",  // blue — zone 1
  "oklch(0.60 0.18 40)",   // amber — zone 2
  "oklch(0.60 0.16 145)",  // teal — zone 3
  "oklch(0.58 0.18 310)",  // purple — zone 4
];

// ── Rack tile ─────────────────────────────────────────────────────────────────

function RackTile({
  rackId, temp, powerPct, alarmCount, overlay, feed, cracColor, onClick, tempWarn = 26, tempCrit = 28,
}: {
  rackId: string; temp: number | null; powerPct: number | null;
  alarmCount: number; overlay: Overlay; feed?: "A" | "B"; cracColor?: string; onClick: () => void;
  tempWarn?: number; tempCrit?: number;
}) {
  const offline = temp === null && powerPct === null;
  const bg = offline ? "oklch(0.22 0.02 265)"
    : overlay === "temp"   ? tempBg(temp, tempWarn, tempCrit)
    : overlay === "power"  ? powerBg(powerPct)
    : overlay === "feed"   ? feedBg(feed)
    : overlay === "crac"   ? (cracColor ?? "oklch(0.22 0.02 265)")
    : alarmBg(alarmCount);

  const shortId = rackId.replace("rack-", "").toUpperCase();
  const mainVal = overlay === "temp"   ? (temp !== null ? `${temp}°` : null)
    : overlay === "power"  ? (powerPct !== null ? `${Math.round(powerPct)}%` : null)
    : overlay === "feed"   ? (feed ?? null)
    : (alarmCount > 0 ? String(alarmCount) : null);
  const subVal = overlay === "temp"   ? (powerPct !== null ? `${Math.round(powerPct)}%` : null)
    : overlay === "power"  ? (temp !== null ? `${temp}°C` : null)
    : overlay === "feed"   ? (temp !== null ? `${temp}°C` : null)
    : (temp !== null ? `${temp}°C` : null);

  return (
    <button
      onClick={onClick}
      title={`${rackId} — ${temp ?? "—"}°C · ${powerPct != null ? Math.round(powerPct) : "—"}% load · ${alarmCount} alarm${alarmCount !== 1 ? "s" : ""}`}
      aria-label={`${rackId} — ${temp ?? "—"}°C · ${powerPct != null ? Math.round(powerPct) : "—"}% load · ${alarmCount} alarm${alarmCount !== 1 ? "s" : ""}`}
      className="group relative flex flex-col items-center justify-center gap-0.5 rounded-lg cursor-pointer select-none transition-all duration-200 hover:ring-2 hover:ring-white/40 hover:scale-105 active:scale-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
      style={{
        backgroundColor: bg,
        width: 76, height: 92,
        backgroundImage: offline
          ? "repeating-linear-gradient(45deg,transparent,transparent 5px,oklch(1 0 0/5%) 5px,oklch(1 0 0/5%) 10px)"
          : undefined,
      }}
    >
      <span className="text-[9px] font-bold text-white/60 tracking-widest">{shortId}</span>
      {offline ? (
        <WifiOff className="w-4 h-4 text-white/30" />
      ) : overlay === "alarms" && alarmCount === 0 ? (
        <CheckCircle2 className="w-4 h-4 text-white/40" />
      ) : (
        <span className="text-[17px] font-bold text-white leading-none">{mainVal ?? "—"}</span>
      )}
      {subVal && (
        <span className="text-[9px] text-white/55 opacity-0 group-hover:opacity-100 transition-opacity">{subVal}</span>
      )}
      {overlay === "temp" && powerPct !== null && (
        <div className="absolute bottom-1.5 left-2 right-2 h-[3px] rounded-full bg-white/15 overflow-hidden">
          <div className="h-full rounded-full bg-white/50" style={{ width: `${powerPct}%` }} />
        </div>
      )}
      {overlay !== "alarms" && alarmCount > 0 && (
        <div className="absolute top-1 right-1 w-3.5 h-3.5 rounded-full bg-destructive flex items-center justify-center">
          <span className="text-[8px] font-bold text-white leading-none">{alarmCount}</span>
        </div>
      )}
    </button>
  );
}

// ── CRAC strip ────────────────────────────────────────────────────────────────

function CracStrip({ crac }: { crac: CracStatus | undefined }) {
  const online = crac?.state === "online";
  return (
    <div className={cn(
      "flex items-center gap-4 rounded-lg px-4 py-2.5 border text-sm",
      online ? "bg-primary/5 border-primary/20" : "bg-destructive/5 border-destructive/20"
    )}>
      <Wind className={cn("w-4 h-4 shrink-0", online ? "text-primary" : "text-destructive")} />
      <div className="flex items-center gap-2">
        <span className="font-semibold text-xs">{crac?.crac_id.toUpperCase() ?? "CRAC"}</span>
        <span className={cn(
          "flex items-center gap-1 text-[10px] font-semibold px-2 py-0.5 rounded-full uppercase",
          online ? "bg-green-500/10 text-green-400" : "bg-destructive/10 text-destructive"
        )}>
          {online ? <CheckCircle2 className="w-3 h-3" /> : <AlertTriangle className="w-3 h-3" />}
          {online ? "Online" : "Fault"}
        </span>
      </div>
      {crac && online && (
        <div className="flex items-center gap-4 ml-2 text-xs text-muted-foreground">
          <span>
            <Thermometer className="w-3 h-3 inline mr-0.5 text-primary" />
            Supply <strong className="text-foreground">{crac.supply_temp ?? "—"}°C</strong>
          </span>
          <span>
            <Thermometer className="w-3 h-3 inline mr-0.5 text-orange-400" />
            Return <strong className="text-foreground">{crac.return_temp ?? "—"}°C</strong>
          </span>
          {crac.delta !== null && (
            <span>ΔT <strong className={cn(
              crac.delta > 14 ? "text-destructive" : crac.delta > 11 ? "text-amber-400" : "text-green-400"
            )}>+{crac.delta}°C</strong></span>
          )}
          {crac.fan_pct !== null && (
            <span>Fan <strong className="text-foreground">{crac.fan_pct}%</strong></span>
          )}
          {crac.cooling_capacity_pct !== null && (
            <span>Cap <strong className={cn(
              (crac.cooling_capacity_pct ?? 0) >= 90 ? "text-destructive" :
              (crac.cooling_capacity_pct ?? 0) >= 75 ? "text-amber-400" : "text-foreground"
            )}>{crac.cooling_capacity_pct?.toFixed(0)}%</strong></span>
          )}
        </div>
      )}
    </div>
  );
}

// ── Room plan ─────────────────────────────────────────────────────────────────

function RoomPlan({
  roomId, layout, data, cracs, overlay, alarmsByRack, onRackClick, tempWarn = 26, tempCrit = 28,
}: {
  roomId: string;
  layout: FloorLayout;
  data: CapacitySummary;
  cracs: CracStatus[];
  overlay: Overlay;
  alarmsByRack: Map<string, number>;
  onRackClick: (id: string) => void;
  tempWarn?: number;
  tempCrit?: number;
}) {
  const roomLayout = layout[roomId];
  if (!roomLayout) return null;

  const rackMap = new Map(data.racks.map((r) => [r.rack_id, r]));
  const crac = cracs.find((c) => c.crac_id === roomLayout.crac_id);
  const roomRacks = data.racks.filter((r) => r.room_id === roomId);
  const offlineCount = roomRacks.filter((r) => r.temp === null && r.power_kw === null).length;

  const avgTemp = (() => {
    const temps = roomRacks.map((r) => r.temp).filter((t): t is number => t !== null);
    return temps.length ? Math.round((temps.reduce((a, b) => a + b, 0) / temps.length) * 10) / 10 : null;
  })();
  const totalPower = (() => {
    const powers = roomRacks.map((r) => r.power_kw).filter((p): p is number => p !== null);
    return powers.length ? Math.round(powers.reduce((a, b) => a + b, 0) * 10) / 10 : null;
  })();

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-6 text-xs text-muted-foreground">
        <span>{roomRacks.length} racks</span>
        {avgTemp !== null && (
          <span className="flex items-center gap-1">
            <Thermometer className="w-3 h-3" />
            Avg <strong className="text-foreground">{avgTemp}°C</strong>
          </span>
        )}
        {totalPower !== null && (
          <span className="flex items-center gap-1">
            <Zap className="w-3 h-3" />
            <strong className="text-foreground">{totalPower} kW</strong> IT load
          </span>
        )}
        {offlineCount > 0 && (
          <span className="flex items-center gap-1 text-muted-foreground/60">
            <WifiOff className="w-3 h-3" />
            {offlineCount} offline
          </span>
        )}
      </div>

      <TransformWrapper initialScale={1} minScale={0.4} maxScale={3} limitToBounds={false} wheel={{ disabled: true }}>
        {({ zoomIn, zoomOut, resetTransform }) => (
          <>
            <div className="flex items-center gap-1 mb-2">
              <button
                onClick={() => zoomIn()}
                className="px-2 py-1 rounded border border-border text-xs text-muted-foreground hover:bg-muted/50 transition-colors"
                title="Zoom in"
              >+</button>
              <button
                onClick={() => resetTransform()}
                className="px-2 py-1 rounded border border-border text-xs text-muted-foreground hover:bg-muted/50 transition-colors"
                title="Reset zoom"
              >⊙</button>
              <button
                onClick={() => zoomOut()}
                className="px-2 py-1 rounded border border-border text-xs text-muted-foreground hover:bg-muted/50 transition-colors"
                title="Zoom out"
              >−</button>
              <span className="text-[10px] text-muted-foreground/50 ml-1">Drag to pan</span>
            </div>
            <TransformComponent wrapperStyle={{ width: "100%", overflow: "hidden", borderRadius: "0.75rem" }}>
              <div className="rounded-xl border border-border bg-muted/10 p-5 space-y-3" style={{ minWidth: "100%" }}>
        <CracStrip crac={crac} />

        <div
          className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-widest px-2 rounded-md py-2"
          style={{ backgroundColor: "oklch(0.55 0.22 25 / 6%)", color: "oklch(0.65 0.20 45)" }}
        >
          <div className="flex-1 h-px" style={{ backgroundColor: "oklch(0.65 0.20 45 / 30%)" }} />
          <Flame className="w-3 h-3 shrink-0" style={{ color: "oklch(0.65 0.20 45)" }} />
          HOT AISLE
          <Flame className="w-3 h-3 shrink-0" style={{ color: "oklch(0.65 0.20 45)" }} />
          <div className="flex-1 h-px" style={{ backgroundColor: "oklch(0.65 0.20 45 / 30%)" }} />
        </div>

        {roomLayout.rows.map((row, rowIdx) => {
          const rowCracColor = CRAC_ZONE_COLORS[rowIdx % CRAC_ZONE_COLORS.length];
          return (
          <div key={rowIdx}>
            <div className="flex items-center gap-2">
              <span className="text-[9px] text-muted-foreground/40 uppercase tracking-widest w-10 shrink-0 text-right">
                {row.label}
              </span>
              <div className="flex gap-2 flex-wrap">
                {row.racks.map((rackId) => {
                  const rack = rackMap.get(rackId);
                  return (
                    <RackTile
                      key={rackId}
                      rackId={rackId}
                      temp={rack?.temp ?? null}
                      powerPct={rack?.power_pct ?? null}
                      alarmCount={alarmsByRack.get(rackId) ?? 0}
                      overlay={overlay}
                      feed={getFeed(layout, rackId)}
                      cracColor={rowCracColor}
                      onClick={() => onRackClick(rackId)}
                      tempWarn={tempWarn}
                      tempCrit={tempCrit}
                    />
                  );
                })}
              </div>
            </div>
            {rowIdx < roomLayout.rows.length - 1 && (
              <div
                className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-widest px-2 mt-2 mb-1 rounded-md py-2"
                style={{ backgroundColor: "oklch(0.62 0.17 212 / 7%)", color: "oklch(0.62 0.17 212)" }}
              >
                <div className="flex-1 h-px border-t border-dashed" style={{ borderColor: "oklch(0.62 0.17 212 / 30%)" }} />
                <Snowflake className="w-3 h-3 shrink-0" style={{ color: "oklch(0.62 0.17 212)" }} />
                COLD AISLE
                <Snowflake className="w-3 h-3 shrink-0" style={{ color: "oklch(0.62 0.17 212)" }} />
                <div className="flex-1 h-px border-t border-dashed" style={{ borderColor: "oklch(0.62 0.17 212 / 30%)" }} />
              </div>
            )}
          </div>
          );
        })}

        <div
          className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-widest px-2 rounded-md py-2"
          style={{ backgroundColor: "oklch(0.55 0.22 25 / 6%)", color: "oklch(0.65 0.20 45)" }}
        >
          <div className="flex-1 h-px" style={{ backgroundColor: "oklch(0.65 0.20 45 / 30%)" }} />
          <Flame className="w-3 h-3 shrink-0" style={{ color: "oklch(0.65 0.20 45)" }} />
          HOT AISLE
          <Flame className="w-3 h-3 shrink-0" style={{ color: "oklch(0.65 0.20 45)" }} />
          <div className="flex-1 h-px" style={{ backgroundColor: "oklch(0.65 0.20 45 / 30%)" }} />
        </div>
              </div>
            </TransformComponent>
          </>
        )}
      </TransformWrapper>
    </div>
  );
}

// ── Leak sensor panel ─────────────────────────────────────────────────────────

function LeakSensorPanel({ sensors }: { sensors: LeakSensorStatus[] }) {
  if (sensors.length === 0) return null;
  const active = sensors.filter((s) => s.state === "detected");
  const byZone = sensors.reduce<Record<string, LeakSensorStatus[]>>((acc, s) => {
    const zone = s.floor_zone ?? "unknown";
    (acc[zone] ??= []).push(s);
    return acc;
  }, {});

  return (
    <Card className={cn("border", active.length > 0 && "border-destructive/50")}>
      <CardHeader className="pb-2">
        <div className="flex items-center justify-between">
          <CardTitle className="text-sm font-semibold flex items-center gap-2">
            <Droplets className={cn("w-4 h-4", active.length > 0 ? "text-destructive" : "text-blue-400")} />
            Leak Sensor Status
          </CardTitle>
          <span className={cn(
            "text-[10px] font-semibold px-2.5 py-0.5 rounded-full uppercase",
            active.length > 0 ? "bg-destructive/10 text-destructive" : "bg-green-500/10 text-green-400",
          )}>
            {active.length > 0 ? `${active.length} leak${active.length > 1 ? "s" : ""} detected` : "All clear"}
          </span>
        </div>
      </CardHeader>
      <CardContent>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
          {Object.entries(byZone).map(([zone, zoneSensors]) => (
            <div key={zone} className="rounded-lg border border-border/50 bg-muted/10 p-3 space-y-2">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">{zone}</p>
              {zoneSensors.map((s) => {
                const detected = s.state === "detected";
                return (
                  <div key={s.sensor_id} className="flex items-start justify-between gap-2">
                    <div className="min-w-0">
                      <div className="flex items-center gap-1.5">
                        <div className={cn(
                          "w-2 h-2 rounded-full shrink-0",
                          detected ? "bg-destructive animate-pulse" :
                          s.state === "unknown" ? "bg-muted-foreground/30" : "bg-green-500",
                        )} />
                        <span className="text-xs font-medium truncate">{s.sensor_id}</span>
                      </div>
                      <p className="text-[9px] text-muted-foreground/60 mt-0.5 truncate">
                        {[
                          s.under_floor ? "Under floor" : "Surface mount",
                          s.near_crac ? "near CRAC" : null,
                          s.room_id ?? null,
                        ].filter(Boolean).join(" · ")}
                      </p>
                    </div>
                    <span className={cn(
                      "text-[10px] font-semibold shrink-0",
                      detected ? "text-destructive" :
                      s.state === "unknown" ? "text-muted-foreground/50" : "text-green-400",
                    )}>
                      {detected ? "LEAK" : s.state === "unknown" ? "unknown" : "clear"}
                    </span>
                  </div>
                );
              })}
            </div>
          ))}
        </div>
      </CardContent>
    </Card>
  );
}

// ── Layout editor ─────────────────────────────────────────────────────────────

function LayoutEditor({
  layout, onSave, saving,
}: {
  layout: FloorLayout;
  onSave: (l: FloorLayout) => void;
  saving?: boolean;
}) {
  const [draft, setDraft] = useState<FloorLayout>(() => JSON.parse(JSON.stringify(layout)));
  const [newRoomId, setNewRoomId]     = useState("");
  const [newRoomLabel, setNewRoomLabel] = useState("");
  const [newRoomCrac, setNewRoomCrac]   = useState("");
  const [expandedRoom, setExpandedRoom] = useState<string | null>(Object.keys(draft)[0] ?? null);

  function updateRoom(roomId: string, patch: Partial<RoomLayout>) {
    setDraft(d => ({ ...d, [roomId]: { ...d[roomId], ...patch } }));
  }

  function deleteRoom(roomId: string) {
    setDraft(d => { const n = { ...d }; delete n[roomId]; return n; });
    if (expandedRoom === roomId) setExpandedRoom(null);
  }

  function addRoom() {
    const id = newRoomId.trim().toLowerCase().replace(/\s+/g, "-");
    if (!id || !newRoomLabel.trim() || draft[id]) return;
    setDraft(d => ({
      ...d,
      [id]: { label: newRoomLabel.trim(), crac_id: newRoomCrac.trim(), rows: [] },
    }));
    setNewRoomId(""); setNewRoomLabel(""); setNewRoomCrac("");
    setExpandedRoom(id);
  }

  function addRow(roomId: string) {
    const room = draft[roomId];
    const label = `Row ${room.rows.length + 1}`;
    updateRoom(roomId, { rows: [...room.rows, { label, racks: [] }] });
  }

  function deleteRow(roomId: string, rowIdx: number) {
    const rows = draft[roomId].rows.filter((_, i) => i !== rowIdx);
    updateRoom(roomId, { rows });
  }

  function updateRowLabel(roomId: string, rowIdx: number, label: string) {
    const rows = draft[roomId].rows.map((r, i) => i === rowIdx ? { ...r, label } : r);
    updateRoom(roomId, { rows });
  }

  function addRack(roomId: string, rowIdx: number, rackId: string) {
    const id = rackId.trim();
    if (!id) return;
    const rows = draft[roomId].rows.map((r, i) =>
      i === rowIdx ? { ...r, racks: [...r.racks, id] } : r
    );
    updateRoom(roomId, { rows });
  }

  function removeRack(roomId: string, rowIdx: number, rackIdx: number) {
    const rows = draft[roomId].rows.map((r, i) =>
      i === rowIdx ? { ...r, racks: r.racks.filter((_, j) => j !== rackIdx) } : r
    );
    updateRoom(roomId, { rows });
  }

  function moveRow(roomId: string, rowIdx: number, dir: -1 | 1) {
    const rows = [...draft[roomId].rows];
    const target = rowIdx + dir;
    if (target < 0 || target >= rows.length) return;
    [rows[rowIdx], rows[target]] = [rows[target], rows[rowIdx]];
    updateRoom(roomId, { rows });
  }

  return (
    <div className="flex flex-col h-full">
      <div className="px-6 pt-6 pb-4 border-b border-border shrink-0">
        <h2 className="text-base font-semibold flex items-center gap-2">
          <Settings2 className="w-4 h-4 text-primary" /> Floor Layout Editor
        </h2>
        <p className="text-xs text-muted-foreground mt-1">
          Configure rooms, rows, and rack positions. Changes are saved for all users.
        </p>
      </div>

      <div className="flex-1 overflow-y-auto px-6 py-4 space-y-4">
        {Object.entries(draft).map(([roomId, room]) => (
          <div key={roomId} className="rounded-xl border border-border bg-muted/10 overflow-hidden">
            {/* Room header */}
            <div className="flex items-center gap-2 px-3 py-2.5 bg-muted/20 border-b border-border/60">
              <button
                onClick={() => setExpandedRoom(expandedRoom === roomId ? null : roomId)}
                className="flex items-center gap-2 flex-1 min-w-0 text-left focus-visible:outline-none"
              >
                {expandedRoom === roomId
                  ? <ChevronUp className="w-3.5 h-3.5 text-muted-foreground shrink-0" />
                  : <ChevronDown className="w-3.5 h-3.5 text-muted-foreground shrink-0" />}
                <span className="text-sm font-semibold truncate">{room.label}</span>
                <span className="text-[10px] text-muted-foreground font-mono">{roomId}</span>
                <span className="text-[10px] text-muted-foreground ml-1">
                  · {room.rows.reduce((s, r) => s + r.racks.length, 0)} racks
                </span>
              </button>
              <button
                onClick={() => deleteRoom(roomId)}
                className="text-muted-foreground hover:text-destructive transition-colors shrink-0 p-1"
                aria-label={`Delete ${room.label}`}
              >
                <Trash2 className="w-3.5 h-3.5" />
              </button>
            </div>

            {expandedRoom === roomId && (
              <div className="p-3 space-y-3">
                {/* Room fields */}
                <div className="grid grid-cols-2 gap-2">
                  <div className="space-y-1">
                    <label className="text-[10px] text-muted-foreground font-medium">Room Label</label>
                    <input
                      value={room.label}
                      onChange={e => updateRoom(roomId, { label: e.target.value })}
                      className="w-full h-7 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary"
                    />
                  </div>
                  <div className="space-y-1">
                    <label className="text-[10px] text-muted-foreground font-medium">CRAC ID</label>
                    <input
                      value={room.crac_id}
                      onChange={e => updateRoom(roomId, { crac_id: e.target.value })}
                      placeholder="e.g. crac-01"
                      className="w-full h-7 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary"
                    />
                  </div>
                </div>

                {/* Rows */}
                <div className="space-y-2">
                  <div className="flex items-center justify-between">
                    <p className="text-[10px] font-semibold text-muted-foreground uppercase tracking-wider">Rows</p>
                    <button
                      onClick={() => addRow(roomId)}
                      className="flex items-center gap-1 text-[10px] text-primary hover:text-primary/80 transition-colors"
                    >
                      <Plus className="w-3 h-3" /> Add Row
                    </button>
                  </div>

                  {room.rows.length === 0 && (
                    <p className="text-[10px] text-muted-foreground/50 py-2 text-center">No rows — click Add Row</p>
                  )}

                  {room.rows.map((row, rowIdx) => (
                    <div key={rowIdx} className="rounded-lg border border-border/60 bg-background/50 p-2.5 space-y-2">
                      <div className="flex items-center gap-1.5">
                        <GripVertical className="w-3 h-3 text-muted-foreground/30 shrink-0" />
                        <input
                          value={row.label}
                          onChange={e => updateRowLabel(roomId, rowIdx, e.target.value)}
                          className="flex-1 h-6 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary"
                        />
                        <button onClick={() => moveRow(roomId, rowIdx, -1)} disabled={rowIdx === 0}
                          className="p-0.5 text-muted-foreground hover:text-foreground disabled:opacity-20 transition-colors">
                          <ChevronUp className="w-3 h-3" />
                        </button>
                        <button onClick={() => moveRow(roomId, rowIdx, 1)} disabled={rowIdx === room.rows.length - 1}
                          className="p-0.5 text-muted-foreground hover:text-foreground disabled:opacity-20 transition-colors">
                          <ChevronDown className="w-3 h-3" />
                        </button>
                        <button onClick={() => deleteRow(roomId, rowIdx)}
                          className="p-0.5 text-muted-foreground hover:text-destructive transition-colors">
                          <Trash2 className="w-3 h-3" />
                        </button>
                      </div>

                      {/* Racks in this row */}
                      <div className="flex flex-wrap gap-1">
                        {row.racks.map((rackId, rackIdx) => (
                          <span key={rackIdx} className="inline-flex items-center gap-0.5 bg-muted rounded px-1.5 py-0.5 text-[10px] font-mono">
                            {rackId}
                            <button
                              onClick={() => removeRack(roomId, rowIdx, rackIdx)}
                              className="text-muted-foreground hover:text-destructive transition-colors ml-0.5"
                              aria-label={`Remove ${rackId}`}
                            >
                              ×
                            </button>
                          </span>
                        ))}
                        <RackAdder onAdd={(id) => addRack(roomId, rowIdx, id)} />
                      </div>
                      <p className="text-[9px] text-muted-foreground/40">
                        Feed: {rowIdx % 2 === 0 ? "A (even rows)" : "B (odd rows)"} · {row.racks.length} rack{row.racks.length !== 1 ? "s" : ""}
                      </p>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        ))}

        {/* Add new room */}
        <div className="rounded-xl border border-dashed border-border p-3 space-y-2">
          <p className="text-[10px] font-semibold text-muted-foreground uppercase tracking-wider">Add New Room</p>
          <div className="grid grid-cols-3 gap-2">
            <input
              value={newRoomId}
              onChange={e => setNewRoomId(e.target.value)}
              placeholder="room-id (e.g. hall-c)"
              className="h-7 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary"
            />
            <input
              value={newRoomLabel}
              onChange={e => setNewRoomLabel(e.target.value)}
              placeholder="Label (e.g. Hall C)"
              className="h-7 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary"
            />
            <input
              value={newRoomCrac}
              onChange={e => setNewRoomCrac(e.target.value)}
              placeholder="CRAC ID (e.g. crac-03)"
              className="h-7 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-primary"
            />
          </div>
          <button
            onClick={addRoom}
            disabled={!newRoomId.trim() || !newRoomLabel.trim()}
            className="flex items-center gap-1.5 text-xs text-primary hover:text-primary/80 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
          >
            <Plus className="w-3.5 h-3.5" /> Add Room
          </button>
        </div>
      </div>

      {/* Footer actions */}
      <div className="px-6 py-4 border-t border-border shrink-0 flex items-center justify-between gap-3">
        <button
          onClick={() => { setDraft(JSON.parse(JSON.stringify(DEFAULT_LAYOUT))); setExpandedRoom(Object.keys(DEFAULT_LAYOUT)[0]); }}
          className="text-xs text-muted-foreground hover:text-foreground transition-colors"
        >
          Reset to default
        </button>
        <Button size="sm" onClick={() => onSave(draft)} disabled={saving}>
          {saving ? "Saving…" : "Save Layout"}
        </Button>
      </div>
    </div>
  );
}

// Small inline input to add a rack ID to a row
function RackAdder({ onAdd }: { onAdd: (id: string) => void }) {
  const [val, setVal] = useState("");
  function submit() {
    if (val.trim()) { onAdd(val.trim()); setVal(""); }
  }
  return (
    <span className="inline-flex items-center gap-0.5">
      <input
        value={val}
        onChange={e => setVal(e.target.value)}
        onKeyDown={e => e.key === "Enter" && submit()}
        placeholder="rack-id"
        className="h-5 w-20 rounded border border-dashed border-border bg-background px-1.5 text-[10px] font-mono focus:outline-none focus:ring-1 focus:ring-primary"
      />
      <button
        onClick={submit}
        className="text-primary hover:text-primary/70 transition-colors"
        aria-label="Add rack"
      >
        <Plus className="w-3 h-3" />
      </button>
    </span>
  );
}

// ── Page ──────────────────────────────────────────────────────────────────────

export default function FloorMapPage() {
  const { thresholds } = useThresholds();
  const [layout, setLayout]             = useState<FloorLayout>(DEFAULT_LAYOUT);
  const [data, setData]                 = useState<CapacitySummary | null>(null);
  const [cracs, setCracs]               = useState<CracStatus[]>([]);
  const [alarms, setAlarms]             = useState<Alarm[]>([]);
  const [leakSensors, setLeakSensors]   = useState<LeakSensorStatus[]>([]);
  const [loading, setLoading]           = useState(true);
  const [overlay, setOverlay]           = useState<Overlay>("temp");
  const [activeRoom, setActiveRoom]     = useState<string>("");
  const [selectedRack, setSelectedRack] = useState<string | null>(null);
  const [editorOpen, setEditorOpen]     = useState(false);
  const [layoutSaving, setLayoutSaving] = useState(false);

  // Load layout from backend on mount
  useEffect(() => {
    fetchFloorLayout(SITE_ID)
      .then((remote) => {
        const parsed = remote as FloorLayout;
        setLayout(parsed);
        setActiveRoom(Object.keys(parsed)[0] ?? "");
      })
      .catch(() => {
        // No saved layout yet — use default
        setActiveRoom(Object.keys(DEFAULT_LAYOUT)[0] ?? "");
      });
  }, []);

  const alarmsByRack = new Map<string, number>();
  for (const a of alarms) {
    if (a.rack_id) alarmsByRack.set(a.rack_id, (alarmsByRack.get(a.rack_id) ?? 0) + 1);
  }

  const load = useCallback(async () => {
    try {
      const [d, c, a, ls] = await Promise.all([
        fetchCapacitySummary(SITE_ID),
        fetchCracStatus(SITE_ID),
        fetchAlarms(SITE_ID, "active", 200),
        fetchLeakStatus(SITE_ID).catch(() => [] as LeakSensorStatus[]),
      ]);
      setData(d);
      setCracs(c);
      setAlarms(a);
      setLeakSensors(ls);
    } catch { /* keep stale */ }
    finally { setLoading(false); }
  }, []);

  useEffect(() => {
    load();
    const id = setInterval(load, 30_000);
    return () => clearInterval(id);
  }, [load]);

  async function handleSaveLayout(newLayout: FloorLayout) {
    setLayoutSaving(true);
    try {
      await saveFloorLayout(SITE_ID, newLayout as unknown as Record<string, unknown>);
      setLayout(newLayout);
      if (!newLayout[activeRoom]) setActiveRoom(Object.keys(newLayout)[0] ?? "");
      setEditorOpen(false);
    } catch {
      // save failed — keep editor open so user can retry
    } finally {
      setLayoutSaving(false);
    }
  }

  const roomIds = Object.keys(layout);

  return (
    <div className="p-6 space-y-6">
      <div className="flex items-start justify-between gap-4 flex-wrap">
        <div>
          <h1 className="text-xl font-semibold">Floor Map</h1>
          <p className="text-sm text-muted-foreground">Singapore DC01 — live rack layout · refreshes every 30s</p>
        </div>
        <div className="flex items-center gap-2">
          {/* Overlay selector */}
          <div className="flex items-center gap-0.5 rounded-lg bg-muted p-1">
            {([
              { val: "temp"   as Overlay, icon: Thermometer,   label: "Temperature" },
              { val: "power"  as Overlay, icon: Zap,           label: "Power %" },
              { val: "alarms" as Overlay, icon: AlertTriangle, label: "Alarms" },
              { val: "feed"   as Overlay, icon: Cable,         label: "Power Feed" },
              { val: "crac"   as Overlay, icon: Wind,          label: "CRAC Coverage" },
            ]).map(({ val, icon: Icon, label }) => (
              <button
                key={val}
                onClick={() => setOverlay(val)}
                aria-label={label}
                aria-pressed={overlay === val}
                className={cn(
                  "flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-colors",
                  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
                  overlay === val ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"
                )}
              >
                <Icon className="w-3.5 h-3.5" /> {label}
              </button>
            ))}
          </div>

          {/* Layout editor trigger */}
          <Sheet open={editorOpen} onOpenChange={setEditorOpen}>
            <SheetTrigger asChild>
              <Button variant="outline" size="sm" className="flex items-center gap-1.5">
                <Settings2 className="w-3.5 h-3.5" /> Edit Layout
              </Button>
            </SheetTrigger>
            <SheetContent side="right" className="p-0 w-[420px] sm:w-[480px] flex flex-col">
              <LayoutEditor layout={layout} onSave={handleSaveLayout} saving={layoutSaving} />
            </SheetContent>
          </Sheet>
        </div>
      </div>

      {loading ? (
        <Skeleton className="h-96 w-full" />
      ) : !data ? (
        <div className="flex items-center justify-center h-64 text-sm text-muted-foreground">
          Unable to load floor map data.
        </div>
      ) : (
        <>
          <RackDetailSheet siteId={SITE_ID} rackId={selectedRack} onClose={() => setSelectedRack(null)} />

          <Card>
            <CardHeader className="pb-3">
              <div className="flex items-center justify-between">
                <CardTitle className="text-sm font-semibold">Room View</CardTitle>
                {roomIds.length > 0 && (
                  <Tabs value={activeRoom} onValueChange={setActiveRoom}>
                    <TabsList className="h-7">
                      {roomIds.map((id) => (
                        <TabsTrigger key={id} value={id} className="text-xs px-3 py-0.5">
                          {layout[id].label}
                        </TabsTrigger>
                      ))}
                    </TabsList>
                  </Tabs>
                )}
              </div>
            </CardHeader>
            <CardContent>
              {activeRoom && layout[activeRoom] ? (
                <RoomPlan
                  roomId={activeRoom}
                  layout={layout}
                  data={data}
                  cracs={cracs}
                  overlay={overlay}
                  alarmsByRack={alarmsByRack}
                  onRackClick={setSelectedRack}
                  tempWarn={thresholds.temp.warn}
                  tempCrit={thresholds.temp.critical}
                />
              ) : (
                <div className="flex flex-col items-center justify-center h-48 gap-3 text-muted-foreground">
                  <Settings2 className="w-8 h-8 opacity-30" />
                  <p className="text-sm">No rooms configured</p>
                  <p className="text-xs">Use Edit Layout to add rooms and racks</p>
                </div>
              )}
            </CardContent>
          </Card>

          <LeakSensorPanel sensors={leakSensors} />

          {/* Legend */}
          <div className="flex items-center gap-3 text-[10px] text-muted-foreground flex-wrap">
            {overlay === "alarms" ? (
              <>
                <span className="font-medium">Alarm count:</span>
                <div className="flex items-center gap-1">
                  {([
                    { c: "oklch(0.22 0.02 265)", l: "0" },
                    { c: "oklch(0.65 0.20 45)",  l: "1–2" },
                    { c: "oklch(0.55 0.22 25)",  l: "3+" },
                  ]).map(({ c, l }) => (
                    <span key={l} className="flex items-center gap-0.5">
                      <span className="w-6 h-4 rounded-sm inline-block" style={{ backgroundColor: c }} />
                      <span>{l}</span>
                    </span>
                  ))}
                </div>
              </>
            ) : overlay === "feed" ? (
              <>
                <span className="font-medium">Power feed:</span>
                <div className="flex items-center gap-2">
                  <span className="flex items-center gap-1">
                    <span className="w-6 h-4 rounded-sm inline-block" style={{ backgroundColor: "oklch(0.55 0.18 255)" }} />
                    <span>Feed A (even rows)</span>
                  </span>
                  <span className="flex items-center gap-1">
                    <span className="w-6 h-4 rounded-sm inline-block" style={{ backgroundColor: "oklch(0.60 0.18 40)" }} />
                    <span>Feed B (odd rows)</span>
                  </span>
                </div>
              </>
            ) : overlay === "crac" ? (
              <>
                <span className="font-medium">CRAC thermal zones:</span>
                <div className="flex items-center gap-2 flex-wrap">
                  {CRAC_ZONE_COLORS.slice(0, layout[activeRoom]?.rows.length ?? 2).map((c, i) => (
                    <span key={i} className="flex items-center gap-1">
                      <span className="w-6 h-4 rounded-sm inline-block" style={{ backgroundColor: c }} />
                      <span>Zone {i + 1}</span>
                    </span>
                  ))}
                </div>
              </>
            ) : (
              <>
                <span className="font-medium">{overlay === "temp" ? "Temperature:" : "Power utilisation:"}</span>
                <div className="flex items-center gap-1">
                  {overlay === "temp"
                    ? (["oklch(0.60 0.15 212)","oklch(0.68 0.14 162)","oklch(0.78 0.14 140)","oklch(0.72 0.18 84)","oklch(0.65 0.20 45)","oklch(0.55 0.22 25)"] as string[]).map((c, i) => (
                        <span key={i} className="w-7 h-4 rounded-sm inline-block" style={{ backgroundColor: c }} />
                      ))
                    : (["oklch(0.60 0.15 212)","oklch(0.68 0.14 162)","oklch(0.72 0.18 84)","oklch(0.65 0.20 45)","oklch(0.55 0.22 25)"] as string[]).map((c, i) => (
                        <span key={i} className="w-7 h-4 rounded-sm inline-block" style={{ backgroundColor: c }} />
                      ))}
                  <span className="ml-1">{overlay === "temp" ? "Cool → Hot" : "Low → High"}</span>
                </div>
                {overlay === "temp"  && <span className="ml-auto">Warn: {thresholds.temp.warn}°C &nbsp;|&nbsp; Critical: {thresholds.temp.critical}°C</span>}
                {overlay === "power" && <span className="ml-auto">Warn: 75% &nbsp;|&nbsp; Critical: 90%</span>}
              </>
            )}
            <span className="text-muted-foreground/50">Click any rack to drill down</span>
          </div>
        </>
      )}
    </div>
  );
}
