/* SkyOps — RGB ‖ Thermal comparator.
   Split / Swipe / Overlay / Blink with synced cursor + zoom, thermal palette & range,
   registration quality, stream correlation, paired detection evidence. */

const { useState: uSRT, useMemo: uMRT, useRef: uRRT, useEffect: uERT } = React;

const RT_FULL = [0, 0, 1000, 560];

function RtScene({ kind, panels: allPanels, pal, range, vb = RT_FULL, cursor, focus, onMove, onLeave, svgRef, mini }) {
  const panels = allPanels.filter(p => p.x + p.w >= vb[0] && p.x <= vb[0] + vb[2] && p.y + p.h >= vb[1] && p.y <= vb[1] + vb[3]);
  const col = (t) => window.psRamp(window.PS_RAMPS[pal], (t - range[0]) / (range[1] - range[0]));
  const SEV = window.PS_SEV;
  return (
    <svg ref={svgRef} viewBox={vb.join(" ")} preserveAspectRatio="xMidYMid meet" className="rt-svg"
         onMouseMove={onMove} onMouseLeave={onLeave}>
      <defs><filter id={`rt-b-${kind}${mini ? "m" : ""}`}><feGaussianBlur stdDeviation="2.5"/></filter></defs>
      {kind === "rgb" ? <>
        <rect width="1000" height="560" fill="#2a2e22"/>
        <path d="M0 40 H1000 M0 520 H1000 M528 0 V560" stroke="#4a4638" strokeWidth="14"/>
        <ellipse cx="300" cy="300" rx="40" ry="18" fill="#3f5a2a" opacity=".8"/>
        {panels.map(p => <g key={p.id}>
          <rect x={p.x} y={p.y} width={p.w} height={p.h} fill="#1c2f48" stroke="#0b1220" strokeWidth=".8"/>
          <path d={`M${p.x+p.w/3} ${p.y}V${p.y+p.h}M${p.x+2*p.w/3} ${p.y}V${p.y+p.h}M${p.x} ${p.y+p.h/2}H${p.x+p.w}`} stroke="#2c4566" strokeWidth=".5"/>
          {p.soil && <rect x={p.x+3} y={p.y+p.h-9} width={p.w-6} height="7" fill="#8a7a55" opacity=".75"/>}
          {p.def?.k === "Module crack" && <path d={`M${p.x+4} ${p.y+3} L${p.x+14} ${p.y+12} L${p.x+24} ${p.y+19}`} stroke="#e2e8f0" strokeWidth=".9"/>}
          {p.def?.k === "Bird dropping" && <circle cx={p.x+18} cy={p.y+8} r="2.3" fill="#f8fafc"/>}
          {p.def?.k === "Hot cell" && p.def.rgb && <rect x={p.x+15} y={p.y+5} width="6" height="6" fill="#4b3b2a"/>}
        </g>)}
      </> : <>
        <rect width="1000" height="560" fill={col(35)}/>
        {panels.map(p => {
          const k = p.def?.k;
          return <g key={p.id}>
            <rect x={p.x} y={p.y} width={p.w} height={p.h} fill={col(k === "Bypass diode" || k === "Hot cell" ? 43 : p.temp)}/>
            {k === "Bypass diode" && <rect x={p.x} y={p.y} width={p.w/3} height={p.h} fill={col(p.temp)}/>}
            {k === "PID" && <rect x={p.x} y={p.y} width={p.w} height="6" fill={col(p.temp + 3)}/>}
          </g>;
        })}
        {panels.filter(p => p.def?.k === "Hot cell").map(p => <circle key={p.id} cx={p.x+18} cy={p.y+8} r="5" fill={col(p.temp + 6)} filter={`url(#rt-b-${kind}${mini ? "m" : ""})`}/>)}
      </>}
      {!mini && panels.filter(p => p.def).map(p => (
        <circle key={p.id} cx={p.x+p.w/2} cy={p.y+p.h/2} r={focus === p.id ? 20 : 13} fill="none"
                stroke={SEV[p.def.sev]} strokeWidth={focus === p.id ? 2.4 : 1.4}
                strokeDasharray={kind === "rgb" && !p.def.rgb ? "3 3" : undefined} opacity={kind === "rgb" && !p.def.rgb ? 0.6 : 1}/>
      ))}
      {!mini && cursor && <g pointerEvents="none">
        <line x1={cursor[0]} x2={cursor[0]} y1={vb[1]} y2={vb[1]+vb[3]} stroke="#60a5fa" strokeWidth={vb[2] / 900} opacity=".8"/>
        <line y1={cursor[1]} y2={cursor[1]} x1={vb[0]} x2={vb[0]+vb[2]} stroke="#60a5fa" strokeWidth={vb[2] / 900} opacity=".8"/>
        <circle cx={cursor[0]} cy={cursor[1]} r={vb[2] / 160} fill="none" stroke="#60a5fa" strokeWidth={vb[2] / 700}/>
      </g>}
    </svg>
  );
}

function ViewCompare({ selJob }) {
  const panels = uMRT(() => window.psField(7), []);
  const dets = panels.filter(p => p.def);
  const [mode, setMode] = uSRT("split");
  const [pal, setPal] = uSRT("ironbow");
  const [range, setRange] = uSRT([38, 72]);
  const [syncCur, setSyncCur] = uSRT(true);
  const [cur, setCur] = uSRT(null);
  const [curSide, setCurSide] = uSRT(null);
  const [vb, setVb] = uSRT(RT_FULL);
  const [focus, setFocus] = uSRT(null);
  const [pos, setPos] = uSRT(50);
  const [blend, setBlend] = uSRT(55);
  const [blinkOn, setBlinkOn] = uSRT(false);
  const [dragging, setDragging] = uSRT(false);
  const [detFilter, setDetFilter] = uSRT("all");
  const refs = { rgb: uRRT(null), thermal: uRRT(null) };
  const wrapRef = uRRT(null);

  uERT(() => {
    if (mode !== "blink") return;
    const id = setInterval(() => setBlinkOn(v => !v), 800);
    return () => clearInterval(id);
  }, [mode]);

  const toSvg = (e, side) => {
    const s = refs[side].current; if (!s) return null;
    const p = s.createSVGPoint(); p.x = e.clientX; p.y = e.clientY;
    const r = p.matrixTransform(s.getScreenCTM().inverse());
    return [r.x, r.y];
  };
  const move = (side) => (e) => { setCur(toSvg(e, side)); setCurSide(side); };
  const leave = () => { setCur(null); setCurSide(null); };
  const showCur = (side) => cur && (syncCur || curSide === side) ? cur : null;
  const curPanel = cur ? panels.find(p => cur[0] >= p.x && cur[0] <= p.x + p.w && cur[1] >= p.y && cur[1] <= p.y + p.h) : null;
  const median = 42.9;

  const focusOn = (p) => { setFocus(p.id); setVb([p.x - 150, p.y - 82, 330, 185]); };
  const reset = () => { setFocus(null); setVb(RT_FULL); };

  const onDrag = (e) => {
    if (!dragging || !wrapRef.current) return;
    const r = wrapRef.current.getBoundingClientRect();
    setPos(Math.max(2, Math.min(98, ((e.clientX - r.left) / r.width) * 100)));
  };

  const dual = dets.filter(p => p.def.rgb).length;
  const thOnly = dets.filter(p => !p.def.rgb).length;
  const rgbOnly = panels.filter(p => p.soil && !p.def).length;
  const fDets = dets.filter(p => detFilter === "all" || (detFilter === "dual" ? p.def.rgb : !p.def.rgb));
  const fp = focus ? panels.find(p => p.id === focus) : null;

  const Readout = ({ side }) => {
    if (!curPanel || (!syncCur && curSide !== side)) return null;
    return <div className="rt-read mono">{curPanel.id} · {side === "thermal"
      ? <>{curPanel.temp}°C <span className={curPanel.temp - median > 10 ? "hot" : ""}>Δ{(curPanel.temp - median >= 0 ? "+" : "")}{(curPanel.temp - median).toFixed(1)}</span></>
      : <>{curPanel.soil ? "soiling visible" : curPanel.def?.rgb ? curPanel.def.k.toLowerCase() : "no visible defect"}</>}</div>;
  };
  const sceneProps = (side) => ({ kind: side, panels, pal, range, vb, focus, svgRef: refs[side], onMove: move(side), onLeave: leave, cursor: showCur(side) });

  return (
    <div className="rt">
      <div className="rt-tb">
        <div className="ps-seg">
          {[["split","Split"],["swipe","Swipe"],["overlay","Overlay"],["blink","Blink"]].map(([k,l]) => <button key={k} className={mode === k ? "on" : ""} onClick={() => setMode(k)}>{l}</button>)}
        </div>
        {mode === "overlay" && <div className="rt-ctl"><span>Thermal</span><input type="range" min="0" max="100" value={blend} onChange={e => setBlend(+e.target.value)}/><b className="mono">{blend}%</b></div>}
        {mode === "swipe" && <span className="rt-hint">Drag the divider</span>}
        <span className="grow"/>
        <label className={`rt-sync ${syncCur ? "on" : ""}`}><input type="checkbox" checked={syncCur} onChange={e => setSyncCur(e.target.checked)}/><Icon name="link" size={11}/>Sync cursor</label>
        <span className="rt-sync on"><Icon name="link" size={11}/>Sync zoom</span>
        {vb !== RT_FULL && <button className="btn btn-secondary btn-xs" onClick={reset}><Icon name="maximize" size={11}/>Reset view</button>}
      </div>

      <div className="rt-main">
        <div className="rt-view" ref={wrapRef} onMouseMove={onDrag} onMouseUp={() => setDragging(false)} onMouseLeave={() => setDragging(false)}>
          {mode === "split" && <div className="rt-split">
            {["rgb","thermal"].map(side => (
              <div key={side} className="rt-pane">
                <div className={`rt-lbl rt-lbl-${side}`}>{side === "rgb" ? "RGB · Zenmuse H30T wide" : "LWIR · 640×512 · radiometric"}</div>
                <RtScene {...sceneProps(side)}/>
                <Readout side={side}/>
              </div>
            ))}
          </div>}
          {mode !== "split" && <div className="rt-pane rt-stack">
            <div className="rt-layer"><RtScene {...sceneProps("rgb")}/></div>
            <div className="rt-layer" style={
              mode === "swipe" ? { clipPath: `inset(0 0 0 ${pos}%)` } :
              mode === "overlay" ? { opacity: blend / 100 } :
              { opacity: blinkOn ? 1 : 0 }}>
              <RtScene {...sceneProps("thermal")}/>
            </div>
            {mode === "swipe" && <div className="rt-div" style={{ left: `${pos}%` }} onMouseDown={(e) => { e.preventDefault(); setDragging(true); }}><span><Icon name="split" size={12}/></span></div>}
            <div className="rt-lbl rt-lbl-rgb">{mode === "blink" ? (blinkOn ? "LWIR" : "RGB") : "RGB"}</div>
            {mode !== "blink" && <div className="rt-lbl rt-lbl-thermal rt-lbl-r">LWIR</div>}
            <Readout side={mode === "blink" && !blinkOn ? "rgb" : "thermal"}/>
          </div>}
          <div className="rt-legend">
            <div className="rt-legend-bar" style={{ background: window.PS_RAMP_CSS(pal) }}/>
            <div className="mono rt-legend-l"><span>{range[0]}°C</span><span>{range[1]}°C</span></div>
          </div>
        </div>

        <aside className="rt-side">
          <div className="rt-sec">
            <div className="rt-sec-h">Thermal display</div>
            <div className="rt-pals">
              {["ironbow","rainbow","gray"].map(k => (
                <button key={k} className={pal === k ? "on" : ""} onClick={() => setPal(k)}>
                  <span style={{ background: window.PS_RAMP_CSS(k) }}/>{k}
                </button>
              ))}
            </div>
            <div className="rt-ctl"><span>Min</span><input type="range" min="30" max="50" value={range[0]} onChange={e => setRange([+e.target.value, range[1]])}/><b className="mono">{range[0]}°C</b></div>
            <div className="rt-ctl"><span>Max</span><input type="range" min="52" max="90" value={range[1]} onChange={e => setRange([range[0], +e.target.value])}/><b className="mono">{range[1]}°C</b></div>
          </div>
          <div className="rt-sec">
            <div className="rt-sec-h">Registration<span className="rt-pass"><Icon name="check" size={10}/>pass</span></div>
            <div className="ps-kv"><span>RMSE</span><b className="mono">0.94 px</b></div>
            <div className="ps-kv"><span>Matched keypoints</span><b className="mono">18,402</b></div>
            <div className="ps-kv"><span>Max drift</span><b className="mono">2.1 px · sortie 11</b></div>
            <div className="ps-kv"><span>Method</span><b className="mono">ORB + affine</b></div>
          </div>
          <div className="rt-sec">
            <div className="rt-sec-h">Stream correlation</div>
            <div className="rt-corr">
              <div><b className="mono">{dual}</b><span>dual-confirmed</span></div>
              <div><b className="mono" style={{ color: "#f97316" }}>{thOnly}</b><span>thermal only</span></div>
              <div><b className="mono" style={{ color: "#a8a29e" }}>{rgbOnly}</b><span>RGB only</span></div>
            </div>
            <p className="rt-note">Thermal-only anomalies are usually electrical (bypass diode, string, PID). RGB-visible ones are physical — soiling, cracks, droppings — and go to cleaning or module replacement.</p>
          </div>
          {fp && <div className="rt-sec rt-focus">
            <div className="rt-sec-h">Selected · <span className="mono">{fp.id}</span></div>
            <div className="ps-kv"><span>Class</span><b>{fp.def.k}</b></div>
            <div className="ps-kv"><span>Temperature</span><b className="mono">{fp.temp}°C · Δ+{(fp.temp - median).toFixed(1)}</b></div>
            <div className="ps-kv"><span>RGB evidence</span><b>{fp.def.rgb ? "visible" : "none"}</b></div>
            <button className="btn btn-primary btn-xs ps-full" onClick={() => window.dispatchEvent(new CustomEvent("skyops:stage",{detail:"review"}))}><Icon name="eye" size={11}/>Open in Review</button>
          </div>}
        </aside>
      </div>

      <div className="rt-dets">
        <div className="rt-dets-hd">
          <span className="rt-sec-h" style={{ margin: 0 }}>Paired evidence · {fDets.length} detections</span>
          <div className="ps-seg">
            {[["all","All"],["dual","Dual-confirmed"],["th","Thermal only"]].map(([k,l]) => <button key={k} className={detFilter === k ? "on" : ""} onClick={() => setDetFilter(k)}>{l}</button>)}
          </div>
          <span className="grow"/>
          <span className="rt-hint">Click a card to zoom both streams</span>
        </div>
        <div className="rt-cards">
          {fDets.map(p => {
            const mvb = [p.x - 20, p.y - 11, 68, 44];
            return (
              <button key={p.id} className={`rt-card ${focus === p.id ? "is-on" : ""}`} onClick={() => focusOn(p)}>
                <div className="rt-card-imgs">
                  <RtScene kind="rgb" panels={panels} pal={pal} range={range} vb={mvb} mini/>
                  <RtScene kind="thermal" panels={panels} pal={pal} range={range} vb={mvb} mini/>
                </div>
                <div className="rt-card-b">
                  <div className="rt-card-t"><span className="rt-dot" style={{ background: window.PS_SEV[p.def.sev] }}/>{p.def.k}</div>
                  <div className="mono rt-card-m">{p.id} · +{p.def.dT}°C</div>
                  <span className={`rt-tag ${p.def.rgb ? "dual" : "th"}`}>{p.def.rgb ? "Thermal + RGB" : "Thermal only"}</span>
                </div>
              </button>
            );
          })}
        </div>
      </div>
    </div>
  );
}

window.ViewCompare = ViewCompare;
