/* Game 1: Robotek — drive robot, press A near zones to pick/drop cubes
   Game 2: Inverse Line — drive robot through 12 zones along path
   UNIFIED CONTROLS: Joystick (drive) + A (primary action) + B (secondary action)
*/

const { useState: useS1, useEffect: useE1, useRef: useR1, useMemo: useM1 } = React;

/* ========================================================
   ROBOTEK — drive robot, A = pick/drop based on context
   ======================================================== */
function GameRobotek({ game, onComplete }) {
  const [phase, setPhase] = useS1('tutorial');
  const [score, setScore] = useS1(0);
  const [breakdown, setBreakdown] = useS1([]);
  const [carry, setCarry] = useS1(null);
  const [cells, setCells] = useS1(null);
  const [step, setStep] = useS1(0);
  const [restarts, setRestarts] = useS1(0);
  const [endStatus, setEndStatus] = useS1(null);
  const finishRef = useR1(false);
  const [, force] = useS1(0);

  const W = 600, H = 400;
  const ZONES = {
    A1: { x: 0.20*W, y: 0.30*H, label: 'A1' },
    A2: { x: 0.20*W, y: 0.65*H, label: 'A2' },
    B1: { x: 0.80*W, y: 0.30*H, label: 'B1' },
    B2: { x: 0.80*W, y: 0.65*H, label: 'B2' },
  };

  const { robotRef, setInput, step: physStep } = useRobot({ x: W/2, y: H*0.85, speed: 2.4 });

  const [time, resetTime] = useTimer(game.duration, phase === 'playing', () => endRound('timeout'));
  const [showToast, toastNode] = useToast();

  // Fixed action sequence locked in at round start. We can't derive it from
  // the live `cells` state because by step 4 the cubes have swapped places —
  // re-deriving redAt/blueAt then would point at the *new* positions and the
  // expected action would no longer match the regulation cycle.
  const seqRef = useR1([]);

  const buildCycle = (initial) => {
    const redAt    = initial.A1 === 'red'  ? 'A1' : 'A2';
    const blueAt   = initial.B1 === 'blue' ? 'B1' : 'B2';
    const redOther = redAt  === 'A1' ? 'A2' : 'A1';
    const blueOther= blueAt === 'B1' ? 'B2' : 'B1';
    return [
      { act: 'pick',  at: redAt,     color: 'red'  },
      { act: 'place', at: blueOther, color: 'red'  },
      { act: 'pick',  at: blueAt,    color: 'blue' },
      { act: 'place', at: redOther,  color: 'blue' },
      { act: 'pick',  at: blueOther, color: 'red'  },
      { act: 'place', at: redAt,     color: 'red'  },
      { act: 'pick',  at: redOther,  color: 'blue' },
      { act: 'place', at: blueAt,    color: 'blue' },
    ];
  };

  const setupRound = (resetScore = true) => {
    const aSlot = Math.random() < 0.5 ? 'A1' : 'A2';
    const bSlot = Math.random() < 0.5 ? 'B1' : 'B2';
    const initial = {
      A1: aSlot === 'A1' ? 'red'  : null,
      A2: aSlot === 'A2' ? 'red'  : null,
      B1: bSlot === 'B1' ? 'blue' : null,
      B2: bSlot === 'B2' ? 'blue' : null,
    };
    setCells(initial);
    seqRef.current = buildCycle(initial);
    setCarry(null);
    setStep(0);
    if (resetScore) { setScore(0); setBreakdown([]); setRestarts(0); }
    robotRef.current.x = W/2; robotRef.current.y = H*0.85;
    finishRef.current = false;
  };

  const start = () => { setupRound(); resetTime(); setPhase('playing'); };

  const seq = seqRef.current;
  const expected = seq.length ? seq[step % seq.length] : null;

  // Find nearest zone
  const nearestZone = () => {
    const r = robotRef.current;
    let best = null, bd = 50;
    for (const k of Object.keys(ZONES)) {
      const z = ZONES[k];
      const d = Math.hypot(z.x - r.x, z.y - r.y);
      if (d < bd) { bd = d; best = k; }
    }
    return best;
  };

  // Physics loop
  useE1(() => {
    if (phase !== 'playing') return;
    let raf;
    const loop = () => {
      physStep({ minX: 20, maxX: W-20, minY: 20, maxY: H-20 });
      force(v => v + 1);
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, [phase]);

  const onA = () => {
    if (phase !== 'playing' || !expected) return;
    const zone = nearestZone();
    if (!zone) { showToast('Drive closer to a zone'); return; }

    if (zone === expected.at) {
      if (expected.act === 'pick') {
        if (cells[zone] === expected.color) {
          setCarry({ color: expected.color });
          setCells(c => ({ ...c, [zone]: null }));
          showToast(t('toast.picked_color_cube', { color: t('color.' + expected.color) }));
          setStep(s => s + 1);
        } else {
          showToast(t('toast.no_cube_here'));
        }
      } else { // place
        if (carry && !cells[zone]) {
          const award = 10;
          setScore(s => s + award);
          setBreakdown(b => [...b, { k: t('breakdown.place', { color: t('color.' + expected.color), zone }), v: award }]);
          setCells(c => ({ ...c, [zone]: expected.color }));
          setCarry(null);
          showToast(`+${award}`);
          setStep(s => s + 1);
        }
      }
    } else if (expected.act === 'place' && carry) {
      setScore(s => s - 10);
      setBreakdown(b => [...b, { k: t('breakdown.wrong_zone'), v: -5 }, { k: t('breakdown.restart'), v: -5 }]);
      setRestarts(r => r + 1);
      setCarry(null);
      setupRound(false);
      showToast(t('toast.wrong_zone_restart'));
    } else {
      showToast(t('toast.go_to', { dest: expected.at }));
    }
  };

  const endRound = (status) => {
    if (finishRef.current) return;
    finishRef.current = true;
    setEndStatus(status);
    setTimeout(() => setPhase('result'), 400);
  };

  const r = robotRef.current;
  const near = phase === 'playing' ? nearestZone() : null;

  return (
    <>
      <div className="field-wrap">
        <svg viewBox={`0 0 ${W} ${H}`} className="field" style={{width: '100%', maxHeight: '100%'}}>
          <defs>
            <pattern id="dotgrid-1" width="14" height="14" patternUnits="userSpaceOnUse">
              <circle cx="1" cy="1" r="0.7" fill="#1a1a1a" opacity="0.08" />
            </pattern>
          </defs>
          <rect width={W} height={H} fill="#fdfcf8" />
          <rect width={W} height={H} fill="url(#dotgrid-1)" />

          <ellipse cx={W/2} cy={H/2} rx={W/2 - 70} ry={H/2 - 60} fill="none" stroke="#1a1a1a" strokeWidth="14" />
          <ellipse cx={W/2} cy={H/2} rx={W/2 - 70} ry={H/2 - 60} fill="none" stroke="#fff" strokeWidth="6" />

          <circle cx={W*0.40} cy={H*0.50} r="22" fill="none" stroke="#1a1a1a" strokeWidth="2.5" />
          <circle cx={W*0.40} cy={H*0.50} r="6" fill="#1a1a1a" />
          <circle cx={W*0.60} cy={H*0.50} r="22" fill="none" stroke="#1a1a1a" strokeWidth="2.5" />
          <circle cx={W*0.60} cy={H*0.50} r="6" fill="#1a1a1a" />

          <line x1={W*0.42} y1={H*0.88} x2={W*0.58} y2={H*0.88} stroke="oklch(0.88 0.17 95)" strokeWidth="6" strokeLinecap="round" />

          {Object.entries(ZONES).map(([k, z]) => {
            const isExpected = expected && expected.at === k;
            const isNear = near === k;
            return (
              <g key={k}>
                <rect x={z.x-28} y={z.y-28} width="56" height="56" rx="2"
                  fill={isExpected ? 'oklch(0.82 0.19 128 / 0.45)' : '#fff'}
                  stroke={isNear ? 'oklch(0.65 0.20 25)' : '#1a1a1a'} strokeWidth={isNear ? 4 : 3} />
                <text x={z.x} y={z.y-36} textAnchor="middle" fontSize="11" fontFamily="Space Mono" fontWeight={700} fill="#444">{k}</text>
                {cells && cells[k] && (
                  <rect x={z.x-13} y={z.y-13} width="26" height="26" rx="2"
                    fill={cells[k] === 'red' ? '#e74c3c' : '#3498db'}
                    stroke="#1a1a1a" strokeWidth="1.5" />
                )}
              </g>
            );
          })}

          <RobotSprite robot={r}
            carrying={carry && (
              <rect x="-9" y="-28" width="18" height="14" rx="2"
                fill={carry.color === 'red' ? '#e74c3c' : '#3498db'}
                stroke="#fff" strokeWidth="1.5" />
            )} />
        </svg>
      </div>

      <HUD time={time} score={Math.max(0, score)} status={t('hud.step')} extra={`${(step%8)+1}/8`} />

      <div className="controls">
        <Joystick onChange={setInput} label={t('btn.steer')} />
        <ActionButtons
          aLabel={expected?.act === 'pick' ? t('btn.pickup') : t('btn.drop')}
          aHint={expected ? t('btn.hint_to_arrow', { dest: expected.at }) : ''}
          onA={onA}
          aActive={near === expected?.at} />
      </div>

      {phase === 'tutorial' && <TutorialOverlay game={game} onStart={start} onSkip={() => onComplete(0, 'skipped', false)} />}
      {phase === 'result' && (
        <ResultOverlay game={game} score={Math.max(0, score)} time={game.duration - time}
          breakdown={breakdown} status={endStatus}
          onRetry={() => setPhase('tutorial')}
          onNext={() => onComplete(Math.max(0, score), endStatus, true)}
          onSkip={() => onComplete(Math.max(0, score), endStatus, true, 'hub')} />
      )}
      {toastNode}
    </>
  );
}

/* ========================================================
   INVERSE LINE — joystick, no buttons (pure driving)
   ======================================================== */
function GameInverse({ game, onComplete }) {
  const [phase, setPhase] = useS1('tutorial');
  const [score, setScore] = useS1(0);
  const [zonesHit, setZonesHit] = useS1(0);
  const [endStatus, setEndStatus] = useS1(null);
  const [, force] = useS1(0);

  const W = 600, H = 400;
  const COLS = 4, ROWS = 3;
  const CW = W / COLS, CH = H / ROWS;

  const cellOrder = useM1(() => {
    const arr = [];
    for (let row = 0; row < ROWS; row++) {
      for (let c = 0; c < COLS; c++) {
        const col = row % 2 === 0 ? c : COLS - 1 - c;
        arr.push({ row, col });
      }
    }
    return arr;
  }, []);

  const pathD = useM1(() => {
    const pts = cellOrder.map(({row, col}) => ({
      x: col * CW + CW/2,
      y: row * CH + CH/2,
    }));
    let d = `M ${pts[0].x} ${pts[0].y}`;
    for (let i = 1; i < pts.length; i++) {
      const p0 = pts[i-1], p1 = pts[i];
      const cx = (p0.x + p1.x)/2, cy = (p0.y + p1.y)/2;
      d += ` Q ${p0.x} ${p1.y}, ${cx} ${cy} T ${p1.x} ${p1.y}`;
    }
    return d;
  }, [cellOrder]);

  const robotRef = useR1({ progress: 0, x: 0, y: 0, angle: 0 });
  const inputRef = useR1({ dx: 0, dy: 0 });
  const pathRef = useR1(null);
  const [zoneStates, setZoneStates] = useS1([]);

  const [time, resetTime] = useTimer(game.duration, phase === 'playing', () => end('timeout'));
  const finishRef = useR1(false);

  useKeyboard((v) => { inputRef.current = v; });

  const start = () => {
    robotRef.current = { progress: 0, x: CW/2, y: CH/2, angle: 0 };
    setZoneStates(cellOrder.map(() => false));
    setScore(0); setZonesHit(0);
    finishRef.current = false;
    resetTime();
    setPhase('playing');
  };

  useE1(() => {
    if (phase !== 'playing') return;
    let raf;
    const loop = () => {
      const r = robotRef.current;
      const i = inputRef.current;
      const inputMag = Math.hypot(i.dx, i.dy);
      const path = pathRef.current;
      if (!path) { raf = requestAnimationFrame(loop); return; }
      const total = path.getTotalLength();

      const dir = i.dy < 0 ? 1 : (i.dy > 0.3 ? -0.4 : 0.6);
      r.progress = Math.max(0, Math.min(total, r.progress + (inputMag * dir * 2.4)));

      const pt = path.getPointAtLength(r.progress);
      const ahead = path.getPointAtLength(Math.min(total, r.progress + 1));
      r.x = pt.x; r.y = pt.y;
      r.angle = Math.atan2(ahead.y - pt.y, ahead.x - pt.x);

      const cellProgress = (r.progress / total) * 12;
      const zoneIdx = Math.floor(cellProgress);
      setZoneStates(zs => {
        if (zoneIdx >= 0 && zoneIdx < 12 && !zs[zoneIdx]) {
          const nz = [...zs];
          nz[zoneIdx] = true;
          setScore(s => s + 10);
          setZonesHit(c => c + 1);
          if (zoneIdx === 11) setTimeout(() => end('finish'), 200);
          return nz;
        }
        return zs;
      });

      force(t => t + 1);
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, [phase]);

  const end = (s) => {
    if (finishRef.current) return;
    finishRef.current = true;
    setEndStatus(s);
    setTimeout(() => setPhase('result'), 500);
  };

  const r = robotRef.current;
  return (
    <>
      <div className="field-wrap">
        <svg viewBox={`0 0 ${W} ${H}`} className="field" style={{width:'100%', maxHeight:'100%'}}>
          {Array.from({length: COLS*ROWS}).map((_, i) => {
            const col = i % COLS, row = Math.floor(i / COLS);
            const dark = (col + row) % 2 === 0;
            return <rect key={i} x={col*CW} y={row*CH} width={CW} height={CH} fill={dark ? '#18171a' : '#fbfaf7'} />;
          })}

          {cellOrder.map(({row, col}, i) => {
            const dark = (col + row) % 2 === 0;
            const lineColor = dark ? '#fbfaf7' : '#18171a';
            const cellId = `c-${row}-${col}`;
            return (
              <g key={i}>
                <clipPath id={cellId}>
                  <rect x={col*CW} y={row*CH} width={CW} height={CH} />
                </clipPath>
                <path d={pathD} stroke={lineColor} strokeWidth="14" fill="none" clipPath={`url(#${cellId})`} strokeLinecap="round" />
              </g>
            );
          })}

          <path ref={pathRef} d={pathD} stroke="none" fill="none" />

          {cellOrder.map(({row, col}, i) => {
            const cx = col*CW + CW/2, cy = row*CH + CH/2;
            const dark = (col + row) % 2 === 0;
            const hit = zoneStates[i];
            return (
              <g key={i} pointerEvents="none">
                <circle cx={cx} cy={cy} r="20"
                  fill={hit ? 'oklch(0.82 0.19 128 / 0.85)' : 'oklch(0.82 0.19 128 / 0.18)'}
                  stroke="oklch(0.82 0.19 128)" strokeWidth="2" />
                <text x={cx} y={cy+4} textAnchor="middle" fontSize="11" fontFamily="Space Mono"
                  fontWeight={700} fill={hit ? '#1a1a1a' : (dark ? '#fff' : '#1a1a1a')}>{i+1}</text>
              </g>
            );
          })}

          {phase === 'playing' && <RobotSprite robot={r} color="oklch(0.65 0.20 25)" accent="#fff" />}
        </svg>
      </div>

      <HUD time={time} score={score} status={t('hud.zones')} extra={`${zonesHit}/12`} />

      <div className="controls">
        <Joystick onChange={(v) => { inputRef.current = v; }} label={t('btn.steer')} />
        <div style={{flex: 1, fontSize:11, color:'var(--ink-3)', textAlign:'right', fontFamily:'var(--font-mono)', lineHeight:1.4}}>
          {tx('inverse.helper')}
        </div>
      </div>

      {phase === 'tutorial' && <TutorialOverlay game={game} onStart={start} onSkip={() => onComplete(0, 'skipped', false)} />}
      {phase === 'result' && (
        <ResultOverlay game={game} score={score} time={game.duration - time}
          breakdown={[{k: `${zonesHit} zones × 10`, v: zonesHit*10}]} status={endStatus}
          onRetry={() => setPhase('tutorial')}
          onNext={() => onComplete(score, endStatus, true)}
          onSkip={() => onComplete(score, endStatus, true, 'hub')} />
      )}
    </>
  );
}

window.GameRobotek = GameRobotek;
window.GameInverse = GameInverse;
