// Invaders — mini game inside the Zuno Works site
// Vanilla canvas 2D with a "ZUNO WORKS" destructible barrier.

function Invaders() {
  const canvasRef = React.useRef(null);
  const [score, setScore] = React.useState(0);
  const [best, setBest] = React.useState(() => {
    try { return parseInt(localStorage.getItem('zw_invaders_best') || '0', 10); } catch { return 0; }
  });
  const [state, setState] = React.useState('ready'); // ready | playing | gameover | clear

  React.useEffect(() => {
    if (state !== 'playing') return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const W = canvas.width, H = canvas.height;

    // --- player ---
    const player = { x: W/2 - 14, y: H - 36, w: 28, h: 12, cool: 0 };
    const bullets = [];
    const enemyBullets = [];
    const enemies = [];
    for (let r = 0; r < 4; r++) {
      for (let c = 0; c < 9; c++) {
        enemies.push({ x: 60 + c*44, y: 40 + r*30, w: 22, h: 14, alive: true, row: r });
      }
    }
    let enemyDir = 1;
    let tickSpeed = 36;
    let lastTick = 0;
    let t = 0;
    const keys = {};
    let localScore = 0;

    // --- "ZUNO WORKS" barrier (pixel-destructible) ---
    const pixelSize = 3;
    const barrierW = 420;
    const barrierH = 36;
    const cols = Math.floor(barrierW / pixelSize);
    const rows = Math.floor(barrierH / pixelSize);
    const off = document.createElement('canvas');
    off.width = barrierW; off.height = barrierH;
    const octx = off.getContext('2d');
    octx.fillStyle = '#F5F5F2';
    octx.textAlign = 'center';
    octx.textBaseline = 'middle';
    octx.font = 'bold 30px "JetBrains Mono", ui-monospace, monospace';
    octx.fillText('ZUNO WORKS', barrierW/2, barrierH/2 + 2);
    const imgData = octx.getImageData(0, 0, barrierW, barrierH).data;
    const barrier = new Uint8Array(cols * rows);
    for (let by = 0; by < rows; by++) {
      for (let bx = 0; bx < cols; bx++) {
        const px = bx * pixelSize + Math.floor(pixelSize/2);
        const py = by * pixelSize + Math.floor(pixelSize/2);
        const idx = (py * barrierW + px) * 4 + 3;
        barrier[by * cols + bx] = imgData[idx] > 128 ? 1 : 0;
      }
    }
    const barrierOX = Math.floor((W - cols * pixelSize) / 2);
    const barrierOY = H - 120;

    const damageBarrier = (b, fromAbove) => {
      if (b.x + b.w < barrierOX) return false;
      if (b.x > barrierOX + cols * pixelSize) return false;
      if (b.y + b.h < barrierOY) return false;
      if (b.y > barrierOY + rows * pixelSize) return false;
      const lx = b.x + b.w / 2 - barrierOX;
      const ly = (fromAbove ? (b.y + b.h) : b.y) - barrierOY;
      const bx0 = Math.floor(lx / pixelSize);
      const by0 = Math.floor(ly / pixelSize);
      const radius = 2;
      let hit = false;
      for (let dy = -radius; dy <= radius; dy++) {
        for (let dx = -radius; dx <= radius; dx++) {
          const nx = bx0 + dx, ny = by0 + dy;
          if (nx < 0 || nx >= cols || ny < 0 || ny >= rows) continue;
          if (dx*dx + dy*dy > radius*radius + 1) continue;
          if (barrier[ny * cols + nx] === 1) {
            barrier[ny * cols + nx] = 0;
            hit = true;
          }
        }
      }
      return hit;
    };

    const onKeyDown = (e) => {
      keys[e.code] = true;
      if (e.code === 'Space' || e.code === 'ArrowLeft' || e.code === 'ArrowRight') e.preventDefault();
    };
    const onKeyUp = (e) => { keys[e.code] = false; };
    window.addEventListener('keydown', onKeyDown);
    window.addEventListener('keyup', onKeyUp);

    let animId = 0;
    let running = true;

    const drawInvader = (e) => {
      const pal = ['#F5F5F2', '#FFE600', '#E8261C', '#1B4DFF'];
      ctx.fillStyle = pal[e.row % pal.length];
      ctx.fillRect(e.x+4, e.y+4, e.w-8, e.h-6);
      const wig = Math.floor(t/8) % 2 === 0;
      ctx.fillRect(e.x+2, e.y+e.h-4, 4, 4);
      ctx.fillRect(e.x+e.w-6, e.y+e.h-4, 4, 4);
      if (wig) {
        ctx.fillRect(e.x+8, e.y+e.h-2, 3, 2);
        ctx.fillRect(e.x+e.w-11, e.y+e.h-2, 3, 2);
      }
      ctx.fillStyle = '#0B0B0C';
      ctx.fillRect(e.x+7, e.y+7, 3, 3);
      ctx.fillRect(e.x+e.w-10, e.y+7, 3, 3);
    };

    const drawPlayer = () => {
      ctx.fillStyle = '#FFE600';
      ctx.fillRect(player.x, player.y, player.w, player.h);
      ctx.fillRect(player.x + player.w/2 - 2, player.y - 6, 4, 6);
      ctx.fillStyle = '#E8261C';
      ctx.fillRect(player.x + player.w/2 - 4, player.y + player.h - 2, 8, 2);
    };

    const drawBarrier = () => {
      ctx.fillStyle = '#FFE600';
      for (let by = 0; by < rows; by++) {
        for (let bx = 0; bx < cols; bx++) {
          if (barrier[by * cols + bx] === 1) {
            ctx.fillRect(barrierOX + bx * pixelSize, barrierOY + by * pixelSize, pixelSize, pixelSize);
          }
        }
      }
      ctx.fillStyle = '#E8261C';
      ctx.fillRect(barrierOX, barrierOY + rows * pixelSize + 2, cols * pixelSize, 1);
    };

    const finish = (newState) => {
      running = false;
      setScore(localScore);
      try {
        if (localScore > best) {
          localStorage.setItem('zw_invaders_best', String(localScore));
          setBest(localScore);
        }
      } catch {}
      setState(newState);
    };

    const loop = () => {
      if (!running) return;
      t += 1;

      if (keys['ArrowLeft'])  player.x = Math.max(0, player.x - 4);
      if (keys['ArrowRight']) player.x = Math.min(W - player.w, player.x + 4);
      player.cool = Math.max(0, player.cool - 1);
      if (keys['Space'] && player.cool === 0) {
        bullets.push({ x: player.x + player.w/2 - 2, y: player.y - 8, w: 4, h: 10, vy: -7 });
        player.cool = 14;
      }

      for (const b of bullets) b.y += b.vy;
      for (let i = bullets.length - 1; i >= 0; i--) {
        const b = bullets[i];
        if (b.y < -12) { bullets.splice(i, 1); continue; }
        if (damageBarrier(b, false)) { bullets.splice(i, 1); continue; }
      }
      for (const b of enemyBullets) b.y += b.vy;
      for (let i = enemyBullets.length - 1; i >= 0; i--) {
        const b = enemyBullets[i];
        if (b.y > H + 12) { enemyBullets.splice(i, 1); continue; }
        if (damageBarrier(b, true)) { enemyBullets.splice(i, 1); continue; }
      }

      if (t - lastTick >= tickSpeed) {
        lastTick = t;
        const alive = enemies.filter(e => e.alive);
        if (alive.length === 0) {
          finish('clear');
          return;
        }
        const minX = Math.min(...alive.map(e => e.x));
        const maxX = Math.max(...alive.map(e => e.x + e.w));
        const wantDx = enemyDir * 12;
        if (maxX + wantDx > W - 4 || minX + wantDx < 4) {
          enemyDir *= -1;
          alive.forEach(e => e.y += 16);
        } else {
          alive.forEach(e => e.x += wantDx);
        }
        if (alive.length > 0 && Math.random() < 0.45) {
          const shooter = alive[Math.floor(Math.random() * alive.length)];
          enemyBullets.push({ x: shooter.x + shooter.w/2 - 1.5, y: shooter.y + shooter.h, w: 3, h: 9, vy: 4 });
        }
        tickSpeed = Math.max(10, 36 - Math.floor((enemies.length - alive.length) * 0.8));
      }

      for (const b of bullets) {
        for (const e of enemies) {
          if (!e.alive) continue;
          if (b.x < e.x + e.w && b.x + b.w > e.x && b.y < e.y + e.h && b.y + b.h > e.y) {
            e.alive = false;
            b.y = -999;
            localScore += 10 + (3 - e.row) * 5;
            setScore(localScore);
          }
        }
      }

      for (const b of enemyBullets) {
        if (b.x < player.x + player.w && b.x + b.w > player.x && b.y < player.y + player.h && b.y + b.h > player.y) {
          finish('gameover');
          return;
        }
      }

      for (const e of enemies) {
        if (e.alive && e.y + e.h >= player.y) {
          finish('gameover');
          return;
        }
      }

      ctx.fillStyle = '#0B0B0C';
      ctx.fillRect(0, 0, W, H);
      ctx.strokeStyle = '#1A1A1D';
      ctx.lineWidth = 1;
      for (let x = 0; x <= W; x += 24) { ctx.beginPath(); ctx.moveTo(x+0.5, 0); ctx.lineTo(x+0.5, H); ctx.stroke(); }
      for (let y = 0; y <= H; y += 24) { ctx.beginPath(); ctx.moveTo(0, y+0.5); ctx.lineTo(W, y+0.5); ctx.stroke(); }

      ctx.strokeStyle = '#1B4DFF';
      ctx.beginPath(); ctx.moveTo(0, player.y + player.h + 8); ctx.lineTo(W, player.y + player.h + 8); ctx.stroke();

      for (const e of enemies) if (e.alive) drawInvader(e);

      drawBarrier();

      ctx.fillStyle = '#E8261C';
      for (const b of bullets) ctx.fillRect(b.x, b.y, b.w, b.h);
      ctx.fillStyle = '#F5F5F2';
      for (const b of enemyBullets) ctx.fillRect(b.x, b.y, b.w, b.h);

      drawPlayer();

      ctx.fillStyle = '#F5F5F2';
      ctx.font = '11px ui-monospace, "JetBrains Mono", monospace';
      ctx.fillText('SCORE ' + String(localScore).padStart(5, '0'), 12, 18);
      ctx.fillText('BEST ' + String(best).padStart(5, '0'), W - 110, 18);

      animId = requestAnimationFrame(loop);
    };
    animId = requestAnimationFrame(loop);

    return () => {
      running = false;
      cancelAnimationFrame(animId);
      window.removeEventListener('keydown', onKeyDown);
      window.removeEventListener('keyup', onKeyUp);
    };
  }, [state]);

  const start = () => { setScore(0); setState('playing'); };

  const btnStyle = {
    fontFamily: 'var(--font-mono)',
    fontSize: 12,
    letterSpacing: '.25em',
    textTransform: 'uppercase',
    padding: '12px 24px',
    background: '#FFE600',
    color: '#0B0B0C',
    border: '1px solid #FFE600',
    cursor: 'pointer',
  };

  const contactBtnStyle = {
    fontFamily: 'var(--font-mono)',
    fontSize: 12,
    letterSpacing: '.25em',
    textTransform: 'uppercase',
    padding: '12px 24px',
    background: '#E8261C',
    color: '#F5F5F2',
    border: '1px solid #E8261C',
    textDecoration: 'none',
    cursor: 'pointer',
    display: 'inline-block',
  };

  return (
    <section id="arcade" className="section">
      <div className="container">
        <div className="section-head">
          <div className="section-label">S07 / Arcade</div>
          <h2 className="section-title"><span className="en">Take a break</span>ZW インベーダー</h2>
          <span style={{fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'.2em', textTransform:'uppercase', color:'var(--fg-3)'}}>BEST · {String(best).padStart(5,'0')}</span>
        </div>

        <div style={{display:'flex', flexDirection:'column', alignItems:'center', gap:16}}>
          <div style={{position:'relative', border:'1px solid var(--ink)', background:'#0B0B0C'}}>
            <canvas ref={canvasRef} width={600} height={400} style={{display:'block', maxWidth:'100%', height:'auto'}} />
            {state !== 'playing' && (
              <div style={{position:'absolute', inset:0, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', color:'#F5F5F2', fontFamily:'var(--font-mono)', background:'rgba(11,11,12,0.86)', textAlign:'center', padding:24}}>
                {state === 'ready' && (
                  <>
                    <div style={{fontSize:28, letterSpacing:'.25em', marginBottom:8}}>ZW INVADERS</div>
                    <div style={{fontSize:12, letterSpacing:'.2em', color:'#8A8A8E', marginBottom:20}}>← → MOVE · SPACE FIRE · PROTECT "ZUNO WORKS"</div>
                    <button onClick={start} style={btnStyle}>START ▶</button>
                  </>
                )}
                {state === 'gameover' && (
                  <>
                    <div style={{fontSize:28, letterSpacing:'.25em', color:'#E8261C', marginBottom:8}}>GAME OVER</div>
                    <div style={{fontSize:12, letterSpacing:'.2em', color:'#8A8A8E', marginBottom:20}}>SCORE · {String(score).padStart(5,'0')} · BEST · {String(best).padStart(5,'0')}</div>
                    <button onClick={start} style={btnStyle}>RETRY ▶</button>
                  </>
                )}
                {state === 'clear' && (
                  <>
                    <div style={{fontSize:34, letterSpacing:'.12em', color:'#FFE600', marginBottom:12, fontWeight:700}}>🎉 Congratulations!</div>
                    <div style={{fontSize:16, color:'#F5F5F2', marginBottom:24, letterSpacing:'.05em', lineHeight:1.5}}>Was Zuno Works helpful?</div>
                    <div style={{fontSize:12, letterSpacing:'.2em', color:'#8A8A8E', marginBottom:20}}>SCORE · {String(score).padStart(5,'0')} · BEST · {String(best).padStart(5,'0')}</div>
                    <div style={{display:'flex', gap:12, flexWrap:'wrap', justifyContent:'center'}}>
                      <a href="#contact" style={contactBtnStyle}>お問い合わせ ▶</a>
                      <button onClick={start} style={btnStyle}>AGAIN ▶</button>
                    </div>
                  </>
                )}
              </div>
            )}
          </div>
          <div style={{fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'.2em', textTransform:'uppercase', color:'var(--fg-3)'}}>
            ← → MOVE &nbsp;·&nbsp; SPACE FIRE &nbsp;·&nbsp; PROTECT "ZUNO WORKS"
          </div>
        </div>
      </div>
    </section>
  );
}

window.Invaders = Invaders;
