/* global React, ReactDOM, TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakToggle, TweakSelect, TweakColor */
const { useState, useMemo, useRef, useEffect, useCallback } = React;

// ---------- Mock data ----------
// Floor plan: grid of cells. Each rack belongs to a row (A, B, C, D).
// 2 pairs of back-to-back rows = 4 rows of ~7-8 racks = ~30 racks.
const ROWS_DEF = [
  { id: "A", y: 4, count: 8, label: "Row A" },
  { id: "B", y: 6, count: 8, label: "Row B" },
  { id: "C", y: 11, count: 7, label: "Row C" },
  { id: "D", y: 13, count: 7, label: "Row D" },
];

// Build rack list with deterministic mock metrics
function seededRand(seed) {
  let x = Math.sin(seed) * 10000;
  return x - Math.floor(x);
}

const RACKS = (() => {
  const out = [];
  ROWS_DEF.forEach((row) => {
    for (let i = 0; i < row.count; i++) {
      const id = `R-${row.id}${String(i + 1).padStart(2, "0")}`;
      const seed = row.id.charCodeAt(0) * 13 + i * 7;
      const u_used = Math.floor(seededRand(seed) * 38) + 4;
      const w_max = 6400;
      const w_used = Math.floor(seededRand(seed + 1) * 5500) + 600;
      const temp = 19 + Math.floor(seededRand(seed + 2) * 14); // 19..32
      const alerts = seededRand(seed + 3) > 0.85 ? (seededRand(seed + 4) > 0.5 ? "critical" : "warning") : "ok";
      out.push({
        id,
        row: row.id,
        col: i,
        x: 3 + i,
        y: row.y,
        u_total: 42,
        u_used,
        w_used,
        w_max,
        temp,
        alerts,
        pdus: 2,
      });
    }
  });
  return out;
})();

const WALLS = [
  // outer walls
  { x1: 1, y1: 1, x2: 14, y2: 1 }, // top
  { x1: 1, y1: 1, x2: 1, y2: 17 }, // left
  { x1: 14, y1: 1, x2: 14, y2: 17 }, // right
  { x1: 1, y1: 17, x2: 14, y2: 17 }, // bottom
];
const DOORS = [
  { x: 13, y: 17, dir: "h" },
];

// ---------- Color scales ----------
const ratioColor = (r) => {
  // 0..1 → green → orange → red, oklch for harmony
  if (r < 0.5) return `oklch(0.72 0.14 ${145 - r * 40})`;
  if (r < 0.7) return `oklch(0.78 0.15 95)`;
  if (r < 0.85) return `oklch(0.72 0.17 60)`;
  return `oklch(0.62 0.20 28)`;
};
const tempColor = (t) => {
  if (t < 22) return `oklch(0.74 0.12 230)`;
  if (t < 25) return `oklch(0.78 0.14 145)`;
  if (t < 28) return `oklch(0.78 0.15 95)`;
  return `oklch(0.62 0.20 28)`;
};
const alertColor = (a) => {
  if (a === "critical") return `oklch(0.62 0.20 28)`;
  if (a === "warning") return `oklch(0.78 0.15 75)`;
  return `oklch(0.72 0.14 150)`;
};

function getRackColor(rack, layer) {
  switch (layer) {
    case "u":
      return ratioColor(rack.u_used / rack.u_total);
    case "w":
      return ratioColor(rack.w_used / rack.w_max);
    case "t":
      return tempColor(rack.temp);
    case "a":
      return alertColor(rack.alerts);
    default:
      return "var(--rack-fill)";
  }
}

// ---------- Icons (inline svg) ----------
const Icon = ({ name, size = 16 }) => {
  const paths = {
    rooms: <><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></>,
    inventory: <><path d="M3 7h18M3 12h18M3 17h18"/></>,
    tickets: <><path d="M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/></>,
    monitoring: <><path d="M3 12h4l3-8 4 16 3-8h4"/></>,
    alerts: <><path d="M12 3l10 18H2z"/><path d="M12 10v5"/><circle cx="12" cy="18" r="0.5"/></>,
    admin: <><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.2 4.2l2.1 2.1M17.7 17.7l2.1 2.1M2 12h3M19 12h3M4.2 19.8l2.1-2.1M17.7 6.3l2.1-2.1"/></>,
    search: <><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></>,
    bell: <><path d="M6 8a6 6 0 1 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9z"/><path d="M10 21a2 2 0 0 0 4 0"/></>,
    chevron: <><path d="m9 6 6 6-6 6"/></>,
    chevronD: <><path d="m6 9 6 6 6-6"/></>,
    plus: <><path d="M12 5v14M5 12h14"/></>,
    edit: <><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4z"/></>,
    zoomIn: <><circle cx="11" cy="11" r="7"/><path d="M11 8v6M8 11h6M20 20l-3.5-3.5"/></>,
    zoomOut: <><circle cx="11" cy="11" r="7"/><path d="M8 11h6M20 20l-3.5-3.5"/></>,
    reset: <><path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5"/></>,
    door: <><path d="M4 22V4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v18"/><path d="M2 22h20"/><circle cx="15" cy="13" r="0.5"/></>,
    wall: <><rect x="3" y="3" width="18" height="18" rx="1"/><path d="M3 9h18M3 15h18M9 3v18M15 3v18"/></>,
    panel: <><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18"/></>,
    moon: <><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></>,
    sun: <><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></>,
    ticket: <><path d="M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/></>,
    arrow: <><path d="M5 12h14M13 5l7 7-7 7"/></>,
    close: <><path d="M18 6 6 18M6 6l12 12"/></>,
    rack: <><rect x="6" y="3" width="12" height="18" rx="1"/><path d="M9 7h6M9 11h6M9 15h6M9 19h6"/></>,
    bolt: <><path d="m13 2-9 12h7l-1 8 9-12h-7z"/></>,
    thermo: <><path d="M14 14.76V3.5a2.5 2.5 0 0 0-5 0v11.26a4 4 0 1 0 5 0z"/></>,
    grip: <><circle cx="9" cy="6" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="9" cy="18" r="1"/><circle cx="15" cy="6" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="18" r="1"/></>,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
      {paths[name]}
    </svg>
  );
};

// ---------- Tooltip / Mini-rack preview ----------
function MiniRack({ rack }) {
  // build mock equipments
  const seed = rack.id.charCodeAt(2) + rack.id.charCodeAt(3);
  const items = [];
  let u = 1;
  let i = 0;
  while (u <= 42) {
    const r = seededRand(seed + i);
    const h = r > 0.85 ? 4 : r > 0.6 ? 2 : 1;
    const filled = (u + h - 1 <= rack.u_used) && seededRand(seed + i + 1) > 0.15;
    items.push({ u, h, filled });
    u += h;
    i++;
  }
  return (
    <div className="mini-rack">
      <div className="mini-rack-frame">
        {items.slice().reverse().map((it, idx) => (
          <div key={idx} className={`mini-u ${it.filled ? "filled" : "empty"}`} style={{ flex: it.h }} />
        ))}
      </div>
    </div>
  );
}

function RackTooltipContent({ rack, layer }) {
  const uPct = Math.round((rack.u_used / rack.u_total) * 100);
  const wPct = Math.round((rack.w_used / rack.w_max) * 100);
  return (
    <div className="rack-tooltip">
      <div className="tt-header">
        <div className="tt-title">{rack.id}</div>
        <div className={`tt-status status-${rack.alerts}`}>
          {rack.alerts === "ok" ? "● OK" : rack.alerts === "warning" ? "● WARN" : "● CRIT"}
        </div>
      </div>
      <div className="tt-body">
        <MiniRack rack={rack} />
        <div className="tt-stats">
          <div className="tt-stat">
            <div className="tt-stat-label">OCCUPATION</div>
            <div className="tt-stat-value">{rack.u_used}<span>/{rack.u_total}U</span></div>
            <div className="tt-bar"><div className="tt-bar-fill" style={{ width: `${uPct}%`, background: ratioColor(rack.u_used / rack.u_total) }} /></div>
          </div>
          <div className="tt-stat">
            <div className="tt-stat-label">CHARGE</div>
            <div className="tt-stat-value">{(rack.w_used / 1000).toFixed(1)}<span>/{(rack.w_max / 1000).toFixed(1)} kW</span></div>
            <div className="tt-bar"><div className="tt-bar-fill" style={{ width: `${wPct}%`, background: ratioColor(rack.w_used / rack.w_max) }} /></div>
          </div>
          <div className="tt-stat">
            <div className="tt-stat-label">TEMP</div>
            <div className="tt-stat-value" style={{ color: tempColor(rack.temp) }}>{rack.temp}<span>°C</span></div>
          </div>
          <div className="tt-stat">
            <div className="tt-stat-label">PDU</div>
            <div className="tt-stat-value">A·B<span> · 2 actives</span></div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------- Floor plan canvas ----------
function FloorPlan({ layer, selectedId, onSelect, editMode, racks, setRacks, walls, setWalls, doors, tool, density }) {
  const [hover, setHover] = useState(null);
  const [zoom, setZoom] = useState(1);
  const [pan, setPan] = useState({ x: 0, y: 0 });
  const [draggingRack, setDraggingRack] = useState(null);
  const svgRef = useRef(null);
  const containerRef = useRef(null);
  const tooltipRef = useRef(null);
  const rafRef = useRef(0);

  const CELL = density === "compact" ? 44 : density === "comfort" ? 64 : 54;
  const GW = 16, GH = 19;

  const handleWheel = (e) => {
    e.preventDefault();
    const delta = e.deltaY > 0 ? 0.92 : 1.08;
    setZoom(z => Math.max(0.5, Math.min(2.5, z * delta)));
  };

  const handleMouseMove = (e) => {
    if (!containerRef.current || !tooltipRef.current) return;
    const cx = e.clientX, cy = e.clientY;
    if (rafRef.current) return;
    rafRef.current = requestAnimationFrame(() => {
      rafRef.current = 0;
      const tt = tooltipRef.current;
      const rect = containerRef.current.getBoundingClientRect();
      if (!tt) return;
      const tw = tt.offsetWidth || 320;
      const th = tt.offsetHeight || 220;
      let x = cx - rect.left + 16;
      let y = cy - rect.top + 16;
      if (x + tw > rect.width) x = cx - rect.left - tw - 16;
      if (y + th > rect.height) y = cy - rect.top - th - 16;
      tt.style.transform = `translate(${x}px, ${y}px)`;
    });
  };

  const onRackMouseDown = (e, rack) => {
    if (!editMode || tool !== "select") return;
    e.stopPropagation();
    setDraggingRack({ id: rack.id, startX: e.clientX, startY: e.clientY, origX: rack.x, origY: rack.y });
  };

  useEffect(() => {
    if (!draggingRack) return;
    const move = (e) => {
      const dx = Math.round((e.clientX - draggingRack.startX) / (CELL * zoom));
      const dy = Math.round((e.clientY - draggingRack.startY) / (CELL * zoom));
      setRacks(rs => rs.map(r => r.id === draggingRack.id ? { ...r, x: draggingRack.origX + dx, y: draggingRack.origY + dy } : r));
    };
    const up = () => setDraggingRack(null);
    window.addEventListner("mousemove", move);
    window.addEventListner("mouseup", up);
    return () => { window.removeEventListner("mousemove", move); window.removeEventListner("mouseup", up); };
  }, [draggingRack, CELL, zoom]);

  return (
    <div className="floor-canvas" ref={containerRef} onMouseMove={handleMouseMove} onWheel={handleWheel}>
      <svg
        ref={svgRef}
        width="100%"
        height="100%"
        viewBox={`0 0 ${GW * CELL} ${GH * CELL}`}
        style={{ transform: `scale(${zoom}) translate(${pan.x}px, ${pan.y}px)`, transformOrigin: "center" }}
      >
        <defs>
          <pattern id="grid" width={CELL} height={CELL} patternUnits="userSpaceOnUse">
            <path d={`M ${CELL} 0 L 0 0 0 ${CELL}`} fill="none" stroke="var(--grid-line)" strokeWidth="1"/>
          </pattern>
          <pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
            <line x1="0" y1="0" x2="0" y2="6" stroke="var(--hatch)" strokeWidth="2"/>
          </pattern>
        </defs>

        {/* Floor */}
        <rect x={CELL} y={CELL} width={(GW - 2) * CELL} height={(GH - 2) * CELL} fill="var(--floor-bg)" />
        <rect x={CELL} y={CELL} width={(GW - 2) * CELL} height={(GH - 2) * CELL} fill="url(#grid)" opacity="0.6"/>

        {/* Compass & scale */}
        <g transform={`translate(${(GW - 2) * CELL - 10}, ${CELL + 24})`}>
          <circle r="14" fill="var(--panel)" stroke="var(--border)"/>
          <text textAnchor="middle" y="-4" fontSize="9" fill="var(--text-dim)">N</text>
          <path d="M0 -8 L3 4 L0 1 L-3 4 Z" fill="var(--text)"/>
        </g>

        {/* Walls */}
        {walls.map((w, i) => (
          <line key={i} x1={w.x1 * CELL} y1={w.y1 * CELL} x2={w.x2 * CELL} y2={w.y2 * CELL} stroke="var(--wall)" strokeWidth="6" strokeLinecap="square"/>
        ))}

        {/* Doors */}
        {doors.map((d, i) => (
          <g key={i}>
            <rect x={d.x * CELL - CELL / 2} y={d.y * CELL - 4} width={CELL} height={8} fill="var(--floor-bg)" stroke="var(--wall)" strokeWidth="1.5"/>
            <path d={`M ${d.x * CELL - CELL / 2} ${d.y * CELL} A ${CELL} ${CELL} 0 0 1 ${d.x * CELL + CELL / 2} ${d.y * CELL - CELL}`} fill="none" stroke="var(--wall)" strokeWidth="1" strokeDasharray="2 3"/>
          </g>
        ))}

        {/* Row labels */}
        {ROWS_DEF.map(row => (
          <g key={row.id}>
            <text x={2.4 * CELL} y={(row.y + 0.65) * CELL} fontSize="11" fontFamily="JetBrains Mono, monospace" fill="var(--text-dim)" textAnchor="end">{row.id}</text>
          </g>
        ))}

        {/* Aisle labels between B and C */}
        <text x={(GW / 2) * CELL} y={(8.5) * CELL + 4} fontSize="10" fontFamily="JetBrains Mono, monospace" fill="var(--text-dim)" textAnchor="middle" letterSpacing="2">— ALLÉE FROIDE —</text>
        <text x={(GW / 2) * CELL} y={(5.1) * CELL} fontSize="9" fontFamily="JetBrains Mono, monospace" fill="var(--text-dim)" textAnchor="middle" letterSpacing="1.5">aisle hote</text>
        <text x={(GW / 2) * CELL} y={(12.1) * CELL} fontSize="9" fontFamily="JetBrains Mono, monospace" fill="var(--text-dim)" textAnchor="middle" letterSpacing="1.5">aisle hote</text>

        {/* Racks */}
        {racks.map(rack => {
          const fill = layer === "none" ? "var(--rack-fill)" : getRackColor(rack, layer);
          const isSel = selectedId === rack.id;
          const isHover = hover === rack.id;
          return (
            <g
              key={rack.id}
              transform={`translate(${rack.x * CELL}, ${rack.y * CELL})`}
              className={`rack-node ${isSel ? "selected" : ""} ${editMode ? "editing" : ""}`}
              onMouseEnter={() => setHover(rack.id)}
              onMouseLeave={() => setHover(null)}
              onClick={() => onSelect(rack.id)}
              onMouseDown={(e) => onRackMouseDown(e, rack)}
            >
              <rect width={CELL - 4} height={CELL * 1.6 - 4} x="2" y="2" rx="3" fill={fill} stroke={isSel ? "var(--accent)" : "var(--rack-border)"} strokeWidth={isSel ? 2.5 : 1}/>
              {/* front face indicator */}
              <rect x="2" y={CELL * 1.6 - 6} width={CELL - 4} height="3" fill="var(--rack-front)"/>
              {/* alert badge */}
              {rack.alerts !== "ok" && (
                <circle cx={CELL - 8} cy={8} r="4" fill={rack.alerts === "critical" ? "oklch(0.62 0.20 28)" : "oklch(0.78 0.15 75)"} stroke="var(--panel)" strokeWidth="1.5"/>
              )}
              <text x={CELL / 2} y={CELL * 0.55} fontSize="10" fontFamily="JetBrains Mono, monospace" fontWeight="600" fill="var(--rack-text)" textAnchor="middle">{rack.id}</text>
              <text x={CELL / 2} y={CELL * 0.85} fontSize="8" fontFamily="JetBrains Mono, monospace" fill="var(--rack-text-dim)" textAnchor="middle">
                {layer === "u" ? `${Math.round(rack.u_used / rack.u_total * 100)}%` :
                 layer === "w" ? `${(rack.w_used / 1000).toFixed(1)}kW` :
                 layer === "t" ? `${rack.temp}°C` :
                 layer === "a" ? rack.alerts.toUpperCase() :
                 `${rack.u_used}U`}
              </text>
              {editMode && (
                <g transform={`translate(${CELL - 16}, ${CELL * 1.6 - 16})`} opacity="0.7">
                  <Icon name="grip" size={10}/>
                </g>
              )}
            </g>
          );
        })}
      </svg>

      {/* Floating zoom controls */}
      <div className="canvas-controls">
        <button onClick={() => setZoom(z => Math.min(2.5, z * 1.15))} title="Zoom +"><Icon name="zoomIn"/></button>
        <button onClick={() => setZoom(z => Math.max(0.5, z * 0.87))} title="Zoom -"><Icon name="zoomOut"/></button>
        <button onClick={() => { setZoom(1); setPan({ x: 0, y: 0 }); }} title="Reset"><Icon name="reset"/></button>
        <div className="canvas-zoom-label">{Math.round(zoom * 100)}%</div>
      </div>

      {/* Hover tooltip — positioned imperatively via ref to avoid re-render flicker */}
      <div ref={tooltipRef} className="rack-tooltip-anchor" style={{ visibility: hover && !draggingRack ? "visible" : "hidden" }}>
        {hover && (() => {
          const rack = racks.find(r => r.id === hover);
          return rack ? <RackTooltipContent rack={rack} layer={layer}/> : null;
        })()}
      </div>
    </div>
  );
}

// ---------- Sidebar Left ----------
function NavSidebar({ collapsed, setCollapsed }) {
  const items = [
    { id: "rooms", label: "Rooms", active: true },
    { id: "inventory", label: "Inventory" },
    { id: "tickets", label: "Tickets", badge: 3 },
    { id: "monitoring", label: "Monitoring" },
    { id: "alerts", label: "Alerts", badge: 2, badgeColor: "danger" },
    { id: "admin", label: "Admin" },
  ];
  return (
    <aside className={`nav-sidebar ${collapsed ? "collapsed" : ""}`}>
      <div className="nav-brand">
        <div className="brand-mark">
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <rect x="3" y="3" width="7" height="18" rx="1"/>
            <rect x="14" y="3" width="7" height="18" rx="1"/>
            <path d="M5 7h3M5 11h3M5 15h3M16 7h3M16 11h3M16 15h3"/>
          </svg>
        </div>
        {!collapsed && <div className="brand-text"><div className="brand-name">DCIM</div><div className="brand-sub">v1.0 · ops</div></div>}
      </div>
      <nav className="nav-list">
        {items.map(it => (
          <a key={it.id} className={`nav-item ${it.active ? "active" : ""}`} href="#">
            <span className="nav-icon"><Icon name={it.id}/></span>
            {!collapsed && <span className="nav-label">{it.label}</span>}
            {!collapsed && it.badge && <span className={`nav-badge ${it.badgeColor || ""}`}>{it.badge}</span>}
          </a>
        ))}
      </nav>
      <div className="nav-foot">
        <button className="nav-collapse" onClick={() => setCollapsed(c => !c)}>
          <Icon name="chevron"/>
          {!collapsed && <span>Collapse</span>}
        </button>
      </div>
    </aside>
  );
}

// ---------- Topbar ----------
function Topbar({ theme, setTheme }) {
  return (
    <header className="topbar">
      <div className="breadcrumb">
        <a href="#">Site mars-7</a>
        <span className="bc-sep">/</span>
        <a href="#">Rooms</a>
        <span className="bc-sep">/</span>
        <span className="bc-current">Hall B — Production</span>
      </div>
      <div className="topbar-search">
        <Icon name="search" size={14}/>
        <input placeholder="Search hostname, IP, serial, rack…"/>
        <kbd>⌘K</kbd>
      </div>
      <div className="topbar-actions">
        <button className="icon-btn" onClick={() => setTheme(t => t === "dark" ? "light" : "dark")} title="Theme">
          <Icon name={theme === "dark" ? "sun" : "moon"}/>
        </button>
        <button className="icon-btn" title="Notifications">
          <Icon name="bell"/>
          <span className="dot"></span>
        </button>
        <div className="user-chip">
          <div className="avatar">MC</div>
          <div className="user-meta">
            <div className="user-name">M. Cooper</div>
            <div className="user-role">Admin</div>
          </div>
        </div>
      </div>
    </header>
  );
}

// ---------- Layer toggle / segmented ----------
const LAYERS = [
  { id: "u", label: "Occupation U", icon: "rack" },
  { id: "w", label: "Load", icon: "bolt" },
  { id: "t", label: "Temperature", icon: "thermo" },
  { id: "a", label: "Alerts", icon: "alerts" },
];

function LayerToggle({ value, onChange }) {
  return (
    <div className="layer-toggle" role="tablist" aria-label="Vue de couche">
      {LAYERS.map(l => (
        <button key={l.id} role="tab" aria-selected={value === l.id} className={value === l.id ? "active" : ""} onClick={() => onChange(l.id)}>
          <Icon name={l.icon} size={14}/>
          <span>{l.label}</span>
        </button>
      ))}
    </div>
  );
}

// ---------- Legend ----------
function Legend({ layer }) {
  if (layer === "u" || layer === "w") {
    const labels = layer === "u" ? ["0U", "21U", "30U", "36U", "42U"] : ["0", "3.2", "4.5", "5.4", "6.4 kW"];
    const stops = [0.05, 0.4, 0.65, 0.78, 0.95];
    return (
      <div className="legend">
        <div className="legend-title">{layer === "u" ? "Taux d'occupation" : "Load électrique"}</div>
        <div className="legend-bar">
          {stops.map((s, i) => <span key={i} style={{ background: ratioColor(s) }}/>)}
        </div>
        <div className="legend-labels">
          {labels.map((l, i) => <span key={i}>{l}</span>)}
        </div>
      </div>
    );
  }
  if (layer === "t") {
    return (
      <div className="legend">
        <div className="legend-title">Temperature polled</div>
        <div className="legend-bar">
          <span style={{ background: tempColor(20) }}/>
          <span style={{ background: tempColor(23) }}/>
          <span style={{ background: tempColor(26) }}/>
          <span style={{ background: tempColor(30) }}/>
        </div>
        <div className="legend-labels"><span>&lt;22°C</span><span>22-25</span><span>25-28</span><span>&gt;28°C</span></div>
      </div>
    );
  }
  return (
    <div className="legend">
      <div className="legend-title">Status alert</div>
      <div className="legend-chips">
        <span className="chip"><i style={{ background: alertColor("ok") }}/>OK</span>
        <span className="chip"><i style={{ background: alertColor("warning") }}/>Warning</span>
        <span className="chip"><i style={{ background: alertColor("critical") }}/>Critical</span>
      </div>
    </div>
  );
}

// ---------- Right detail panel ----------
function DetailPanel({ rack, racks, onClose }) {
  if (!rack) {
    // KPIs
    const totalU = racks.reduce((a, r) => a + r.u_total, 0);
    const usedU = racks.reduce((a, r) => a + r.u_used, 0);
    const totalW = racks.reduce((a, r) => a + r.w_used, 0);
    const maxW = racks.reduce((a, r) => a + r.w_max, 0);
    const temps = racks.map(r => r.temp);
    const alerts = racks.filter(r => r.alerts !== "ok").length;
    return (
      <aside className="detail-panel">
        <div className="dp-section">
          <div className="dp-section-title">Hall B — Production</div>
          <div className="dp-section-sub">Site mars-7 · DC tiers · 30 racks</div>
        </div>
        <div className="kpi-grid">
          <div className="kpi-card">
            <div className="kpi-label">BAIES</div>
            <div className="kpi-value">{racks.length}<span className="kpi-suffix">/30</span></div>
            <div className="kpi-sub">28 actives · 2 reservedes</div>
          </div>
          <div className="kpi-card">
            <div className="kpi-label">OCCUPATION U</div>
            <div className="kpi-value">{Math.round(usedU / totalU * 100)}<span className="kpi-suffix">%</span></div>
            <div className="kpi-bar"><div style={{ width: `${usedU/totalU*100}%`, background: ratioColor(usedU/totalU) }}/></div>
          </div>
          <div className="kpi-card">
            <div className="kpi-label">CHARGE</div>
            <div className="kpi-value">{(totalW / 1000).toFixed(1)}<span className="kpi-suffix">/{(maxW/1000).toFixed(0)} kW</span></div>
            <div className="kpi-bar"><div style={{ width: `${totalW/maxW*100}%`, background: ratioColor(totalW/maxW) }}/></div>
          </div>
          <div className="kpi-card">
            <div className="kpi-label">ALERTES</div>
            <div className="kpi-value" style={{ color: alerts > 0 ? "var(--danger)" : "var(--ok)" }}>{alerts}</div>
            <div className="kpi-sub">{alerts > 0 ? "Action requise" : "All est OK"}</div>
          </div>
        </div>
        <div className="dp-section">
          <div className="dp-section-title">Temperatures</div>
          <div className="temp-row">
            <div><span className="t-label">min</span><span className="t-val">{Math.min(...temps)}°</span></div>
            <div><span className="t-label">moy</span><span className="t-val">{Math.round(temps.reduce((a,b)=>a+b,0)/temps.length)}°</span></div>
            <div><span className="t-label">max</span><span className="t-val" style={{ color: tempColor(Math.max(...temps)) }}>{Math.max(...temps)}°</span></div>
          </div>
        </div>
        <div className="dp-section">
          <div className="dp-section-title">Recent activity</div>
          <ul className="activity">
            <li><span className="a-time">12 min</span><span>Ticket #2841 open sur <b>mercury-14</b></span></li>
            <li><span className="a-time">1h</span><span>Alert temp acknowledged sur <b>titan-33</b></span></li>
            <li><span className="a-time">3h</span><span>Équipement <b>srv-lyon-prod-12</b> added en mars-04</span></li>
          </ul>
        </div>
        <div className="dp-hint">Cliquez sur une rack pour view son detail</div>
      </aside>
    );
  }

  const uPct = rack.u_used / rack.u_total;
  const wPct = rack.w_used / rack.w_max;

  return (
    <aside className="detail-panel">
      <div className="dp-head">
        <div>
          <div className="dp-title">{rack.id}</div>
          <div className="dp-sub">Row {rack.row} · Position {rack.col + 1} · 42U</div>
        </div>
        <button className="icon-btn small" onClick={onClose}><Icon name="close" size={14}/></button>
      </div>

      <div className={`dp-status status-${rack.alerts}`}>
        {rack.alerts === "ok" ? "No alert active" : rack.alerts === "warning" ? "1 alert warning active" : "1 alert critical active"}
      </div>

      <MiniRack rack={rack}/>

      <div className="dp-metrics">
        <div className="metric">
          <div className="metric-head">
            <span className="metric-label">Occupation</span>
            <span className="metric-val">{rack.u_used}/{rack.u_total} U</span>
          </div>
          <div className="metric-bar"><div style={{ width: `${uPct*100}%`, background: ratioColor(uPct) }}/></div>
          <div className="metric-foot">{rack.u_total - rack.u_used} U availables · plus grand bloc contigu : 4 U</div>
        </div>
        <div className="metric">
          <div className="metric-head">
            <span className="metric-label">Load</span>
            <span className="metric-val">{(rack.w_used/1000).toFixed(2)}/{(rack.w_max/1000).toFixed(1)} kW</span>
          </div>
          <div className="metric-bar"><div style={{ width: `${wPct*100}%`, background: ratioColor(wPct) }}/></div>
          <div className="metric-foot">PDU A : {(rack.w_used*0.52/1000).toFixed(2)} kW · PDU B : {(rack.w_used*0.48/1000).toFixed(2)} kW · équifree OK</div>
        </div>
        <div className="metric">
          <div className="metric-head">
            <span className="metric-label">Temperature</span>
            <span className="metric-val" style={{ color: tempColor(rack.temp) }}>{rack.temp}°C</span>
          </div>
          <div className="sbykline">
            {Array.from({length: 24}).map((_, i) => {
              const h = 30 + Math.sin(i / 3 + rack.col) * 8 + (rack.temp - 24) * 1.5 + (i === 23 ? 4 : 0);
              return <span key={i} style={{ height: `${h}%`, background: tempColor(rack.temp) }}/>;
            })}
          </div>
          <div className="metric-foot">24h · probe high</div>
        </div>
      </div>

      <div className="dp-actions">
        <button className="btn primary"><Icon name="arrow" size={14}/>View la rack</button>
        <button className="btn"><Icon name="ticket" size={14}/>Open un ticket</button>
      </div>

      <div className="dp-section dense">
        <div className="dp-section-title">Équipements recent</div>
        <ul className="eq-list">
          <li><span className="eq-u">U38</span><span className="eq-name">switch-lyon-b-02</span><span className="eq-type">switch</span></li>
          <li><span className="eq-u">U30</span><span className="eq-name">srv-lyon-prod-{rack.col + 12}</span><span className="eq-type">server</span></li>
          <li><span className="eq-u">U28</span><span className="eq-name">srv-lyon-prod-{rack.col + 13}</span><span className="eq-type">server</span></li>
          <li><span className="eq-u">U24</span><span className="eq-name">san-lyon-{rack.row}-{rack.col}</span><span className="eq-type">stockage</span></li>
        </ul>
      </div>
    </aside>
  );
}

// ---------- Edit toolbar ----------
function EditToolbar({ tool, setTool, onAddRack, onAddWall, onAddDoor, onSave, onCancel }) {
  return (
    <div className="edit-toolbar">
      <div className="edit-tools">
        <button className={tool === "select" ? "active" : ""} onClick={() => setTool("select")}><Icon name="grip"/>Selection</button>
        <button className={tool === "rack" ? "active" : ""} onClick={() => { setTool("rack"); onAddRack(); }}><Icon name="rack"/>Rack</button>
        <button className={tool === "wall" ? "active" : ""} onClick={() => { setTool("wall"); onAddWall(); }}><Icon name="wall"/>Mur</button>
        <button className={tool === "door" ? "active" : ""} onClick={() => { setTool("door"); onAddDoor(); }}><Icon name="door"/>Porte</button>
      </div>
      <div className="edit-actions">
        <button className="btn ghost" onClick={onCancel}>Cancel</button>
        <button className="btn primary" onClick={onSave}>Save le layout</button>
      </div>
    </div>
  );
}

// ---------- Main App ----------
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "aesthetic": "ops",
  "density": "comfort",
  "accent": "#22d3a8"
}/*EDITMODE-END*/;

function App() {
  const [theme, setTheme] = useState("dark");
  const [layer, setLayer] = useState("u");
  const [selectedId, setSelectedId] = useState(null);
  const [navCollapsed, setNavCollapsed] = useState(false);
  const [editMode, setEditMode] = useState(false);
  const [tool, setTool] = useState("select");
  const [racks, setRacks] = useState(RACKS);
  const [walls, setWalls] = useState(WALLS);
  const [doors, setDoors] = useState(DOORS);

  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
    document.documentElement.setAttribute("data-aesthetic", t.aesthetic);
    document.documentElement.style.setProperty("--accent", t.accent);
  }, [theme, t.aesthetic, t.accent]);

  const selectedRack = useMemo(() => racks.find(r => r.id === selectedId), [racks, selectedId]);

  return (
    <div className="app" data-screen-label="Room view — Plan schematic">
      <NavSidebar collapsed={navCollapsed} setCollapsed={setNavCollapsed}/>
      <div className="main">
        <Topbar theme={theme} setTheme={setTheme}/>
        <div className="content">
          <div className="canvas-area">
            <div className="canvas-head">
              <div className="canvas-title">
                <h1>Hall B — Production</h1>
                <div className="canvas-meta">
                  <span className="badge ghost">DC tiers</span>
                  <span className="meta-sep">·</span>
                  <span>30 racks · 4 rows</span>
                  <span className="meta-sep">·</span>
                  <span>SNMP : active</span>
                  <span className="dot-pulse"/>
                </div>
              </div>
              <div className="canvas-head-right">
                <LayerToggle value={layer} onChange={setLayer}/>
                <button className={`btn ${editMode ? "primary" : "ghost"}`} onClick={() => setEditMode(e => !e)}>
                  <Icon name="edit" size={14}/>
                  {editMode ? "Quit l'edit" : "Edit mode"}
                </button>
              </div>
            </div>

            {editMode && (
              <EditToolbar
                tool={tool}
                setTool={setTool}
                onAddRack={() => {}}
                onAddWall={() => {}}
                onAddDoor={() => {}}
                onSave={() => { setEditMode(false); }}
                onCancel={() => { setEditMode(false); }}
              />
            )}

            <FloorPlan
              layer={layer}
              selectedId={selectedId}
              onSelect={setSelectedId}
              editMode={editMode}
              racks={racks}
              setRacks={setRacks}
              walls={walls}
              setWalls={setWalls}
              doors={doors}
              tool={tool}
              density={t.density}
            />

            <Legend layer={layer}/>
          </div>

          <DetailPanel rack={selectedRack} racks={racks} onClose={() => setSelectedId(null)}/>
        </div>
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Direction aesthetic">
          <TweakRadio label="Style" value={t.aesthetic}
            options={["ops", "linear", "industrial"]}
            onChange={(v) => setTweak("aesthetic", v)}/>
        </TweakSection>
        <TweakSection label="Density">
          <TweakRadio label="Plan" value={t.density}
            options={["compact", "comfort", "spacious"]}
            onChange={(v) => setTweak("density", v)}/>
        </TweakSection>
        <TweakSection label="Couleur d'accent">
          <TweakColor label="Accent" value={t.accent}
            options={["#22d3a8", "#5b8def", "#f59e0b", "#e879f9"]}
            onChange={(v) => setTweak("accent", v)}/>
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
