import { useState, useEffect, useCallback, useRef } from 'react';
import { api, S } from '../lib.js';

const GRID     = 20;
const MY_COLOR  = '#4ecdc4';
const OPP_COLOR = '#ff6b9d';
const DIRS8     = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];

// Terrain-Konstanten (müssen mit Backend übereinstimmen)
const T_NORMAL = 0;
const T_GOLD   = 1;
const T_MINE   = 2;
const T_ROCK   = 3;
const T_FOG    = -1; // maskiert vom Server

function getMyId() {
  try { return JSON.parse(atob(localStorage.getItem('sk_token').split('.')[1])).id || null; } catch { return null; }
}
function getMyRole() {
  try { return JSON.parse(atob(localStorage.getItem('sk_token').split('.')[1])).role || null; } catch { return null; }
}

// ── Spielerklärung ────────────────────────────────────────────────────────────
function HelpModal({ onClose }) {
  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.85)', zIndex:1000, display:'flex', flexDirection:'column' }}
      onClick={onClose}>
      <div style={{ ...S.card, maxWidth:460, width:'100%', margin:'16px auto', display:'flex', flexDirection:'column',
        maxHeight:'calc(100dvh - 32px)', overflow:'hidden' }}
        onClick={e => e.stopPropagation()}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center',
          paddingBottom:14, marginBottom:14, borderBottom:'1px solid rgba(255,255,255,0.08)', flexShrink:0 }}>
          <span style={{ color:'#fff', fontFamily:'Space Mono,monospace', fontSize:14, fontWeight:700, letterSpacing:1 }}>⬡ SPIELREGELN</span>
          <button onClick={onClose} style={S.btn('#ff6b9d', true)}>✕ Schließen</button>
        </div>
        <div style={{ overflowY:'auto', paddingBottom:'calc(56px + env(safe-area-inset-bottom, 0px))' }}>
        <div style={{ color:'rgba(255,255,255,0.75)', fontSize:13, lineHeight:1.9, fontFamily:'monospace' }}>
          <p style={{ marginTop:0 }}>
            <strong style={{ color:MY_COLOR }}>Ziel:</strong> Sammle mehr <strong>Punkte</strong> als dein Gegner — durch clevere Expansion und das Meiden von Fallen.
          </p>

          <p><strong style={{ color:'#fff' }}>Ablauf:</strong><br/>
            Beide starten in gegenüberliegenden Ecken. Du hast einen <strong style={{ color:MY_COLOR }}>Kopf</strong> — dein letzter Zug, markiert mit einem leuchtenden Rahmen. Du kannst <strong>nur an den Kopf anbauen</strong> (alle 8 Richtungen). Dein Gebiet bleibt erhalten, aber du kannst nicht mehr von alten Feldern aus expandieren. Tippe ein Feld an, bestätige — fertig.
          </p>

          <div style={{ background:'rgba(255,255,255,0.04)', borderRadius:8, padding:'12px 14px', marginBottom:12, border:'1px solid rgba(255,255,255,0.08)' }}>
            <div style={{ marginBottom:8, color:'#fff', fontSize:12, letterSpacing:1 }}>FELDER & PUNKTE</div>
            <div style={{ display:'grid', gridTemplateColumns:'28px 1fr', gap:'6px 10px', alignItems:'center' }}>
              <span style={{ fontSize:16, textAlign:'center' }}>⬜</span><span><strong style={{ color:'rgba(255,255,255,0.9)' }}>Normales Feld</strong> — +1 Punkt</span>
              <span style={{ fontSize:16, textAlign:'center' }}>⭐</span><span><strong style={{ color:'#ffe66d' }}>Goldfeld</strong> — +3 Punkte, sehr wertvoll!</span>
              <span style={{ fontSize:16, textAlign:'center' }}>💣</span><span><strong style={{ color:'#ff6b9d' }}>Sprengmine</strong> — Betreten zündet eine Explosion: alle 8 umliegenden Felder werden zu Felsen (auch Gold!). Besetzte Felder gehen verloren. Liegt eine weitere Mine im Umkreis, explodiert auch diese (Kettenreaktion!). Du verlierst deinen nächsten Zug.</span>
              <span style={{ fontSize:16, textAlign:'center' }}>🪨</span><span><strong style={{ color:'rgba(255,255,255,0.4)' }}>Felsen</strong> — unbesetzbar, blockiert Wege</span>
            </div>
          </div>

          <p>
            <strong style={{ color:'#fff' }}>🌫️ Nebel:</strong><br/>
            Du siehst nur dein Gebiet und die direkt angrenzenden Felder. Goldfelder und Minen bleiben verborgen bis du nahe genug herankommst — also aufgepasst!
          </p>

          <p>
            <strong style={{ color:'#ffe66d' }}>🔭 Kundschaften:</strong><br/>
            Statt ein Feld zu besetzen kannst du einmal pro Zug <strong>kundschaften</strong>: tippe auf den Button <strong style={{ color:'#ffe66d' }}>🔭 Kundschaften</strong>, dann wähle einen Mittelpunkt auf dem Spielfeld — ein <strong>3×3 Bereich</strong> wird nur für dich aufgedeckt. Dein Gegner sieht nicht was du entdeckt hast. Kostet deinen Zug, gibt dir aber wertvolle Information über Minen und Gold.
          </p>

          <p>
            <strong style={{ color:'#fff' }}>Spielende:</strong><br/>
            Das Spiel endet wenn niemand mehr ziehen kann — oder wenn jemand <strong>doppelt so viele Punkte</strong> hat wie der Gegner (Dominanzsieg 👑). Wer mehr Punkte hat, gewinnt.
          </p>

          <div style={{ background:'rgba(255,255,255,0.04)', borderRadius:8, padding:'10px 14px', border:'1px solid rgba(255,255,255,0.08)' }}>
            📱 <em>Auf dem Handy: Pinch zum Zoomen, Feld antippen und bestätigen.</em>
          </div>
        </div>
        </div>
      </div>
    </div>
  );
}

// ── Neues Spiel Modal ─────────────────────────────────────────────────────────
function NewGameModal({ onClose, onCreated, toast }) {
  const [users,   setUsers]   = useState([]);
  const [oppId,   setOppId]   = useState('');
  const [loading, setLoading] = useState(false);

  useEffect(() => { api('/tools/gebietseroberung/users').then(setUsers).catch(() => {}); }, []);

  const create = async () => {
    if (!oppId) return;
    setLoading(true);
    try {
      const res = await api('/tools/gebietseroberung', { body: { opponent_id: Number(oppId) } });
      toast('Spiel erstellt! Dein Gegner wurde benachrichtigt ⬡');
      onCreated(res.id);
    } catch(e) {
      toast(e.message || 'Fehler beim Erstellen', 'error');
    } finally { setLoading(false); }
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.85)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:1000, padding:20 }}>
      <div style={{ ...S.card, maxWidth:360, width:'100%' }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:18 }}>
          <span style={{ color:'#fff', fontFamily:'Space Mono,monospace', fontSize:13, fontWeight:700, letterSpacing:1 }}>NEUES SPIEL</span>
          <button onClick={onClose} style={S.btn('#666666', true)}>✕</button>
        </div>
        <div style={{ ...S.head, marginBottom:6 }}>GEGNER WÄHLEN</div>
        <select value={oppId} onChange={e => setOppId(e.target.value)} style={{ ...S.inp, marginBottom:18 }}>
          <option value=''>-- Benutzer wählen --</option>
          {users.map(u => <option key={u.id} value={u.id}>{u.username}</option>)}
        </select>
        <div style={{ display:'flex', gap:8 }}>
          <button onClick={onClose} style={{ ...S.btn('#666666'), flex:1 }}>Abbrechen</button>
          <button onClick={create} disabled={!oppId || loading} style={{ ...S.btn('#4ecdc4'), flex:1 }}>
            {loading ? 'Erstelle…' : 'Spiel starten'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Topliste ──────────────────────────────────────────────────────────────────
function Leaderboard({ reloadKey }) {
  const [rows, setRows] = useState(null);
  useEffect(() => { api('/tools/gebietseroberung/leaderboard').then(setRows).catch(() => setRows([])); }, [reloadKey]);
  if (!rows) return null;
  const medals = ['🥇','🥈','🥉'];
  return (
    <div style={{ marginTop:28 }}>
      <div style={{ ...S.head, marginBottom:10 }}>TOPLISTE — SIEGE</div>
      {rows.length === 0
        ? <div style={{ color:'rgba(255,255,255,0.25)', fontFamily:'monospace', fontSize:12, textAlign:'center', padding:'16px 0' }}>Noch keine abgeschlossenen Spiele.</div>
        : rows.map((r,i) => (
          <div key={r.username} style={{ display:'flex', alignItems:'center', gap:12, padding:'10px 14px', marginBottom:6, background:'rgba(255,255,255,0.03)', border:'1px solid rgba(255,255,255,0.07)', borderRadius:8 }}>
            <span style={{ fontSize:16, width:24, textAlign:'center', flexShrink:0 }}>{medals[i] || `${i+1}.`}</span>
            <span style={{ flex:1, color:'#fff', fontFamily:'monospace', fontSize:13 }}>{r.username}</span>
            <span style={{ color:MY_COLOR, fontFamily:'Space Mono,monospace', fontSize:16, fontWeight:700 }}>{r.wins}</span>
            <span style={{ color:'rgba(255,255,255,0.3)', fontFamily:'monospace', fontSize:10 }}>Siege</span>
          </div>
        ))
      }
    </div>
  );
}

// ── Spielfeld ─────────────────────────────────────────────────────────────────
function GameBoard({ game, myId, onMove, onScout, toast }) {
  const [pending,    setPending]    = useState(null);
  const [moving,     setMoving]     = useState(false);
  const [scoutMode,  setScoutMode]  = useState(false); // Scout-Modus aktiv
  const [scoutPend,  setScoutPend]  = useState(null);  // gewählter Scout-Mittelpunkt
  const [mineAlert, setMineAlert] = useState(null); // letztes Mine-Event

  const grid    = JSON.parse(game.grid);
  const terrain = JSON.parse(game.terrain || '[]');
  const hasTerrain = terrain.length > 0;

  const isMyTurn = game.current_turn === myId;
  const opponent = game.owner_id === myId ? game.opponent_id : game.owner_id;
  const myColor  = game.owner_id === myId ? MY_COLOR : OPP_COLOR;
  const oppColor = game.owner_id === myId ? OPP_COLOR : MY_COLOR;
  const oppName  = game.owner_id === myId ? game.opp_name : game.owner_name;

  // Mine-Event anzeigen wenn frisch
  const [blastHighlight, setBlastHighlight] = useState(new Set());
  const [alertShownAt,  setAlertShownAt]  = useState(null); // move_count beim Anzeigen

  useEffect(() => {
    if (!game.last_event) {
      setMineAlert(null); // Event wurde vom Server geclearet (nächster Zug)
      return;
    }
    try {
      const ev = JSON.parse(game.last_event);
      if (ev.type === 'mine') {
        setMineAlert(ev);
        setAlertShownAt(game.move_count);
        if (ev.blastCells?.length) {
          const keys = new Set(ev.blastCells.map(([r,c]) => `${r}-${c}`));
          setBlastHighlight(keys);
          setTimeout(() => setBlastHighlight(new Set()), 2000);
        }
      }
    } catch {}
  }, [game.last_event, game.move_count]);

  // Schlangen-Köpfe aus Server-Response
  const myHeadStr  = game.myHead;
  const myHead     = myHeadStr ? myHeadStr.split(',').map(Number) : null;
  const [myHR, myHC] = myHead ?? [null, null];

  const oppHeadStr = game.oppHead;
  const oppHead    = oppHeadStr ? oppHeadStr.split(',').map(Number) : null;
  const [oppHR, oppHC] = oppHead ?? [null, null];

  const isAdjacentToHead = (r, c) => {
    if (myHR === null) return false;
    return Math.abs(r - myHR) <= 1 && Math.abs(c - myHC) <= 1 && !(r === myHR && c === myHC);
  };

  const canClick = (r, c) => {
    if (scoutMode) return false; // im Scout-Modus kein normaler Zug
    if (!isMyTurn || game.status !== 'active') return false;
    if (grid[r][c] !== 0) return false;
    if (hasTerrain && terrain[r][c] === T_ROCK) return false;
    if (myHead) return isAdjacentToHead(r, c);
    return DIRS8.some(([dr,dc]) => {
      const nr=r+dr, nc=c+dc;
      return nr>=0&&nr<GRID&&nc>=0&&nc<GRID&&grid[nr][nc]===myId;
    });
  };

  const handleCellClick = (r, c) => {
    if (!canClick(r, c) || moving) return;
    if (pending?.row === r && pending?.col === c) { setPending(null); return; }
    setPending({ row:r, col:c });
  };

  const confirmMove = async () => {
    if (!pending || moving) return;
    setMoving(true);
    try {
      await onMove(pending.row, pending.col);
      setPending(null);
    } catch(e) {
      toast?.(e.message || 'Fehler', 'error');
    } finally { setMoving(false); }
  };

  // Scores kommen vom Server (auf ungemasktem Grid berechnet — korrekt für beide Spieler)
  const myScore  = game.myScore  ?? 0;
  const oppScore = game.oppScore ?? 0;
  const myCount  = grid.flat().filter(v => v === myId).length;
  const oppCount = grid.flat().filter(v => v === opponent).length;
  const fogCount = grid.flat().filter(v => v === 0 && hasTerrain).length;

  let banner = null;
  if (game.status === 'finished') {
    const isDominance = myScore >= oppScore * 2 || oppScore >= myScore * 2;
    if (!game.winner_id)               banner = { text:'Unentschieden! 🤝', color:'#ffe66d' };
    else if (game.winner_id === myId)  banner = { text: isDominance ? 'Dominanzsieg! 👑🎉' : 'Du hast gewonnen! 🎉', color:MY_COLOR };
    else                               banner = { text: isDominance ? 'Dominanzniederlage 💀' : 'Du hast verloren.',  color:OPP_COLOR };
  }

  const [cellSize, setCellSize] = useState(14);

  useEffect(() => {
    const calc = () => {
      const vw     = Math.min(window.innerWidth, 600);
      const vh     = window.visualViewport?.height ?? window.innerHeight;
      // Overhead: Header(36) + Scoreboard(50) + Status(30) + Legende(26) + margins(28) = ~170px
      const availH = vh - 170;
      const byW    = Math.floor((vw - 32) / GRID);
      const byH    = Math.floor(availH / GRID);
      setCellSize(Math.max(10, Math.min(byW, byH)));
    };
    calc();
    window.visualViewport?.addEventListener('resize', calc);
    window.addEventListener('resize', calc);
    return () => {
      window.visualViewport?.removeEventListener('resize', calc);
      window.removeEventListener('resize', calc);
    };
  }, []);

  // Zell-Rendering
  const handleScoutClick = (r, c) => {
    if (!scoutPend) return;
    setScoutPend({ row:r, col:c, confirmed: true });
  };

  const confirmScout = async () => {
    if (!scoutPend || moving) return;
    setMoving(true);
    try {
      await onScout(scoutPend.row, scoutPend.col);
      setScoutMode(false);
      setScoutPend(null);
    } catch(e) {
      toast?.(e.message || 'Fehler', 'error');
    } finally { setMoving(false); }
  };

  const renderCell = (r, c) => {
    const cell    = grid[r][c];
    const t       = hasTerrain ? terrain[r][c] : T_NORMAL;
    const clic    = canClick(r, c);
    const isPend  = pending?.row === r && pending?.col === c;
    const isBlast = blastHighlight.has(`${r}-${c}`);
    const isHead    = myHR === r && myHC === c;
    const isOppHead = game.status === 'finished' && oppHR === r && oppHC === c;
    // Scout-Preview: 3x3 um Maus-Position im Scout-Modus
    const isScoutPreview = scoutPend &&
      Math.abs(r - scoutPend.row) <= 1 && Math.abs(c - scoutPend.col) <= 1;
    const isFog   = t === T_FOG;
    const isRock  = t === T_ROCK;
    const isGold  = t === T_GOLD;
    const isMine  = t === T_MINE;

    let bg = 'rgba(255,255,255,0.05)';
    let content = null;
    let border = '1px solid transparent';

    if (isFog || (cell === 0 && !clic && hasTerrain && t === T_FOG)) {
      bg = 'rgba(0,0,0,0.4)'; // dunkler Nebel
    } else if (isRock) {
      bg = 'rgba(255,255,255,0.12)';
      content = cellSize > 16 ? '🪨' : null;
    } else if (cell === myId) {
      bg = isGold ? `#ffe66d88` : isMine ? `#ff6b9d44` : `${myColor}55`;
      if (isGold) content = cellSize > 16 ? '⭐' : null;
      if (isMine) content = cellSize > 16 ? '💣' : null;
    } else if (cell === opponent) {
      bg = isGold ? `#ffe66d55` : isMine ? `#ff6b9d33` : `${oppColor}55`;
    } else {
      // neutral & sichtbar
      if (isGold) { bg = 'rgba(255,230,109,0.18)'; content = cellSize > 16 ? '⭐' : null; }
      else if (isMine) { bg = 'rgba(255,107,157,0.15)'; content = cellSize > 16 ? '💣' : null; }
      else if (clic) bg = `${myColor}22`;
    }

    if (isBlast) { bg = '#ff440066'; border = '2px solid #ff4400'; }
    if (isOppHead) { border = `2px solid ${oppColor}`; }
    if (isScoutPreview && !isHead) { bg = `rgba(255,230,109,0.2)`; border = `1px solid rgba(255,230,109,0.5)`; }
    if (isHead && !isPend) { border = `2px solid ${myColor}`; }
    if (isPend) { bg = myColor; border = `2px solid ${myColor}`; }
    else if (clic && !isPend && !isBlast && !isHead) border = `1px solid ${myColor}44`;

    return (
      <div
        key={`${r}-${c}`}
        onClick={() => scoutMode ? setScoutPend({row:r,col:c}) : handleCellClick(r, c)}
      onMouseEnter={() => scoutMode ? setScoutPend({row:r,col:c}) : setHover(`${r}-${c}`)}
      onMouseLeave={() => { if(!scoutMode) setHover(null); }}
        style={{
          width:cellSize, height:cellSize, background:bg,
          borderRadius:1, cursor:clic?'pointer':'default',
          transition:'background 0.08s', border, boxSizing:'border-box',
          display:'flex', alignItems:'center', justifyContent:'center',
          fontSize: cellSize > 18 ? 10 : 7, lineHeight:1, userSelect:'none',
        }}
      >{content}</div>
    );
  };

  return (
    <div>
      {/* Scoreboard */}
      <div style={{ display:'flex', gap:8, alignItems:'center', marginBottom:6 }}>
        <div style={{ ...S.card, padding:'5px 8px', flex:1 }}>
          <div style={{ color:myColor, fontFamily:'monospace', fontSize:9, letterSpacing:1, marginBottom:2 }}>DU</div>
          <div style={{ color:'#fff', fontFamily:'Space Mono,monospace', fontSize:16, fontWeight:700, lineHeight:1 }}>{myScore} <span style={{ fontSize:9, color:'rgba(255,255,255,0.3)' }}>Pkt</span></div>
        </div>
        <div style={{ textAlign:'center', color:'rgba(255,255,255,0.2)', fontFamily:'monospace', fontSize:9 }}>🌫️{fogCount}</div>
        <div style={{ ...S.card, padding:'5px 8px', flex:1, textAlign:'right' }}>
          <div style={{ color:oppColor, fontFamily:'monospace', fontSize:9, letterSpacing:1, marginBottom:2 }}>{oppName?.toUpperCase()}</div>
          <div style={{ color:'#fff', fontFamily:'Space Mono,monospace', fontSize:16, fontWeight:700, lineHeight:1 }}><span style={{ fontSize:9, color:'rgba(255,255,255,0.3)' }}>Pkt </span>{oppScore}</div>
        </div>
      </div>

      {/* Mine-Alert */}
      {mineAlert && (
        <div style={{
          background:'rgba(255,107,157,0.15)', border:'1px solid rgba(255,107,157,0.4)',
          borderRadius:8, padding:'10px 14px', marginBottom:12,
          display:'flex', alignItems:'center', gap:10,
        }}>
          <span style={{ fontSize:20 }}>💣</span>
          <span style={{ color:'#ff6b9d', fontFamily:'monospace', fontSize:12, flex:1 }}>
            {mineAlert.player === myId
              ? `💥 Mine! ${mineAlert.destroyedOwn ? mineAlert.destroyedOwn + ' deiner Felder zerstört — ' : ''}Zug verloren.`
              : `💥 ${oppName} trat auf eine Mine! ${mineAlert.destroyedOpp ? mineAlert.destroyedOpp + ' deiner Felder zerstört!' : 'Kein Schaden.'} 😈`}
          </span>
          <button onClick={() => setMineAlert(null)} style={{ ...S.btn('#666666', true), padding:'2px 8px' }}>✕</button>
        </div>
      )}

      {/* Gewinner-Banner */}
      {banner && (
        <div style={{
          background:`${banner.color}18`, border:`1px solid ${banner.color}44`,
          borderRadius:10, padding:'12px 16px', marginBottom:14,
          color:banner.color, fontFamily:'Space Mono,monospace', fontSize:15,
          textAlign:'center', fontWeight:700, letterSpacing:1,
        }}>{banner.text}</div>
      )}

      {/* Zug-Status */}
      {game.status === 'active' && (
        <div style={{ marginBottom:6 }}>
          {!isMyTurn && !pending && (
            <div style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:11, textAlign:'center', padding:'4px 0' }}>
              ⏳ {oppName} ist dran…
            </div>
          )}
          {isMyTurn && !pending && !scoutMode && (
            <div style={{ display:'flex', alignItems:'center', gap:6 }}>
              <div style={{ color:myColor, fontFamily:'monospace', fontSize:11, flex:1, textAlign:'center', padding:'4px 0' }}>
                ▶ Baue vom Kopf aus — Vorsicht vor Minen! 💣
              </div>
              <button onClick={() => { setScoutMode(true); setPending(null); }}
                style={{ ...S.btn('#ffe66d', true), fontSize:10, flexShrink:0 }} title="3x3 Bereich aufdecken (kostet Zug)">
                🔭 Kundschaften
              </button>
            </div>
          )}
          {isMyTurn && scoutMode && !scoutPend && (
            <div style={{ display:'flex', alignItems:'center', gap:8, background:'rgba(255,230,109,0.1)', border:'1px solid rgba(255,230,109,0.4)', borderRadius:8, padding:'7px 10px' }}>
              <span style={{ color:'#ffe66d', fontFamily:'monospace', fontSize:11, flex:1 }}>
                🔭 Klicke einen Mittelpunkt zum Aufdecken (3×3)
              </span>
              <button onClick={() => { setScoutMode(false); setScoutPend(null); }} style={S.btn('#666666', true)}>✕ Abbrechen</button>
            </div>
          )}
          {isMyTurn && scoutMode && scoutPend && (
            <div style={{ display:'flex', alignItems:'center', gap:8, background:'rgba(255,230,109,0.1)', border:'1px solid rgba(255,230,109,0.44)', borderRadius:8, padding:'7px 10px' }}>
              <span style={{ color:'#ffe66d', fontFamily:'monospace', fontSize:11, flex:1 }}>
                🔭 R{scoutPend.row+1} S{scoutPend.col+1} aufdecken — kostet einen Zug
              </span>
              <button onClick={() => setScoutPend(null)} style={S.btn('#666666', true)}>✕</button>
              <button onClick={confirmScout} disabled={moving} style={S.btn('#ffe66d', true)}>{moving ? '…' : '✓ Aufdecken'}</button>
            </div>
          )}
          {pending && !scoutMode && (
            <div style={{ display:'flex', alignItems:'center', gap:8, background:`${myColor}12`, border:`1px solid ${myColor}44`, borderRadius:8, padding:'7px 10px' }}>
              <span style={{ color:myColor, fontFamily:'monospace', fontSize:11, flex:1 }}>
                ✦ R{pending.row+1} S{pending.col+1} — bestätigen?
              </span>
              <button onClick={() => setPending(null)} style={S.btn('#666666', true)}>✕</button>
              <button onClick={confirmMove} disabled={moving} style={S.btn(MY_COLOR, true)}>{moving ? '…' : '✓ Ja'}</button>
            </div>
          )}
        </div>
      )}

      {/* Legende */}
      <div style={{ display:'flex', gap:6, marginBottom:4, flexWrap:'wrap' }}>
        {[['⭐','Gold +3','#ffe66d'],['💣','Mine 💥','#ff6b9d'],['🪨','Felsen','rgba(255,255,255,0.35)'],['🌫️','Nebel','rgba(255,255,255,0.25)']].map(([icon,label,color]) => (
          <div key={label} style={{ display:'flex', alignItems:'center', gap:4 }}>
            <span style={{ fontSize:12 }}>{icon}</span>
            <span style={{ color, fontFamily:'monospace', fontSize:10 }}>{label}</span>
          </div>
        ))}
      </div>

      {/* Grid */}
      <div style={{ overflowX:'auto', overflowY:'auto', WebkitOverflowScrolling:'touch', touchAction:'pinch-zoom', borderRadius:8, width:'fit-content' }}>
        <div style={{ display:'grid', gridTemplateColumns:`repeat(${GRID}, ${cellSize}px)`, gridTemplateRows:`repeat(${GRID}, ${cellSize}px)`, gap:1, background:'rgba(255,255,255,0.04)', borderRadius:8, padding:3 }}>
          {grid.map((row, r) => row.map((_, c) => renderCell(r, c)))}
        </div>
      </div>

    </div>
  );
}

// ── Spielzeile ────────────────────────────────────────────────────────────────
function GameRow({ g, myId, isAdmin, onSelect, onDelete }) {
  const isMyTurn = g.status === 'active' && g.current_turn === myId;
  const opp      = g.owner_id === myId ? g.opp_name : g.owner_name;
  const finished = g.status === 'finished' && (g.move_count || 0) >= 2;
  let result = null;
  if (g.status === 'finished') {
    if (!g.winner_id)              result = { label:'Unentschieden', color:'#ffe66d' };
    else if (g.winner_id === myId) result = { label:'Gewonnen 🎉',   color:MY_COLOR  };
    else                           result = { label:'Verloren',       color:OPP_COLOR };
  }
  return (
    <div style={{ ...S.card, marginBottom:8, display:'flex', alignItems:'center', gap:10, border: isMyTurn ? '1px solid rgba(78,205,196,0.35)' : '1px solid rgba(255,255,255,0.07)', padding:'12px 14px' }}>
      <button onClick={() => onSelect(g.id)} style={{ flex:1, background:'none', border:'none', cursor:'pointer', textAlign:'left', padding:0 }}>
        <div style={{ color:'#fff', fontFamily:'monospace', fontSize:13, marginBottom:4 }}>
          {isMyTurn && <span style={{ color:MY_COLOR, marginRight:6 }}>▶</span>}
          vs <strong>{opp}</strong>
        </div>
        <div style={{ color:'rgba(255,255,255,0.35)', fontSize:11, fontFamily:'monospace' }}>
          {g.move_count || 0} Züge gespielt
        </div>
      </button>
      {result
        ? <span style={{ color:result.color, fontSize:11, fontFamily:'monospace', flexShrink:0 }}>{result.label}</span>
        : <span style={{ color: isMyTurn ? MY_COLOR : 'rgba(255,255,255,0.3)', fontSize:11, fontFamily:'monospace', flexShrink:0 }}>
            {isMyTurn ? 'Du bist dran' : 'Gegner dran'}
          </span>
      }
      {isAdmin && finished && (
        <button onClick={e => { e.stopPropagation(); onDelete(g.id); }} style={{ ...S.btn('#ff6b9d', true), flexShrink:0 }} title="Löschen">🗑</button>
      )}
    </div>
  );
}

// ── Spielliste ────────────────────────────────────────────────────────────────
function GameList({ games, myId, isAdmin, onSelect, onNew, onDelete, reloadKey }) {
  const active   = games.filter(g => g.status === 'active');
  const finished = games.filter(g => g.status === 'finished' && (g.move_count || 0) >= 2);
  return (
    <div>
      <button onClick={onNew} style={{ ...S.btn('#4ecdc4'), width:'100%', marginBottom:20, padding:'10px 14px', fontSize:13 }}>
        + Neues Spiel starten
      </button>
      {active.length > 0 && <>
        <div style={{ ...S.head, marginBottom:10 }}>LAUFENDE SPIELE ({active.length})</div>
        {active.map(g => <GameRow key={g.id} g={g} myId={myId} isAdmin={isAdmin} onSelect={onSelect} onDelete={onDelete} />)}
      </>}
      {finished.length > 0 && <>
        <div style={{ ...S.head, marginTop:20, marginBottom:10 }}>BEENDETE SPIELE</div>
        {finished.map(g => <GameRow key={g.id} g={g} myId={myId} isAdmin={isAdmin} onSelect={onSelect} onDelete={onDelete} finished />)}
      </>}
      {games.length === 0 && (
        <div style={{ color:'rgba(255,255,255,0.25)', fontFamily:'monospace', fontSize:13, textAlign:'center', paddingTop:40 }}>
          Noch keine Spiele — starte eines!
        </div>
      )}
      <Leaderboard reloadKey={reloadKey} />
    </div>
  );
}

// ── Hauptkomponente ───────────────────────────────────────────────────────────
export default function HexWars({ toast }) {
  const [games,    setGames]    = useState([]);
  const [activeId, setActiveId] = useState(null);
  const [game,     setGame]     = useState(null);
  const [showNew,  setShowNew]  = useState(false);
  const [showHelp, setShowHelp] = useState(false);
  const [loading,  setLoading]  = useState(true);

  const [reloadKey, setReloadKey] = useState(0);
  const myId    = getMyId();
  const isAdmin = getMyRole() === 'admin';

  const loadGames = useCallback(async () => {
    try { setGames(await api('/tools/gebietseroberung')); }
    catch { toast?.('Fehler beim Laden', 'error'); }
    finally { setLoading(false); }
  }, []);

  useEffect(() => { loadGames(); }, [loadGames]);

  useEffect(() => {
    if (!activeId) { setGame(null); return; }
    api(`/tools/gebietseroberung/${activeId}`).then(g => {
      setGame(g);
      // Beendetes Spiel als gesehen markieren → Badge verschwindet
      if (g.status === 'finished') {
        api(`/tools/gebietseroberung/${activeId}/seen`, { body: {} }).catch(() => {});
      }
    }).catch(() => {});
  }, [activeId]);

  // Polling wenn Gegner dran
  useEffect(() => {
    if (!activeId || !game || !myId) return;
    if (game.status !== 'active' || game.current_turn === myId) return;
    const iv = setInterval(async () => {
      const g = await api(`/tools/gebietseroberung/${activeId}`).catch(() => null);
      if (!g) return;
      setGame(g);
      if (g.current_turn === myId) {
        toast?.('Du bist dran! ⬡');
        // games-Liste sofort aktualisieren
        setGames(prev => prev.map(p => p.id === g.id
          ? { ...p, current_turn: g.current_turn, move_count: g.move_count }
          : p
        ));
      }
    }, 10000);
    return () => clearInterval(iv);
  }, [activeId, game, myId]);

  const handleMove = async (row, col) => {
    const updated = await api(`/tools/gebietseroberung/${activeId}/move`, { body: { row, col } });
    setGame(updated);
    if (updated.status === 'finished') {
      api(`/tools/gebietseroberung/${activeId}/seen`, { body: {} }).catch(() => {});
    }
    // Direkt den games-State patchen damit die Liste sofort stimmt (kein Warten auf loadGames)
    setGames(prev => prev.map(g => g.id === updated.id
      ? { ...g, current_turn: updated.current_turn, move_count: updated.move_count, status: updated.status, winner_id: updated.winner_id }
      : g
    ));
  };

  const handleScout = async (row, col) => {
    const updated = await api(`/tools/gebietseroberung/${activeId}/scout`, { body: { row, col } });
    setGame(updated);
    setGames(prev => prev.map(g => g.id === updated.id
      ? { ...g, current_turn: updated.current_turn, move_count: updated.move_count }
      : g
    ));
  };

  const handleResign = async () => {
    if (!window.confirm('Wirklich aufgeben?')) return;
    await api(`/tools/gebietseroberung/${activeId}/resign`, { body: {} });
    const updated = await api(`/tools/gebietseroberung/${activeId}`);
    setGame(updated);
    setGames(prev => prev.map(g => g.id === updated.id ? { ...g, ...updated } : g));
    toast('Du hast aufgegeben.');
  };

  const handleDelete = async (id) => {
    if (!window.confirm('Spiel wirklich löschen?')) return;
    try {
      await api(`/tools/gebietseroberung/${id}`, { method: 'DELETE' });
      setGames(prev => prev.filter(g => g.id !== id));
      setReloadKey(k => k + 1);
      toast('Spiel gelöscht.');
    } catch(e) { toast?.(e.message || 'Fehler', 'error'); }
  };

  if (loading) return <div style={{ color:'rgba(255,255,255,0.4)', fontFamily:'monospace', padding:40, textAlign:'center' }}>Lade…</div>;

  return (
    <div style={{ maxWidth:600, margin:'0 auto' }}>
      <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
        {activeId && (
          <button onClick={() => { setActiveId(null); setGame(null); loadGames(); }} style={S.btn('#666666', true)}>← Zurück</button>
        )}
        <h2 style={{ margin:0, fontSize:13, fontFamily:'monospace', color:'rgba(255,255,255,0.55)', letterSpacing:2, fontWeight:400, flexShrink:0 }}>
          ⬡ HEX WARS
        </h2>
        <div style={{ flex:1 }} />
        <button onClick={() => setShowHelp(true)} style={S.btn('#ffe66d', true)}>? Regeln</button>
        {activeId && game?.status === 'active' && (
          <button onClick={handleResign} style={S.btn('#ff6b9d', true)}>⚑</button>
        )}
      </div>

      {!activeId
        ? <GameList games={games} myId={myId} isAdmin={isAdmin} onSelect={setActiveId} onNew={() => setShowNew(true)} onDelete={handleDelete} reloadKey={reloadKey} />
        : game && myId
          ? <GameBoard game={game} myId={myId} onMove={handleMove} onScout={handleScout} toast={toast} />
          : <div style={{ color:'rgba(255,255,255,0.3)', fontFamily:'monospace', textAlign:'center', paddingTop:40 }}>Lade Spiel…</div>
      }

      {showNew  && <NewGameModal onClose={() => setShowNew(false)} toast={toast} onCreated={id => { setShowNew(false); setActiveId(id); loadGames(); }} />}
      {showHelp && <HelpModal onClose={() => setShowHelp(false)} />}
    </div>
  );
}
