/* global React */
/* ===========================================================
   VOLTLAB · MONTAGEM DE QUADROS ELÉTRICOS  (v2)
   Editor de posição livre na placa de montagem  +  geração do
   DESENHO TÉCNICO (Frontal · Interna · Lateral) exportável em PNG.
   Depende de window.QM (painel/qm-core.js) e window.PE.
=========================================================== */
const { useState, useRef, useEffect, useMemo, useCallback } = React;

const qmPersist = (k, init) => (window.useLocalStorage ? window.useLocalStorage(k, init) : React.useState(init));

const QM_LIB     = () => window.QM?.COMP_LIB || {};
const QM_GROUPS  = () => window.QM?.GROUPS || [];
const QM_PRESETS = () => window.QM?.PRESETS || [];

/* ---- ícones ---- */
const QmIcon = ({ name, size = 16 }) => {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    image:    <><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></>,
    download: <><path d="M12 3v12"/><polyline points="7 10 12 15 17 10"/><line x1="4" y1="21" x2="20" y2="21"/></>,
    trash:    <><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6"/></>,
    grid:     <><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/></>,
    ruler:    <><path d="M3 17L17 3l4 4L7 21z"/><path d="M7 11l2 2M11 7l2 2M15 11l1 1"/></>,
    edit:     <><path d="M12 20h9"/><path d="M16.5 3.5a2.1 2.1 0 013 3L7 19l-4 1 1-4z"/></>,
    list:     <><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></>,
    close:    <><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></>,
  };
  return <svg {...p}>{paths[name]}</svg>;
};

/* ===========================================================
   TAG automática
=========================================================== */
function nextTag(type, items) {
  const d = QM_LIB()[type]; if (!d) return "X1";
  let n = 0;
  items.forEach((c) => { const m = (c.tag || "").match(new RegExp(`^${d.tag}(\\d+)$`)); if (m) n = Math.max(n, +m[1]); });
  return `${d.tag}${n + 1}`;
}

/* ===========================================================
   RENDER DE UM COMPONENTE NO EDITOR (coordenadas em mm)
=========================================================== */
function EditorItem({ item, def, size, selected, onPointerDown }) {
  const { w, h } = size;
  const c = def.color;
  const term = (cx, cy, r) => <circle cx={cx} cy={cy} r={r} fill="#fff" stroke="rgba(0,0,0,.45)" strokeWidth={1.1} />;
  let body = null;

  if (def.family === "mcb") {
    const pitch = w / def.poles;
    body = (
      <g>
        <rect x={0} y={h * 0.28} width={w} height={h * 0.44} rx={3} fill={c} stroke="rgba(255,255,255,.18)" strokeWidth={1} />
        {Array.from({ length: def.poles }).map((_, i) => (
          <g key={i}>
            {i > 0 && <line x1={pitch * i} y1={h * 0.28} x2={pitch * i} y2={h * 0.72} stroke="rgba(0,0,0,.35)" strokeWidth={0.8} />}
            {term(pitch * (i + 0.5), h * 0.1, Math.min(pitch * 0.18, h * 0.06))}
            {term(pitch * (i + 0.5), h * 0.9, Math.min(pitch * 0.18, h * 0.06))}
            <rect x={pitch * (i + 0.5) - pitch * 0.14} y={h * 0.44} width={pitch * 0.28} height={h * 0.12} rx={2} fill="rgba(255,255,255,.85)" />
          </g>
        ))}
      </g>
    );
  } else if (def.family === "mccb") {
    body = (
      <g>
        <rect x={0} y={h * 0.14} width={w} height={h * 0.72} rx={5} fill="#eef1f4" stroke="rgba(0,0,0,.35)" strokeWidth={1.2} />
        <rect x={w * 0.27} y={h * 0.32} width={w * 0.46} height={h * 0.36} rx={3} fill="#3a3d44" />
        <rect x={w * 0.42} y={h * 0.40} width={w * 0.16} height={h * 0.2} rx={2} fill="#cfd4da" />
        {[0, 1, 2].map((i) => (<g key={i}>{term(w * (0.25 + 0.25 * i), h * 0.07, w * 0.05)}{term(w * (0.25 + 0.25 * i), h * 0.93, w * 0.05)}</g>))}
      </g>
    );
  } else if (def.family === "surge") {
    body = (
      <g>
        <rect x={0} y={0} width={w} height={h} rx={3} fill="url(#qmHatch)" stroke={c} strokeWidth={1.8} />
        {Array.from({ length: def.bars || 4 }).map((_, i) => {
          const bx = w * (0.16 + 0.68 * i / ((def.bars || 4) - 1));
          return <line key={i} x1={bx} y1={h * 0.1} x2={bx} y2={h * 0.78} stroke="#ff7a00" strokeWidth={2.2} />;
        })}
        {[0, 1, 2].map((i) => <g key={i}>{term(w * (0.25 + 0.25 * i), h * 0.9, w * 0.06)}</g>)}
      </g>
    );
  } else if (def.family === "rail") {
    const slots = Math.max(2, Math.round(w / 30));
    body = (
      <g>
        <rect x={0} y={0} width={w} height={h} rx={2} fill="#c2c8d0" stroke="#7d8590" strokeWidth={1} />
        <rect x={0} y={0} width={w} height={h * 0.24} fill="#aab0b8" />
        <rect x={0} y={h * 0.76} width={w} height={h * 0.24} fill="#aab0b8" />
        {Array.from({ length: slots }).map((_, i) => (
          <rect key={i} x={(w / slots) * (i + 0.5) - (w / slots) * 0.16} y={h * 0.34} width={(w / slots) * 0.32} height={h * 0.34} rx={1.5} fill="#7d8590" />
        ))}
      </g>
    );
  } else if (def.family === "busbar") {
    body = (
      <g>
        <rect x={0} y={0} width={w} height={h} rx={3} fill="#fff6cc" stroke="none" />
        <line x1={0} y1={1.5} x2={w} y2={1.5} stroke={c} strokeWidth={3} />
        <line x1={0} y1={h - 1.5} x2={w} y2={h - 1.5} stroke={c} strokeWidth={3} />
        <text x={w / 2} y={h / 2} textAnchor="middle" dominantBaseline="central" fontSize={Math.min(h * 0.5, 22)} fontFamily="var(--ff-mono)" fill="#9a7b00" letterSpacing="0.12em">CANALETA</text>
      </g>
    );
  } else if (def.family === "termH" || def.family === "termV") {
    const vertical = def.family === "termV";
    const n = window.QM.termCount(item);
    const cells = Array.from({ length: n });
    body = (
      <g>
        <rect x={0} y={0} width={w} height={h} rx={3} fill={c} stroke="rgba(255,255,255,.2)" strokeWidth={1} />
        {cells.map((_, i) => {
          const cx = vertical ? w / 2 : (w / n) * (i + 0.5);
          const cy = vertical ? (h / n) * (i + 0.5) : h / 2;
          return (
            <g key={i}>
              {i > 0 && (vertical
                ? <line x1={2} y1={(h / n) * i} x2={w - 2} y2={(h / n) * i} stroke="rgba(0,0,0,.3)" strokeWidth={0.8} />
                : <line x1={(w / n) * i} y1={2} x2={(w / n) * i} y2={h - 2} stroke="rgba(0,0,0,.3)" strokeWidth={0.8} />)}
              {term(cx, cy, Math.min(vertical ? w * 0.2 : (w / n) * 0.22, h * 0.3))}
            </g>
          );
        })}
      </g>
    );
  } else { // block
    body = (
      <g>
        <rect x={0} y={h * 0.12} width={w} height={h * 0.76} rx={4} fill={c} stroke="rgba(255,255,255,.18)" strokeWidth={1} />
        {Array.from({ length: def.poles || 3 }).map((_, i) => {
          const cx = w * ((i + 0.5) / (def.poles || 3));
          return <g key={i}>{term(cx, h * 0.06, Math.min(w / (def.poles || 3) * 0.16, h * 0.05))}{term(cx, h * 0.94, Math.min(w / (def.poles || 3) * 0.16, h * 0.05))}</g>;
        })}
        {def.label2 && <text x={w / 2} y={h / 2} textAnchor="middle" dominantBaseline="central" fontSize={Math.min(h * 0.26, w * 0.5)} fontFamily="var(--ff-mono)" fontWeight="700" fill="#fff">{def.label2}</text>}
      </g>
    );
  }

  return (
    <g transform={`translate(${item.x},${item.y})`} onPointerDown={onPointerDown} style={{ cursor: "grab" }}>
      {body}
      {def.family !== "busbar" && def.family !== "rail" && item.tag && (
        <text x={w / 2} y={-7} textAnchor="middle" fontSize={24} fontFamily="var(--ff-mono)" fontWeight="600" fill={selected ? "var(--accent)" : "#cfe3ff"}>{item.tag}</text>
      )}
      {selected && <rect x={-6} y={-6} width={w + 12} height={h + 12} rx={5} fill="none" stroke="var(--accent)" strokeWidth={2} strokeDasharray="7 5" />}
    </g>
  );
}

/* ===========================================================
   CANVAS DO EDITOR — placa de montagem, posição livre
=========================================================== */
function PlateEditor({ preset, items, selectedId, armedType, snap50, ovl, onOvlMove, onSelect, onMove, onPlace, onCommit }) {
  const svgRef = useRef(null);
  const dragRef = useRef(null);
  const plate = window.QM.plateSize(preset);
  const step = snap50 ? 50 : 1;   // 1mm = arraste suave, contínuo

  const toMM = (e) => {
    const svg = svgRef.current; if (!svg) return { x: 0, y: 0 };
    const pt = svg.createSVGPoint(); pt.x = e.clientX; pt.y = e.clientY;
    const ctm = svg.getScreenCTM(); if (!ctm) return { x: 0, y: 0 };
    const p = pt.matrixTransform(ctm.inverse());
    return { x: p.x, y: p.y };
  };
  const snap = (v) => Math.round(v / step) * step;
  const snapRail = (x, y, s, family, skipId) => {
    if (family === "rail" || family === "busbar") return y;
    const clipY = y + s.h * 0.5; let best = null, bestD = 46;
    items.forEach((r) => {
      if (r.id === skipId) return;
      const rd = QM_LIB()[r.type]; if (!rd || rd.family !== "rail") return;
      const rs = window.QM.itemSize(r); const rCy = r.y + rs.h / 2;
      if (x + s.w < r.x || x > r.x + rs.w) return;
      const dd = Math.abs(clipY - rCy); if (dd < bestD) { bestD = dd; best = rCy; }
    });
    if (best == null) return y;
    return Math.max(0, Math.min(plate.h - s.h, Math.round(best - s.h * 0.5)));
  };

  const onItemDown = (item) => (e) => {
    e.stopPropagation();
    if (armedType) return;
    onSelect(item.id);
    const m = toMM(e);
    dragRef.current = { id: item.id, offx: m.x - item.x, offy: m.y - item.y, moved: false };
    svgRef.current.setPointerCapture?.(e.pointerId);
  };
  const onOvlDown = (e) => {
    if (armedType || !ovl || ovl.locked) return;
    e.stopPropagation();
    const m = toMM(e);
    dragRef.current = { id: "__ovl", offx: m.x - ovl.x, offy: m.y - ovl.y, moved: false };
    svgRef.current.setPointerCapture?.(e.pointerId);
  };
  const onSvgMove = (e) => {
    const d = dragRef.current; if (!d) return;
    const m = toMM(e);
    if (d.id === "__ovl") { d.moved = true; onOvlMove(Math.round(m.x - d.offx), Math.round(m.y - d.offy)); return; }
    const it = items.find((i) => i.id === d.id); if (!it) return;
    const s = window.QM.itemSize(it);
    const fam = QM_LIB()[it.type]?.family;
    let x = snap(m.x - d.offx), y = snap(m.y - d.offy);
    x = Math.max(0, Math.min(plate.w - s.w, x));
    y = Math.max(0, Math.min(plate.h - s.h, y));
    y = snapRail(x, y, s, fam, it.id);
    d.moved = true;
    onMove(d.id, x, y);
  };
  const endDrag = () => { if (dragRef.current?.moved) onCommit?.(); dragRef.current = null; };

  const onSvgDown = (e) => {
    if (!armedType) { onSelect(null); return; }
    const m = toMM(e);
    const d = QM_LIB()[armedType];
    const s = window.QM.itemSize({ type: armedType });
    let x = snap(m.x - s.w / 2), y = snap(m.y - s.h / 2);
    x = Math.max(0, Math.min(plate.w - s.w, x));
    y = Math.max(0, Math.min(plate.h - s.h, y));
    y = snapRail(x, y, s, d.family, null);
    onPlace(armedType, x, y);
  };

  const GRID = 50;
  const vLines = []; for (let gx = GRID; gx < plate.w; gx += GRID) vLines.push(gx);
  const hLines = []; for (let gy = GRID; gy < plate.h; gy += GRID) hLines.push(gy);

  return (
    <div style={{ height: "min(72vh, 700px)", background: "#0e1014", borderRadius: 10, border: "1px solid var(--border)", display: "grid", placeItems: "center", padding: 18, overflow: "hidden" }}>
      <svg ref={svgRef} viewBox={`-20 -40 ${plate.w + 40} ${plate.h + 60}`} style={{ height: "100%", width: "auto", maxWidth: "100%", cursor: armedType ? "crosshair" : "default", touchAction: "none" }}
        onPointerDown={onSvgDown} onPointerMove={onSvgMove} onPointerUp={endDrag} onPointerLeave={endDrag}>
        <defs>
          <pattern id="qmHatch" width="14" height="14" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
            <rect width="14" height="14" fill="rgba(192,31,159,.1)" />
            <line x1="0" y1="0" x2="0" y2="14" stroke="#c01f9f" strokeWidth="1.5" />
          </pattern>
        </defs>

        {/* placa de montagem (cyan) */}
        <rect x={0} y={0} width={plate.w} height={plate.h} fill="#0a1418" stroke="#15b8c9" strokeWidth={3} />
        {ovl && ovl.visible && ovl.src && (
          <image href={ovl.src} x={ovl.x} y={ovl.y} width={plate.w * (ovl.scale || 1)} height={plate.h * (ovl.scale || 1)}
            preserveAspectRatio="xMidYMid meet" opacity={ovl.opacity} onPointerDown={onOvlDown}
            style={{ pointerEvents: (ovl.locked || armedType) ? "none" : "auto", cursor: "move" }} />
        )}
        {ovl && !ovl.locked && ovl.visible && (
          <rect x={ovl.x} y={ovl.y} width={plate.w * (ovl.scale || 1)} height={plate.h * (ovl.scale || 1)} fill="none" stroke="var(--accent)" strokeWidth={1.5} strokeDasharray="6 4" pointerEvents="none" />
        )}
        {vLines.map((gx) => <line key={"v" + gx} x1={gx} y1={0} x2={gx} y2={plate.h} stroke="#15b8c9" strokeWidth={0.7} opacity={0.32} />)}
        {hLines.map((gy) => <line key={"h" + gy} x1={0} y1={gy} x2={plate.w} y2={gy} stroke="#15b8c9" strokeWidth={0.7} opacity={0.32} />)}

        <text x={plate.w / 2} y={-14} textAnchor="middle" fontSize={26} fontFamily="var(--ff-mono)" fill="#15b8c9" letterSpacing="0.12em" opacity={0.8}>
          PLACA DE MONTAGEM · {plate.w} × {plate.h} mm
        </text>

        {[...items].sort((a, b) => ((QM_LIB()[a.type]?.family === "rail" ? 0 : 1) - (QM_LIB()[b.type]?.family === "rail" ? 0 : 1))).map((it) => {
          const def = QM_LIB()[it.type]; if (!def) return null;
          return <EditorItem key={it.id} item={it} def={def} size={window.QM.itemSize(it)} selected={selectedId === it.id} onPointerDown={onItemDown(it)} />;
        })}
      </svg>
    </div>
  );
}

/* ===========================================================
   ITEM DA PALETA
=========================================================== */
const QmPaletteItem = ({ type, def, active, onClick }) => (
  <button onClick={onClick} title={`${def.label} · ${def.w}×${def.h} mm`}
    style={{ display: "flex", alignItems: "center", gap: 10, padding: "7px 9px", borderRadius: 6, width: "100%", textAlign: "left",
      background: active ? "var(--accent-soft)" : "transparent",
      border: active ? "1px solid oklch(72% 0.18 245/0.35)" : "1px solid transparent",
      color: active ? "var(--accent)" : "var(--fg-dim)", cursor: "pointer", transition: "all .15s" }}>
    <span style={{ width: 26, height: 26, borderRadius: 4, background: def.color, flexShrink: 0, border: "1px solid rgba(255,255,255,.12)" }} />
    <span style={{ flex: 1, minWidth: 0 }}>
      <span style={{ display: "block", fontSize: 12, fontWeight: 500, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{def.label}</span>
      <span style={{ display: "block", fontSize: 10, fontFamily: "var(--ff-mono)", color: "var(--fg-mute)" }}>{def.w}×{def.h} mm</span>
    </span>
  </button>
);

/* ===========================================================
   DESENHO TÉCNICO — 3 vistas + exportação
=========================================================== */
function TecnicoView({ config }) {
  const svgRef = useRef(null);
  const [showCotas, setCotas] = useState(true);
  const [showGrid, setGrid] = useState(true);
  const [showTags, setTags] = useState(true);
  const [lw, setLw] = useState(1);
  const [busy, setBusy] = useState(false);

  useEffect(() => {
    if (!svgRef.current || !window.QM) return;
    window.PE.CONFIG.lwScale = lw;
    window.QM.buildPanelFromConfig(svgRef.current, config, { showCotas, showGrid, showTags });
  }, [config, showCotas, showGrid, showTags, lw]);

  const opts = { showCotas, showGrid, showTags };
  const doPNG = async () => { setBusy(true); window.PE.CONFIG.lwScale = lw; try { await window.QM.exportPNG(config, opts, "quadro-eletrico.png"); } finally { setBusy(false); } };
  const doSVG = () => { window.PE.CONFIG.lwScale = lw; window.QM.exportSVG(config, opts, "quadro-eletrico.svg"); };

  const Toggle = ({ on, set, children }) => (
    <button onClick={() => set(!on)} style={{ display: "inline-flex", alignItems: "center", gap: 7, padding: "6px 11px", borderRadius: 7, cursor: "pointer",
      fontFamily: "var(--ff-mono)", fontSize: 10, letterSpacing: ".06em", border: "1px solid", transition: "all .15s",
      color: on ? "var(--accent)" : "var(--fg-mute)", background: on ? "var(--accent-soft)" : "transparent", borderColor: on ? "oklch(72% 0.18 245/0.3)" : "var(--border)" }}>
      <span style={{ width: 7, height: 7, borderRadius: "50%", background: "currentColor", opacity: on ? 1 : 0.5 }} />{children}
    </button>
  );

  return (
    <div className="panel">
      <div className="panel-head" style={{ marginBottom: 14, flexWrap: "wrap", gap: 12 }}>
        <div><div className="panel-eyebrow">DESENHO TÉCNICO · 3 VISTAS</div><h3>Frontal · Interna · Lateral</h3></div>
        <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
          <Toggle on={showCotas} set={setCotas}>COTAS</Toggle>
          <Toggle on={showGrid} set={setGrid}>GRADE</Toggle>
          <Toggle on={showTags} set={setTags}>TAGS</Toggle>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontFamily: "var(--ff-mono)", fontSize: 10, color: "var(--fg-mute)" }}>
            TRAÇO<input type="range" min="0.5" max="2" step="0.1" value={lw} onChange={(e) => setLw(+e.target.value)} style={{ width: 90, accentColor: "var(--accent)" }} />
          </span>
          <button className="btn btn-sm" onClick={doSVG}><QmIcon name="download" size={13} /> SVG</button>
          <button className="btn btn-sm btn-primary" onClick={doPNG} disabled={busy} style={{ opacity: busy ? 0.6 : 1 }}><QmIcon name="image" size={13} /> {busy ? "Gerando…" : "Exportar PNG"}</button>
        </div>
      </div>
      <div style={{ background: "#fff", borderRadius: 6, padding: "18px 14px", boxShadow: "0 10px 40px rgba(0,0,0,.4)", overflow: "auto" }}>
        <svg ref={svgRef} style={{ display: "block", width: "100%", height: "auto" }} />
      </div>
      <div className="vl-banner vl-banner-info" style={{ marginTop: 14, fontSize: 12 }}>
        As três vistas são geradas automaticamente da sua montagem. O PNG sai com fundo branco (papel), em alta resolução, pronto para o projeto.
      </div>
    </div>
  );
}

/* ===========================================================
   MÓDULO PRINCIPAL
=========================================================== */
const QuadroMontagem = () => {
  const ready = !!window.QM;
  const [presetKey, setPresetKey] = qmPersist("vl_qm2_preset", "p800b");
  const [items, setItems]         = qmPersist("vl_qm2_items", null);
  const [view, setView]           = useState("editor"); // editor | tecnico
  const [armed, setArmed]         = useState(null);
  const [selId, setSelId]         = useState(null);
  const [snap50, setSnap50]       = useState(false);
  const [seeded, setSeeded]       = useState(false);
  const [custom, setCustom]       = qmPersist("vl_qm2_custom", { W: 800, H: 1200, D: 250 });
  const [ovl, setOvl]             = useState(null);
  const [showMat, setShowMat]     = useState(false);

  // semeia o exemplo inicial (uma vez)
  useEffect(() => {
    if (!ready || seeded) return;
    if (items == null) { const ex = window.QM.defaultExample(); setPresetKey(ex.presetKey); setItems(ex.items); }
    setSeeded(true);
  }, [ready, seeded]); // eslint-disable-line

  const list = items || [];
  const dims = presetKey === "custom"
    ? { W: +custom.W || 600, H: +custom.H || 800, D: +custom.D || 250 }
    : (ready ? window.QM.presetByKey(presetKey) : { W: 800, H: 1200, D: 250 });
  const dimLabel = `${dims.W} × ${dims.H} × ${dims.D}`;
  const LIB = QM_LIB();
  const config = useMemo(() => ({ presetKey, dims, items: list }), [presetKey, dims.W, dims.H, dims.D, list]);
  const selected = list.find((i) => i.id === selId) || null;

  const placeComp = (type, x, y) => {
    setItems((prev) => { const arr = prev || []; const it = { id: "c" + Date.now().toString(36), type, x, y, tag: nextTag(type, arr) }; const d = LIB[type]; if (d?.lengthAdjustable) it.len = d.vertical ? d.h : d.w; return [...arr, it]; });
    setArmed(null);
  };
  const moveComp = (id, x, y) => setItems((prev) => (prev || []).map((i) => (i.id === id ? { ...i, x, y } : i)));
  const updateComp = (patch) => setItems((prev) => (prev || []).map((i) => (i.id === selId ? { ...i, ...patch } : i)));
  const removeComp = () => { setItems((prev) => (prev || []).filter((i) => i.id !== selId)); setSelId(null); };
  const clearAll = () => { if (window.confirm("Limpar toda a montagem?")) { setItems([]); setSelId(null); } };
  const loadExample = () => { if (window.confirm("Carregar o exemplo de referência? Isto substitui a montagem atual.")) { const ex = window.QM.defaultExample(); setPresetKey(ex.presetKey); setItems(ex.items); setSelId(null); } };
  const onOvlUpload = (e) => { const f = e.target.files?.[0]; if (!f) return; const r = new FileReader(); r.onload = () => setOvl({ src: r.result, x: 0, y: 0, scale: 1, opacity: 0.55, visible: true, locked: true }); r.readAsDataURL(f); e.target.value = ""; };

  // teclado: Delete remove selecionado
  useEffect(() => {
    const h = (e) => { if ((e.key === "Delete" || e.key === "Backspace") && selId && view === "editor" && document.activeElement?.tagName !== "INPUT") { e.preventDefault(); removeComp(); } };
    window.addEventListener("keydown", h); return () => window.removeEventListener("keydown", h);
  }); // eslint-disable-line

  // BOM agregada
  const bom = useMemo(() => {
    const map = {};
    list.forEach((c) => { const d = LIB[c.type]; if (!d) return; (map[c.type] = map[c.type] || { def: d, type: c.type, tags: [] }).tags.push(c.tag); });
    return Object.values(map).sort((a, b) => a.def.group.localeCompare(b.def.group));
  }, [list]); // eslint-disable-line

  const exportBOM = () => {
    const rows = list.map((c) => ({ tag: c.tag, tipo: LIB[c.type]?.label, grupo: LIB[c.type]?.group, dim: `${window.QM.itemSize(c).w}×${window.QM.itemSize(c).h}mm`, x: c.x, y: c.y }));
    const m = window.QM.materials(list);
    const resumo = { equipamentos: m.equip, disjuntores: m.disj.qty, disjuntores_modulos: m.disj.mod, contatoras: m.cont, reles_timer: m.rele, dps: m.dps, mccb: m.mccb, bornes_vias: m.bornes, trilho_din_m: m.rail_m, canaleta_m: m.duct_m };
    const blob = new Blob([JSON.stringify({ gabinete: dimLabel, total: rows.length, resumo, bom: rows }, null, 2)], { type: "application/json" });
    const a = document.createElement("a"); a.href = URL.createObjectURL(blob); a.download = "bom-quadro.json"; a.click();
  };

  if (!ready) return <div className="panel" style={{ padding: 28, color: "var(--fg-mute)" }}>Carregando motor de desenho…</div>;

  const usedArea = list.reduce((s, c) => { const z = window.QM.itemSize(c); return s + z.w * z.h; }, 0);
  const plate = window.QM.plateSize(dims);
  const occ = Math.min(100, Math.round((usedArea / (plate.w * plate.h)) * 100));

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap-grid,20px)" }}>

      {/* ── Barra superior ───────────────────────────── */}
      <div className="panel" style={{ padding: "14px 20px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
            <span style={{ fontFamily: "var(--ff-mono)", fontSize: 10, letterSpacing: ".12em", color: "var(--fg-mute)", textTransform: "uppercase" }}>Gabinete</span>
            <select value={presetKey} onChange={(e) => { const v = e.target.value; if (v === "custom") setCustom({ W: dims.W, H: dims.H, D: dims.D }); setPresetKey(v); }}
              style={{ padding: "7px 12px", background: "var(--bg-0)", border: "1px solid var(--border)", borderRadius: 7, color: "var(--fg)", fontFamily: "var(--ff-mono)", fontSize: 12, cursor: "pointer" }}>
              {QM_PRESETS().map((p) => <option key={p.key} value={p.key}>{p.label} mm</option>)}
              <option value="custom">Personalizado…</option>
            </select>
            {presetKey === "custom" ? (
              <div style={{ display: "flex", alignItems: "center", gap: 5 }}>
                {[["W", "L"], ["H", "A"], ["D", "P"]].map(([k, lbl], i) => (
                  <React.Fragment key={k}>
                    {i > 0 && <span style={{ color: "var(--fg-faint)" }}>×</span>}
                    <span style={{ position: "relative", display: "inline-flex", alignItems: "center" }}>
                      <input type="number" value={custom[k]} min={k === "D" ? 100 : 200} max={k === "H" ? 2400 : 2000} step={10}
                        onChange={(e) => setCustom((c) => ({ ...c, [k]: +e.target.value }))}
                        style={{ width: 66, padding: "6px 8px", background: "var(--bg-1)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--fg)", fontFamily: "var(--ff-mono)", fontSize: 12 }} title={lbl} />
                    </span>
                  </React.Fragment>
                ))}
                <span className="mono dim" style={{ fontSize: 11 }}>mm</span>
              </div>
            ) : <span className="mono dim" style={{ fontSize: 11 }}>L×A×P</span>}
          </div>

          {/* alternador de visão */}
          <div style={{ display: "flex", gap: 4, background: "var(--bg-0)", padding: 3, borderRadius: 7, border: "1px solid var(--border)" }}>
            {[["editor", "Montagem", "edit"], ["tecnico", "Desenho Técnico", "ruler"]].map(([v, lbl, ic]) => (
              <button key={v} onClick={() => { setView(v); setArmed(null); }}
                style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "6px 13px", borderRadius: 5, fontFamily: "var(--ff-mono)", fontSize: 11, border: "none",
                  background: view === v ? "var(--accent-soft)" : "transparent", color: view === v ? "var(--accent)" : "var(--fg-mute)", cursor: "pointer", transition: "all .15s" }}>
                <QmIcon name={ic} size={13} /> {lbl}
              </button>
            ))}
          </div>

          <div style={{ marginLeft: "auto", display: "flex", gap: 8, flexWrap: "wrap" }}>
            {view === "editor" && (
              <button className="btn btn-sm" onClick={() => setSnap50(!snap50)} style={{ color: snap50 ? "var(--accent)" : undefined, borderColor: snap50 ? "var(--accent)" : undefined }}>
                <QmIcon name="grid" size={13} /> Snap {snap50 ? "50mm" : "5mm"}
              </button>
            )}
            <button className="btn btn-sm" onClick={loadExample}>Exemplo</button>
            <button className="btn btn-sm btn-primary" onClick={() => setShowMat(true)}><QmIcon name="list" size={13} /> Lista de Materiais</button>
            <button className="btn btn-sm" onClick={exportBOM} title="Exportar JSON da montagem"><QmIcon name="download" size={13} /> BOM</button>
            <button className="btn btn-sm" onClick={clearAll} style={{ color: "var(--danger)" }}><QmIcon name="trash" size={13} /></button>
          </div>
        </div>
      </div>

      {view === "tecnico" ? (
        <TecnicoView config={config} />
      ) : (
        <div style={{ display: "grid", gridTemplateColumns: "214px 1fr 288px", gap: "var(--gap-grid,20px)", alignItems: "start" }}>

          {/* COLUNA 1 — Biblioteca */}
          <div className="panel" style={{ padding: "14px 11px" }}>
            <div className="panel-eyebrow" style={{ marginBottom: 12, padding: "0 5px" }}>BIBLIOTECA</div>
            {armed && (
              <div className="vl-banner vl-banner-info" style={{ marginBottom: 12, fontSize: 11 }}>
                ✓ <b>{LIB[armed]?.label}</b> — clique na placa
                <button onClick={() => setArmed(null)} style={{ marginLeft: "auto", background: "none", border: "none", cursor: "pointer", color: "var(--accent)", fontSize: 14, lineHeight: 1 }}>✕</button>
              </div>
            )}
            {QM_GROUPS().map((group) => (
              <div key={group} style={{ marginBottom: 13 }}>
                <div style={{ fontFamily: "var(--ff-mono)", fontSize: 9, letterSpacing: ".14em", color: "var(--fg-faint)", textTransform: "uppercase", padding: "0 5px", marginBottom: 5 }}>{group}</div>
                {Object.entries(LIB).filter(([, d]) => d.group === group).map(([type, def]) => (
                  <QmPaletteItem key={type} type={type} def={def} active={armed === type} onClick={() => { setArmed(armed === type ? null : type); setSelId(null); }} />
                ))}
              </div>
            ))}
          </div>

          {/* COLUNA 2 — Placa */}
          <div className="panel">
            <div className="panel-head" style={{ marginBottom: 14 }}>
              <div><div className="panel-eyebrow">PLACA DE MONTAGEM</div><h3>Posição livre — arraste para mover</h3></div>
              <div style={{ fontFamily: "var(--ff-mono)", fontSize: 10, color: "var(--fg-mute)" }}>{dimLabel} mm</div>
            </div>
            <div className="vl-quadros-stats" style={{ gridTemplateColumns: "repeat(4,1fr)", marginBottom: 14 }}>
              {[["COMPONENTES", list.length], ["GABINETE", `${dims.W}×${dims.H}`], ["OCUPAÇÃO", occ + "%"], ["PLACA", `${plate.w}×${plate.h}`]].map(([l, v]) => (
                <div key={l}><span>{l}</span><b className="readout">{v}</b></div>
              ))}
            </div>
            {/* imagem de referência para sobrepor / decalcar */}
            <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginBottom: 12, padding: "9px 12px", background: "var(--bg-0)", border: "1px solid var(--border)", borderRadius: 8 }}>
              <span style={{ fontFamily: "var(--ff-mono)", fontSize: 9, letterSpacing: ".14em", color: "var(--fg-faint)", textTransform: "uppercase" }}>Imagem de referência</span>
              <label className="btn btn-sm" style={{ cursor: "pointer" }}>
                <QmIcon name="image" size={13} /> {ovl ? "Trocar" : "Sobrepor imagem"}
                <input type="file" accept="image/*" onChange={onOvlUpload} style={{ display: "none" }} />
              </label>
              {ovl && (<>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--ff-mono)", fontSize: 10, color: "var(--fg-mute)" }}>OPAC<input type="range" min="0.1" max="1" step="0.05" value={ovl.opacity} onChange={(e) => setOvl((o) => ({ ...o, opacity: +e.target.value }))} style={{ width: 78, accentColor: "var(--accent)" }} /></span>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--ff-mono)", fontSize: 10, color: "var(--fg-mute)" }}>ESC<input type="range" min="0.2" max="2.5" step="0.05" value={ovl.scale} onChange={(e) => setOvl((o) => ({ ...o, scale: +e.target.value }))} style={{ width: 78, accentColor: "var(--accent)" }} /></span>
                <button className="btn btn-sm" onClick={() => setOvl((o) => ({ ...o, locked: !o.locked }))} style={{ color: ovl.locked ? undefined : "var(--accent)", borderColor: ovl.locked ? undefined : "var(--accent)" }}>{ovl.locked ? "🔒 Travada" : "✥ Mover"}</button>
                <button className="btn btn-sm" onClick={() => setOvl((o) => ({ ...o, visible: !o.visible }))}>{ovl.visible ? "Ocultar" : "Mostrar"}</button>
                <button className="btn btn-sm" onClick={() => setOvl(null)} style={{ color: "var(--danger)" }}><QmIcon name="trash" size={13} /></button>
              </>)}
            </div>
            <PlateEditor preset={dims} items={list} selectedId={selId} armedType={armed} snap50={snap50} ovl={ovl} onOvlMove={(x, y) => setOvl((o) => ({ ...o, x, y }))}
              onSelect={setSelId} onMove={moveComp} onPlace={placeComp} />
            <div style={{ marginTop: 12, fontFamily: "var(--ff-mono)", fontSize: 11, color: "var(--fg-mute)", display: "flex", gap: 18, flexWrap: "wrap" }}>
              <span>① Selecione um componente na biblioteca</span><span>② Clique na placa para posicionar</span><span>③ Arraste para ajustar · Delete remove</span>
            </div>
          </div>

          {/* COLUNA 3 — Propriedades / BOM */}
          <div className="panel" style={{ position: "sticky", top: 0 }}>
            {selected ? (
              <QmProps item={selected} def={LIB[selected.type]} onUpdate={updateComp} onRemove={removeComp} onDeselect={() => setSelId(null)} />
            ) : (
              <QmBom bom={bom} total={list.length} occ={occ} mat={window.QM.materials(list)} />
            )}
          </div>
        </div>
      )}

      {/* ── Referência técnica ─────────────────────────── */}
      <div className="panel">
        <div className="panel-head"><div><div className="panel-eyebrow">REFERÊNCIA · NBR 5410 / IEC 60715</div><h3>Módulos DIN e trilho 35 mm</h3></div></div>
        <div className="ref-table">
          <div className="ref-head" style={{ gridTemplateColumns: "1fr 1fr 1.6fr 1fr 1fr" }}><span>MÓDULO</span><span>LARGURA</span><span>EXEMPLO</span><span>TRILHO</span><span>NORMA</span></div>
          {[["1 mód.", "18 mm", "Disjuntor 1P, sinaleiro", "35 mm", "IEC 60715"], ["2 mód.", "36 mm", "Disj. 2P, temporizador", "35 mm", "IEC 60715"], ["3 mód.", "54 mm", "Disj. 3P, relé térmico", "35 mm", "IEC 60715"], ["Bloco", "45–80 mm", "Contatoras P/M/G", "35 mm", "IEC 60947"], ["Moldada", "105 mm", "Disjuntor geral (MCCB)", "fixa", "IEC 60947"]].map((r) => (
            <div key={r[0]} className="ref-row" style={{ gridTemplateColumns: "1fr 1fr 1.6fr 1fr 1fr" }}>
              <span className="mono"><b>{r[0]}</b></span><span className="mono">{r[1]}</span><span style={{ fontSize: 12 }}>{r[2]}</span><span className="mono dim">{r[3]}</span><span><span className="pill pill-ok">{r[4]}</span></span>
            </div>
          ))}
        </div>
      </div>

      {showMat && <QmMaterialModal mat={window.QM.materials(list)} bom={bom} dimLabel={dimLabel} dims={dims}
        presetLabel={presetKey === "custom" ? "Personalizado" : (QM_PRESETS().find((p) => p.key === presetKey)?.label || dimLabel)}
        total={list.length} occ={occ} onClose={() => setShowMat(false)} />}
    </div>
  );
};

/* ===========================================================
   PROPRIEDADES DO COMPONENTE
=========================================================== */
const QmProps = ({ item, def, onUpdate, onRemove, onDeselect }) => {
  if (!def) return null;
  const s = window.QM.itemSize(item);
  return (
    <div>
      <div className="panel-eyebrow" style={{ marginBottom: 10 }}>COMPONENTE</div>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 16, padding: "12px 14px", background: "var(--bg-0)", borderRadius: 8, border: "1px solid var(--border)" }}>
        <span style={{ width: 40, height: 40, borderRadius: 6, background: def.color, flexShrink: 0, border: "1px solid rgba(255,255,255,.12)" }} />
        <div><div style={{ fontFamily: "var(--ff-display)", fontWeight: 600, fontSize: 15 }}>{def.label}</div>
          <div style={{ fontFamily: "var(--ff-mono)", fontSize: 10, color: "var(--fg-mute)", marginTop: 2 }}>{def.group} · {s.w}×{s.h} mm</div></div>
      </div>

      <label style={{ fontFamily: "var(--ff-mono)", fontSize: 10, letterSpacing: ".12em", color: "var(--fg-mute)", textTransform: "uppercase", display: "block", marginBottom: 6 }}>TAG</label>
      <input value={item.tag || ""} onChange={(e) => onUpdate({ tag: e.target.value })}
        style={{ width: "100%", padding: "8px 12px", background: "var(--bg-0)", border: "1px solid var(--border)", borderRadius: 6, color: "var(--fg)", fontFamily: "var(--ff-mono)", fontSize: 14, fontWeight: 600, outline: "none", marginBottom: 14 }} />

      {def.lengthAdjustable && (
        <div style={{ marginBottom: 14 }}>
          <label style={{ fontFamily: "var(--ff-mono)", fontSize: 10, letterSpacing: ".12em", color: "var(--fg-mute)", textTransform: "uppercase", display: "flex", justifyContent: "space-between", marginBottom: 6 }}>
            <span>COMPRIMENTO</span><span style={{ color: "var(--accent)" }}>{item.len || (def.vertical ? def.h : def.w)} mm</span>
          </label>
          <input type="range" min={def.vertical ? 80 : 120} max={def.vertical ? 900 : 680} step="10" value={item.len || (def.vertical ? def.h : def.w)}
            onChange={(e) => onUpdate({ len: +e.target.value })} style={{ width: "100%", accentColor: "var(--accent)" }} />
        </div>
      )}

      <div className="vl-mini-grid" style={{ gridTemplateColumns: "1fr 1fr", marginBottom: 16 }}>
        <div className="vl-metric"><span className="vl-metric-label">Posição X</span><div className="vl-metric-value"><span className="readout">{item.x}</span><em>mm</em></div></div>
        <div className="vl-metric"><span className="vl-metric-label">Posição Y</span><div className="vl-metric-value"><span className="readout">{item.y}</span><em>mm</em></div></div>
      </div>

      <button onClick={onDeselect} className="btn btn-block" style={{ marginBottom: 8 }}>← Voltar à lista</button>
      <button onClick={onRemove} style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 8, width: "100%", padding: "9px 14px", borderRadius: 6, background: "oklch(70% 0.20 25/0.1)", border: "1px solid oklch(70% 0.20 25/0.3)", color: "var(--danger)", fontFamily: "var(--ff-body)", fontSize: 13, cursor: "pointer" }}>🗑 Remover</button>
    </div>
  );
};

/* ===========================================================
   LISTA DE MATERIAIS
=========================================================== */
const QmBom = ({ bom, total, occ, mat }) => (
  <div>
    <div className="panel-eyebrow" style={{ marginBottom: 14 }}>LISTA DE MATERIAIS</div>
    <div className="vl-mini-grid" style={{ gridTemplateColumns: "1fr 1fr", marginBottom: 14 }}>
      <div className="vl-metric"><span className="vl-metric-label">Componentes</span><div className="vl-metric-value"><span className="readout">{total}</span></div></div>
      <div className="vl-metric"><span className="vl-metric-label">Ocupação</span><div className="vl-metric-value"><span className="readout">{occ}</span><em>%</em></div></div>
    </div>
    {mat && (
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontFamily: "var(--ff-mono)", fontSize: 9, letterSpacing: ".14em", color: "var(--fg-faint)", textTransform: "uppercase", marginBottom: 8 }}>RESUMO DE MATERIAIS</div>
        <div className="vl-mini-grid" style={{ gridTemplateColumns: "1fr 1fr", marginBottom: 8 }}>
          <div className="vl-metric"><span className="vl-metric-label">Trilho DIN</span><div className="vl-metric-value"><span className="readout">{mat.rail_m.toFixed(2)}</span><em>m</em></div></div>
          <div className="vl-metric"><span className="vl-metric-label">Canaleta</span><div className="vl-metric-value"><span className="readout">{mat.duct_m.toFixed(2)}</span><em>m</em></div></div>
        </div>
        <div className="vl-metric" style={{ marginBottom: 8 }}><span className="vl-metric-label">Disjuntores</span><div className="vl-metric-value"><span className="readout">{mat.disj.qty}</span><em>un · {mat.disj.mod} mód. DIN</em></div></div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
          {[["Contatoras", mat.cont], ["Relés/Timer", mat.rele], ["DPS", mat.dps], ["MCCB", mat.mccb], ["Bornes (vias)", mat.bornes]].filter(([, v]) => v > 0).map(([l, v]) => (
            <span key={l} className="pill" style={{ fontSize: 10 }}>{l}: {v}</span>
          ))}
        </div>
      </div>
    )}
    {bom.length === 0 ? (
      <div style={{ textAlign: "center", padding: "24px 12px", color: "var(--fg-mute)", fontSize: 12 }}>Adicione componentes à placa para montar a lista de materiais.</div>
    ) : (
      <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 40px 1fr", gap: 8, paddingBottom: 8, borderBottom: "1px solid var(--border)", fontFamily: "var(--ff-mono)", fontSize: 9, letterSpacing: ".1em", color: "var(--fg-mute)", textTransform: "uppercase" }}>
          <span>COMPONENTE</span><span style={{ textAlign: "center" }}>QT</span><span>TAGS</span>
        </div>
        {bom.map((b) => (
          <div key={b.type} style={{ display: "grid", gridTemplateColumns: "1fr 40px 1fr", gap: 8, padding: "7px 0", borderBottom: "1px solid oklch(28% 0.012 240/0.4)", alignItems: "center" }}>
            <div><div style={{ fontSize: 12, color: "var(--fg-dim)" }}>{b.def.label}</div><div style={{ fontSize: 10, fontFamily: "var(--ff-mono)", color: "var(--fg-mute)" }}>{b.def.group}</div></div>
            <span className="readout" style={{ textAlign: "center", fontSize: 13, color: "var(--accent)" }}>{b.tags.length}</span>
            <span style={{ fontFamily: "var(--ff-mono)", fontSize: 10, color: "var(--fg-mute)", wordBreak: "break-word" }}>{b.tags.join(", ")}</span>
          </div>
        ))}
      </div>
    )}
  </div>
);

/* ===========================================================
   MODAL · GERAR LISTA DE MATERIAIS
=========================================================== */
const QmMaterialModal = ({ mat, dimLabel, dims, presetLabel, total, occ, onClose }) => {
  const order = ["Estrutura", "Proteção", "Manobra", "Proteção Motriz", "Controle", "Distribuição"];
  const rows = Object.values(mat.byType).sort((a, b) => {
    const ga = order.indexOf(a.group), gb = order.indexOf(b.group);
    return (ga < 0 ? 99 : ga) - (gb < 0 ? 99 : gb) || a.label.localeCompare(b.label);
  });
  const grouped = order.map((g) => ({ g, items: rows.filter((r) => r.group === g) })).filter((x) => x.items.length);

  const asText = () => {
    const L = [];
    L.push(`LISTA DE MATERIAIS`);
    L.push(`Quadro / Gabinete: ${presetLabel}  (${dims.W} × ${dims.H} × ${dims.D} mm · L×A×P)`);
    L.push(`Trilho DIN: ${mat.rail_qty} un · ${mat.rail_m.toFixed(2)} m`);
    L.push(`Canaleta: ${mat.duct_qty} un · ${mat.duct_m.toFixed(2)} m`);
    L.push(`Disjuntores: ${mat.disj.qty} un · ${mat.disj.mod} módulos DIN`);
    L.push(`Total de componentes: ${total}`);
    L.push("");
    grouped.forEach(({ g, items }) => {
      L.push(`[${g}]`);
      items.forEach((r) => L.push(`  ${String(r.qty).padStart(2)}×  ${r.label}${r.len_mm ? `  (${(r.len_mm / 1000).toFixed(2)} m)` : ""}`));
    });
    return L.join("\n");
  };
  const [copied, setCopied] = useState(false);
  const doCopy = () => { navigator.clipboard?.writeText(asText()).then(() => { setCopied(true); setTimeout(() => setCopied(false), 1600); }); };
  const doCSV = () => {
    const head = "Qtd,Componente,Grupo,Comprimento_m\n";
    const body = rows.map((r) => `${r.qty},"${r.label}","${r.group}",${r.len_mm ? (r.len_mm / 1000).toFixed(2) : ""}`).join("\n");
    const blob = new Blob(["\uFEFF" + head + body], { type: "text/csv;charset=utf-8" });
    const a = document.createElement("a"); a.href = URL.createObjectURL(blob); a.download = "lista-materiais.csv"; a.click();
  };

  const Hi = ({ label, big, sub, accent }) => (
    <div style={{ background: "var(--bg-0)", border: "1px solid var(--border)", borderRadius: 10, padding: "13px 15px" }}>
      <div style={{ fontFamily: "var(--ff-mono)", fontSize: 9, letterSpacing: ".14em", color: "var(--fg-faint)", textTransform: "uppercase", marginBottom: 7 }}>{label}</div>
      <div style={{ fontFamily: "var(--ff-display)", fontWeight: 700, fontSize: 22, color: accent ? "var(--accent)" : "var(--fg)", lineHeight: 1.05 }}>{big}</div>
      {sub && <div style={{ fontFamily: "var(--ff-mono)", fontSize: 11, color: "var(--fg-mute)", marginTop: 4 }}>{sub}</div>}
    </div>
  );

  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 999, background: "rgba(4,6,9,.72)", backdropFilter: "blur(3px)", display: "grid", placeItems: "center", padding: 24 }}>
      <div onClick={(e) => e.stopPropagation()} className="panel" style={{ width: "min(760px, 100%)", maxHeight: "88vh", display: "flex", flexDirection: "column", padding: 0, overflow: "hidden" }}>
        {/* head */}
        <div style={{ display: "flex", alignItems: "flex-start", gap: 12, padding: "20px 22px 16px", borderBottom: "1px solid var(--border)" }}>
          <div style={{ flex: 1 }}>
            <div className="panel-eyebrow">LISTA DE MATERIAIS</div>
            <h3 style={{ margin: "2px 0 0" }}>Quadro {presetLabel}</h3>
            <div style={{ fontFamily: "var(--ff-mono)", fontSize: 11, color: "var(--fg-mute)", marginTop: 3 }}>{dims.W} × {dims.H} × {dims.D} mm · L×A×P · ocupação {occ}%</div>
          </div>
          <button className="btn btn-sm" onClick={onClose} style={{ padding: 8 }}><QmIcon name="close" size={15} /></button>
        </div>

        {/* corpo rolável */}
        <div style={{ overflow: "auto", padding: "18px 22px" }}>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 10, marginBottom: 18 }}>
            <Hi label="Quadro" big={`${dims.W}×${dims.H}`} sub={`Prof. ${dims.D} mm`} />
            <Hi label="Trilho DIN" big={mat.rail_qty} sub={`${mat.rail_m.toFixed(2)} m no total`} accent />
            <Hi label="Canaleta" big={mat.duct_qty} sub={`${mat.duct_m.toFixed(2)} m no total`} accent />
            <Hi label="Disjuntores" big={mat.disj.qty} sub={`${mat.disj.mod} mód. DIN`} accent />
          </div>

          {(mat.cont || mat.rele || mat.dps || mat.mccb || mat.borne_reguas) > 0 && (
            <div style={{ display: "flex", flexWrap: "wrap", gap: 7, marginBottom: 18 }}>
              {[["Disj. Geral (MCCB)", mat.mccb], ["DPS / Surto", mat.dps], ["Contatoras", mat.cont], ["Relés / Timer", mat.rele], ["Réguas de bornes", mat.borne_reguas], ["Vias de borne", mat.bornes]]
                .filter(([, v]) => v > 0).map(([l, v]) => (
                  <span key={l} className="pill" style={{ fontSize: 11, padding: "5px 11px" }}>{l}: <b style={{ color: "var(--accent)", marginLeft: 4 }}>{v}</b></span>
                ))}
            </div>
          )}

          {/* tabela detalhada por grupo */}
          {rows.length === 0 ? (
            <div style={{ textAlign: "center", padding: "32px 12px", color: "var(--fg-mute)", fontSize: 13 }}>Nenhum componente na placa. Adicione itens para gerar a lista.</div>
          ) : grouped.map(({ g, items }) => (
            <div key={g} style={{ marginBottom: 16 }}>
              <div style={{ fontFamily: "var(--ff-mono)", fontSize: 9, letterSpacing: ".14em", color: "var(--fg-faint)", textTransform: "uppercase", marginBottom: 6, paddingBottom: 6, borderBottom: "1px solid var(--border)" }}>{g}</div>
              {items.map((r) => (
                <div key={r.type} style={{ display: "grid", gridTemplateColumns: "44px 1fr auto", gap: 10, padding: "7px 0", borderBottom: "1px solid oklch(28% 0.012 240/0.4)", alignItems: "center" }}>
                  <span className="readout" style={{ fontSize: 15, color: "var(--accent)", textAlign: "center" }}>{r.qty}×</span>
                  <span style={{ fontSize: 13, color: "var(--fg-dim)" }}>{r.label}</span>
                  <span style={{ fontFamily: "var(--ff-mono)", fontSize: 11, color: "var(--fg-mute)" }}>{r.len_mm ? `${(r.len_mm / 1000).toFixed(2)} m` : ""}</span>
                </div>
              ))}
            </div>
          ))}
        </div>

        {/* rodapé */}
        <div style={{ display: "flex", gap: 8, justifyContent: "flex-end", padding: "14px 22px", borderTop: "1px solid var(--border)" }}>
          <button className="btn btn-sm" onClick={doCopy} style={{ color: copied ? "var(--accent)" : undefined, borderColor: copied ? "var(--accent)" : undefined }}>{copied ? "✓ Copiado" : "Copiar texto"}</button>
          <button className="btn btn-sm" onClick={doCSV}><QmIcon name="download" size={13} /> CSV</button>
          <button className="btn btn-sm btn-primary" onClick={onClose}>Fechar</button>
        </div>
      </div>
    </div>
  );
};

window.VL_QuadroMontagem = QuadroMontagem;
