/* ============================================================
   CIRCUIT LOCK — the second gate type.
   A clockwork ring of 4 concentric rotatable conductors. Power enters
   Ring 0 at the top and must chain inward, ring by ring, to the core.
   • CircuitMainView    — the authoritative shared screen (live glow)
   • CircuitRingPreview — a small single-ring orientation preview (reused)
   • CircuitPlayerOverlay — a player's rotate controls for their ring(s)
   The Moderator panel (CircuitHostPanel) lives in host.jsx beside GatePanel.
   ============================================================ */
const { useState: useStateCl, useEffect: useEffectCl, useRef: useRefCl } = React;

/* ---------- geometry on a 400×400 board, centred at (200,200) ---------- */
const CL_CENTER = 200;
const CL_POWER_R = 192;     // radius the gold power node sits at (above Ring 0)
const CL_CORE_R = 30;       // core receptacle radius
function clMod8(n){ return ((n % 8) + 8) % 8; }
function clPolar(r, slot, cx, cy){
  const a = (-90 + slot*45) * Math.PI/180;
  return [ (cx==null?CL_CENTER:cx) + r*Math.cos(a), (cy==null?CL_CENTER:cy) + r*Math.sin(a) ];
}
// arc that traces a conductor from entry slot → exit slot, sweeping clockwise
function clArc(r, entrySlot, exitSlot, cx, cy){
  const delta = clMod8(exitSlot - entrySlot);
  const [x1,y1] = clPolar(r, entrySlot, cx, cy);
  const [x2,y2] = clPolar(r, exitSlot, cx, cy);
  const large = delta*45 > 180 ? 1 : 0;
  if(delta===0) return `M ${x1.toFixed(2)} ${y1.toFixed(2)}`;
  return `M ${x1.toFixed(2)} ${y1.toFixed(2)} A ${r} ${r} 0 ${large} 1 ${x2.toFixed(2)} ${y2.toFixed(2)}`;
}
function clStub(r1, r2, slot, cx, cy){
  const [a1,b1] = clPolar(r1, slot, cx, cy);
  const [a2,b2] = clPolar(r2, slot, cx, cy);
  return `M ${a1.toFixed(2)} ${b1.toFixed(2)} L ${a2.toFixed(2)} ${b2.toFixed(2)}`;
}
// neighbour radii — what a ring's entry receives from, and its exit feeds into
function upstreamR(i){ return i===0 ? CL_POWER_R : CIRCUIT_META[i-1].radius; }
function downstreamR(i){ return i===CIRCUIT_META.length-1 ? CL_CORE_R : CIRCUIT_META[i+1].radius; }
const midR = (a,b)=> (a+b)/2;

window.clArc = clArc; window.clStub = clStub; window.clPolar = clPolar;

/* ============================================================
   MAIN SCREEN — the whole lock, the source of truth for the glow
   ============================================================ */
function CircuitMainView({ circuit }){
  const game = useGame();
  const live = circuitLiveness(circuit);
  const rings = circuit.rings || [];
  const complete = circuit.complete;
  const [flareN, setFlareN] = useStateCl(0);
  const [surgeN, setSurgeN] = useStateCl(0);
  const [surgeLeft, setSurgeLeft] = useStateCl(0);

  useGameEvents((ev)=>{
    if(ev.type==='circuit-surge'){ setSurgeN(k=>k+1); }
    else if(ev.type==='circuit-open'){ audio.play('circuitComplete'); setFlareN(k=>k+1); }
  });
  // Turn sound follows the rings actually moving on screen (state-driven) so the
  // click lands with the visual rotation — not ahead of it via the event channel.
  const ringSig = rings.map(r=>r.rotation).join(',');
  const prevRingSig = useRefCl(ringSig);
  const lastClick = useRefCl(0);
  useEffectCl(()=>{
    if(prevRingSig.current === ringSig) return;
    prevRingSig.current = ringSig;
    const now = Date.now();
    if(now - lastClick.current > 70){ lastClick.current = now; try{ audio.play('gearClick'); }catch(_){} }
  }, [ringSig]);

  // the Main screen is the authority that drives the surge cadence
  useEffectCl(()=>{
    if(!circuit.open || complete || !circuit.surge || !circuit.surgeAt){ setSurgeLeft(0); return; }
    const tick = ()=>{
      const left = store.getState().circuit.surgeAt - Date.now();
      setSurgeLeft(Math.max(0, left));
      if(left <= 0){ Game.triggerSurge(); }
    };
    tick();
    const id = setInterval(tick, 160);
    return ()=> clearInterval(id);
  }, [circuit.open, complete, circuit.surge, circuit.surgeAt]);

  const surgePct = circuit.surge && circuit.surgeInterval ? Math.max(0, Math.min(100, (surgeLeft/circuit.surgeInterval)*100)) : 0;
  const [px,py] = clPolar(CL_POWER_R, circuit.powerSlot);
  const gap = (!complete && live.firstGap) ? live.firstGap : null;
  let gapRadius = 0;
  if(gap){
    if(gap.kind==='power') gapRadius = midR(CL_POWER_R, CIRCUIT_META[0].radius);
    else if(gap.kind==='core') gapRadius = midR(CIRCUIT_META[CIRCUIT_META.length-1].radius, CL_CORE_R);
    else gapRadius = midR(CIRCUIT_META[gap.ring].radius, CIRCUIT_META[gap.ring+1].radius);
  }
  const [gx,gy] = gap ? clPolar(gapRadius, gap.slot) : [0,0];
  const gapColor = gap ? CIRCUIT_META[gap.ring].color : '#d9534f';

  return (
    <div className={`circuit-stage ${complete?'is-complete':''}`}>
      <Embers count={26}/>
      {surgeN>0 && <div key={'sg'+surgeN} className="circuit-surge-flash"></div>}
      {flareN>0 && <div key={'fl'+flareN} className="circuit-open-flare"></div>}

      <div className="circuit-titlebar">
        <div className="circuit-title display">The Circuit Lock</div>
        <div className="circuit-sub">
          {complete ? 'The current runs true — the seal breaks'
            : 'Turn the rings until the current chains from the source to the core'}
        </div>
      </div>

      <div className="circuit-board">
        <svg className={`circuit-lock ${complete?'complete':''}`} viewBox="0 0 400 400" aria-hidden="true">
          <defs>
            <radialGradient id="cl-core-grad" cx="50%" cy="42%" r="60%">
              <stop offset="0%" stopColor="#fff3d6"/>
              <stop offset="45%" stopColor="#f0a836"/>
              <stop offset="100%" stopColor="#7a4a12"/>
            </radialGradient>
          </defs>

          {/* brass backplate rings */}
          {CIRCUIT_META.map((m,i)=>(
            <circle key={'plate'+i} cx="200" cy="200" r={m.radius} className="cl-plate"/>
          ))}

          {/* rotatable ring groups */}
          {rings.map((r,i)=>{
            const m = CIRCUIT_META[i];
            const rad = m.radius;
            const ringLive = live.liveRing[i];
            const exitLive = i < rings.length-1 ? live.liveJunction[i] : live.coreLive;
            const entryMid = midR(rad, upstreamR(i));
            const exitMid = midR(rad, downstreamR(i));
            return (
              <g key={'ring'+i} className={`ring-group ${ringLive?'lit':'dim'}`}
                 style={{ transform:`rotate(${r.rotation*45}deg)`, color:m.color }}>
                <circle cx="200" cy="200" r={rad} className="cl-track"/>
                {/* entry port — receives from upstream (outward stub) */}
                <path className={`cl-port ${ringLive?'live':'dim'}`} d={clStub(rad, entryMid, r.entrySlot)}/>
                {/* the conductor arc */}
                <path className={`conductor ${ringLive?'live':'dim'}`} d={clArc(rad, r.entrySlot, r.exitSlot)}/>
                {/* exit port — feeds downstream (inward stub) */}
                <path className={`cl-port ${exitLive?'live':'dim'}`} d={clStub(rad, exitMid, r.exitSlot)}/>
                {/* port nodes */}
                <circle className={`cl-node ${ringLive?'live':''}`} cx={clPolar(rad, r.entrySlot)[0]} cy={clPolar(rad, r.entrySlot)[1]} r="5"/>
                <circle className={`cl-node ${exitLive?'live':''}`} cx={clPolar(rad, r.exitSlot)[0]} cy={clPolar(rad, r.exitSlot)[1]} r="5"/>
              </g>
            );
          })}

          {/* hint ghost — flashes a ring's solved position */}
          {circuit.hint>=0 && circuit.solution && circuit.solution[circuit.hint]!=null && (
            <g key={'hint'+circuit.hintId} className="cl-hint-ghost"
               style={{ transform:`rotate(${circuit.solution[circuit.hint]*45}deg)` }}>
              <path className="cl-hint-arc" d={clArc(CIRCUIT_META[circuit.hint].radius, rings[circuit.hint].entrySlot, rings[circuit.hint].exitSlot)}/>
            </g>
          )}

          {/* power source node (fixed, always lit) */}
          <g className="cl-power">
            <circle cx={px} cy={py} r="15" className="cl-power-halo"/>
            <circle cx={px} cy={py} r="9" className="cl-power-core"/>
            <path className="cl-power-feed" d={clStub(CL_POWER_R, CIRCUIT_META[0].radius, circuit.powerSlot)}/>
          </g>

          {/* core receptacle */}
          <g className={`cl-core ${live.coreLive?'lit':''}`}>
            <path className="cl-core-intake" d={clStub(CL_CORE_R+12, CL_CORE_R-2, circuit.coreSlot)}/>
            <circle cx="200" cy="200" r={CL_CORE_R} className="cl-core-ring"/>
            <circle cx="200" cy="200" r={CL_CORE_R-6} className="cl-core-fill"/>
          </g>

          {/* the first broken junction — a red gap marker */}
          {gap && (
            <g className="cl-gap" style={{ '--gc':gapColor }}>
              <circle cx={gx} cy={gy} r="13" className="cl-gap-ring"/>
              <path d={`M ${gx-5} ${gy-5} L ${gx+5} ${gy+5} M ${gx+5} ${gy-5} L ${gx-5} ${gy+5}`} className="cl-gap-x"/>
            </g>
          )}
        </svg>
      </div>

      {/* HUD — ring legend + status */}
      <div className="circuit-hud">
        {!complete ? (
          <>
            <div className="cl-legend">
              {rings.map((r,i)=>{
                const m = CIRCUIT_META[i];
                const owner = game.players.find(p=>p.id===r.owner);
                const lit = live.liveRing[i];
                return (
                  <div key={i} className={`cl-leg ${lit?'lit':''}`} style={{ '--rc':m.color }}>
                    <span className="cl-leg-dot"></span>
                    <span className="cl-leg-name">{m.label}</span>
                    <span className="cl-leg-owner">{owner ? owner.name.split(' ')[0] : '—'}</span>
                    <span className="cl-leg-state">{lit ? '⚡ live' : 'dark'}</span>
                  </div>
                );
              })}
            </div>
            {gap && (
              <div className="cl-stuck">
                <span className="cl-stuck-dot" style={{ background:gapColor }}></span>
                {gap.kind==='power'   ? 'No power reaches the rings — align the Outer ring to the source above.'
                 : gap.kind==='core'  ? 'The current stalls at the core — turn the Inner ring to seat the bolt.'
                 : `The current breaks at the ${CIRCUIT_META[gap.ring].label} ring — line up the next ring's intake.`}
              </div>
            )}
            {circuit.surge && (
              <div className="cl-surge">
                <span className="cl-surge-lbl">⚡ Power surge</span>
                <div className="cl-surge-bar"><div className={`cl-surge-fill ${surgePct<30?'low':''}`} style={{ width:surgePct+'%' }}></div></div>
              </div>
            )}
          </>
        ) : (
          <div className="cl-open-text display">THE GATE OPENS</div>
        )}
      </div>
    </div>
  );
}
window.CircuitMainView = CircuitMainView;

/* ============================================================
   RING PREVIEW — a small single-ring orientation read-out (reused on
   the player handset and the moderator panel). 120×120 board.
   ============================================================ */
function CircuitRingPreview({ ringIndex, circuit, live, size=120 }){
  const r = circuit.rings[ringIndex];
  if(!r) return null;
  const m = CIRCUIT_META[ringIndex];
  const C = 60, R = 42;
  const ringLive = live ? live.liveRing[ringIndex] : false;
  return (
    <svg className="cl-preview" viewBox="0 0 120 120" width={size} height={size}>
      {/* source reference tick at the top */}
      <circle cx="60" cy="10" r="3.4" className="cl-pv-source"/>
      <circle cx="60" cy="60" r="7" className="cl-pv-core"/>
      <circle cx="60" cy="60" r={R} className="cl-pv-track" style={{ color:m.color }}/>
      <g className={`cl-pv-ring ${ringLive?'lit':''}`} style={{ transform:`rotate(${r.rotation*45}deg)`, transformOrigin:'60px 60px', color:m.color }}>
        <path className="cl-pv-cond" d={clArc(R, r.entrySlot, r.exitSlot, C, C)}/>
        <path className="cl-pv-stub" d={clStub(R, R+10, r.entrySlot, C, C)}/>
        <path className="cl-pv-stub" d={clStub(R, R-10, r.exitSlot, C, C)}/>
        <circle cx={clPolar(R, r.entrySlot, C, C)[0]} cy={clPolar(R, r.entrySlot, C, C)[1]} r="4.5" className="cl-pv-node"/>
        <circle cx={clPolar(R, r.exitSlot, C, C)[0]} cy={clPolar(R, r.exitSlot, C, C)[1]} r="4.5" className="cl-pv-node"/>
      </g>
    </svg>
  );
}
window.CircuitRingPreview = CircuitRingPreview;

/* ============================================================
   PLAYER SCREEN — rotate controls for the ring(s) this hero holds
   ============================================================ */
function CircuitRingControl({ ringIndex, circuit, live, player, secondary }){
  const m = CIRCUIT_META[ringIndex];
  const ringLive = live.liveRing[ringIndex];
  const complete = circuit.complete;
  const rotate = (dir)=>{
    if(complete || player.dead) return;
    Game.rotateRing(ringIndex, dir);
    haptic(HAPTIC.card);
    try{ audio.play('gearClick'); }catch(_){}
  };
  return (
    <div className={`cl-ctrl ${secondary?'secondary':''} ${ringLive?'live':''}`} style={{ '--rc':m.color }}>
      <div className="cl-ctrl-head">
        <span className="cl-ctrl-eyebrow">{secondary ? 'Also controlling' : 'Your ring'}</span>
        <span className="cl-ctrl-name">{m.label}{ringLive && <span className="cl-ctrl-live">⚡ live</span>}</span>
      </div>
      <div className="cl-ctrl-body">
        <button className={`rotate-btn liquid-glass glass-btn`} onClick={()=>rotate(-1)} disabled={complete} aria-label="Rotate left">↺</button>
        <CircuitRingPreview ringIndex={ringIndex} circuit={circuit} live={live} size={132}/>
        <button className={`rotate-btn liquid-glass glass-btn`} onClick={()=>rotate(1)} disabled={complete} aria-label="Rotate right">↻</button>
      </div>
    </div>
  );
}

function CircuitPlayerOverlay({ player }){
  const game = useGame();
  const c = game.circuit;
  const [bump, setBump] = useStateCl(0);
  useGameEvents((ev)=>{
    if(ev.type==='circuit-surge'){ haptic(HAPTIC.damage); setBump(k=>k+1); }
    else if(ev.type==='circuit-open'){ haptic(HAPTIC.premium); }
  });
  if(!c.open) return null;
  const live = circuitLiveness(c);
  const mine = c.rings.map((r,i)=>({ r, i })).filter(x=> x.r.owner===player.id);
  const complete = c.complete;

  return (
    <div className={`circuit-overlay ${complete?'is-open':''}`}>
      <Embers count={14}/>
      <div className="circuit-ov-inner animate-fade-rise">
        {complete ? (
          <>
            <div className="cl-ov-spark"></div>
            <h2 className="display gold">The circuit completes</h2>
            <p className="muted" style={{ textTransform:'none' }}>Your current broke the seal. Move through the gate.</p>
          </>
        ) : mine.length===0 ? (
          <>
            <div className="cl-ov-eyebrow">A clockwork lock bars the way</div>
            <h2 className="display">No ring is yours</h2>
            <p className="muted gn-hint" style={{ textTransform:'none' }}>
              The Keeper has not handed you a ring. Watch the main screen and help call the order aloud.
            </p>
          </>
        ) : (
          <>
            <div className="cl-ov-eyebrow">A clockwork lock bars the way</div>
            <h2 className="display">{mine.length>1 ? 'Turn your two rings' : 'Turn your ring'}</h2>
            <p className="muted gn-hint" style={{ textTransform:'none' }}>
              Rotate to carry the current inward. You only see your own ring here —
              <strong className="gold"> watch the main screen</strong> and coordinate out loud.
            </p>
            <div className={`cl-ctrl-stack n${mine.length}`}>
              {mine.map((x,k)=>(
                <CircuitRingControl key={x.i} ringIndex={x.i} circuit={c} live={live} player={player} secondary={k>0}/>
              ))}
            </div>
            <div className="cl-watch">⛬ The whole solution is on the main screen — look up.</div>
          </>
        )}
      </div>
    </div>
  );
}
window.CircuitPlayerOverlay = CircuitPlayerOverlay;
