/* ===================================================================
   GAME 04 — DUNGEON CRAWLER WORLD: FLOOR 1  (engine view)
   Walks the window.DCC_FLOOR1 node graph: scenes, forks, the canon
   combat set-piece, bespoke endings, a live HUD, and localStorage
   tracking of which endings you've discovered. window.Floor1Page
   =================================================================== */
const { useState: useStateF1, useEffect: useEffectF1, useRef: useRefF1 } = React;
const FLR = window.DCC_FLOOR1;
const F1_ACCENT = 'var(--amber)';            // Floor 1 reads as the "warning broadcast"
const F1_KEY = 'dcc-floor1-endings';

function f1LoadFound(){
  try { const v = JSON.parse(localStorage.getItem(F1_KEY) || '[]'); return new Set(v); }
  catch (e) { return new Set(); }
}
function f1SaveFound(set){
  try { localStorage.setItem(F1_KEY, JSON.stringify(Array.from(set))); } catch (e) {}
}

/* small labelled icon for a choice's flavour (attack / dodge / environment / Donut) */
const F1_KIND = {
  attack: '⚔ Attack', dodge: '↯ Dodge', env: '◇ Use the room',
  donut: '🐾 Let Donut', go: '▸ Press on', stray: '↪ Stray',
};

function Floor1Panel({ id }){
  const svg = FLR.PANELS[id];
  if (!svg) return null;
  return <div className="f1-panel" dangerouslySetInnerHTML={{ __html: svg }} />;
}

function Floor1HUD({ hp, level, followers, found }){
  const pct = Math.max(0, Math.min(100, hp));
  const hpcol = pct > 55 ? 'var(--rar-uncommon)' : (pct > 25 ? 'var(--amber)' : 'var(--warn)');
  return (
    <div className="f1-hud">
      <div className="f1-hp">
        <div className="f1-hp-top"><span>HP</span><b>{Math.round(pct)}</b></div>
        <div className="f1-hp-track"><div className="f1-hp-fill" style={{ width: pct + '%', background: hpcol }} /></div>
      </div>
      <div className="f1-stat"><span>LVL</span><b>{level}</b></div>
      <div className="f1-stat"><span>Followers</span><b>{followers.toLocaleString()}</b></div>
      <div className="f1-stat"><span>Endings</span><b>{found.size}/{FLR.ENDINGS_TOTAL}</b></div>
    </div>
  );
}

function Floor1Scorecard({ hp, level, followers, accuracy, found }){
  return (
    <div className="f1-score">
      <div className="f1-score-h">Run scorecard</div>
      <div className="f1-score-grid">
        <div className="f1-cell"><span>HP left</span><b>{Math.max(0, Math.round(hp))}</b></div>
        <div className="f1-cell"><span>Level</span><b>{level}</b></div>
        <div className="f1-cell"><span>Followers</span><b>{followers.toLocaleString()}</b></div>
        <div className="f1-cell"><span>Canon accuracy</span><b>{accuracy}</b></div>
        <div className="f1-cell wide"><span>Endings discovered</span><b>{found.size} / {FLR.ENDINGS_TOTAL}</b></div>
      </div>
    </div>
  );
}

function Floor1Page({ go }){
  const toHub = () => go({ view: 'games', game: null });

  const [nodeId, setNodeId] = useStateF1(FLR.START);
  const [hp, setHp] = useStateF1(100);
  const [level, setLevel] = useStateF1(1);
  const [followers, setFollowers] = useStateF1(0);
  const [canonPicks, setCanonPicks] = useStateF1(0);
  const [forks, setForks] = useStateF1(0);
  const [found, setFound] = useStateF1(f1LoadFound);
  const [toast, setToast] = useStateF1(null);
  const toastRef = useRefF1(null);

  useEffectF1(() => () => clearTimeout(toastRef.current), []);

  const node = FLR.NODES[nodeId];
  const accuracy = forks > 0 ? Math.round((canonPicks / forks) * 100) + '%' : '—';

  function popToast(txt){
    setToast(txt);
    clearTimeout(toastRef.current);
    toastRef.current = setTimeout(() => setToast(null), 2600);
  }

  function restart(){
    setNodeId(FLR.START); setHp(100); setLevel(1); setFollowers(0);
    setCanonPicks(0); setForks(0); setToast(null);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }

  function enter(id){
    const n = FLR.NODES[id];
    if (n && n.type === 'ending' && n.endingId){
      setFound(prev => { const s = new Set(prev); s.add(n.endingId); f1SaveFound(s); return s; });
    }
    setNodeId(id);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }

  function choose(c){
    const nextHp = Math.max(0, Math.min(100, hp + (c.hp || 0)));
    setHp(nextHp);
    if (c.followers) setFollowers(f => f + c.followers);
    if (c.level) setLevel(l => l + c.level);
    setForks(f => f + 1);
    if (c.outcome === 'canon') setCanonPicks(p => p + 1);
    if (c.achievement) popToast(c.achievement);
    const dest = (nextHp <= 0 && node.on_death) ? node.on_death : c.next;
    enter(dest);
  }

  /* ---------------- render body ---------------- */
  let body;

  if (node.type === 'ending' || node.type === 'continue'){
    const isWin = node.type === 'continue';
    body = (
      <div className="gstep f1-end" key={nodeId}>
        <Floor1Panel id={node.panel} />
        <div className={'f1-end-kicker' + (isWin ? ' win' : '')}>{node.kicker}{node.tone ? ' · ' + node.tone : ''}</div>
        <div className="f1-end-title">{node.title}</div>
        <div className="f1-end-body">
          {node.system.map((p, i) => <p key={i}>{p}</p>)}
        </div>
        <div className="f1-signoff"><span className="dot" /> System // {node.signoff}</div>

        {isWin && (
          <div className="f1-preview">
            <div className="f1-preview-h">Up next on Floor 1 — and the moment Princess Donut gets her voice</div>
            <p className="f1-preview-sub">The slice ends here. Past this door: the Tutorial Guild, Mordecai's loophole lesson, the Enhanced Pet Biscuit that turns a screaming house cat into a talking crawler, the restaurant safe room, and the Ball of Swine. Here's the register that comes online the moment she eats the biscuit:</p>
            <div className="f1-preview-quips">
              {FLR.DONUT_PREVIEW.map((q, i) => (
                <div className="f1-quip" key={i}>
                  <span className="f1-quip-reg">{q.reg}</span>
                  <span className="f1-quip-line">“{q.line}”</span>
                </div>
              ))}
            </div>
          </div>
        )}

        <Floor1Scorecard hp={hp} level={level} followers={followers} accuracy={accuracy} found={found} />

        <div className="gactions">
          <button className="btn" onClick={restart}>↻ Run it back</button>
          <button className="btn ghost" onClick={toHub}>Back to Arcade</button>
        </div>
        <div className="f1-foot">
          {isWin
            ? "Endings are collectible. Wander off-canon on purpose and the System will write you a worse, funnier exit."
            : "That's one for the collection. Every wrong door is a card. Run it back and try to think like a crawler."}
        </div>
      </div>
    );
  } else {
    const isCombat = node.type === 'combat';
    body = (
      <div className="gstep" key={nodeId}>
        <Floor1HUD hp={hp} level={level} followers={followers} found={found} />
        <Floor1Panel id={node.panel} />

        {isCombat && node.enemies && (
          <div className="f1-enemies">
            {node.enemies.map((e, i) => (
              <div className="f1-enemy" key={i}>
                <span className="f1-en-name">{e.name}</span>
                <span className="f1-en-sub">{e.sub}{e.level ? ' · Lvl ' + e.level : ''}</span>
              </div>
            ))}
          </div>
        )}

        <window.SysCard from="System // Floor 1">
          {node.system.map((p, i) => <p key={i} className="f1-sys-p">{p}</p>)}
        </window.SysCard>

        {node.donut && <div className="f1-donut">{node.donut}</div>}

        {isCombat && node.tell && (
          <div className="f1-tell"><span className="f1-tell-tag">Read the tell</span>{node.tell}</div>
        )}

        <div className="gopts f1-opts">
          {node.choices.map((c, idx) => (
            <button key={idx} className="gopt" onClick={() => choose(c)}>
              <span className="gk">{String.fromCharCode(65 + idx)}</span>
              <span className="f1-opt-text">{c.text}</span>
              {c.kind && <span className="f1-opt-kind">{F1_KIND[c.kind] || ''}</span>}
            </button>
          ))}
        </div>
      </div>
    );
  }

  return (
    <div className="view"><div className="wrap">
      <div className="crumbs">
        <a onClick={() => go({ view: 'home' })}>Home</a><span className="sep">/</span>
        <a onClick={toHub}>Arcade</a><span className="sep">/</span>
        <span style={{ color: 'var(--ink)' }}>Floor 1</span>
      </div>
      <window.GameStage accent={F1_ACCENT} title="Dungeon Crawler World · Floor 1" onExit={toHub}>
        {toast && <div className="f1-toast" key={toast}>★ Achievement // {toast}</div>}
        {body}
      </window.GameStage>
    </div></div>
  );
}
window.Floor1Page = Floor1Page;
