import { rollBirth, makeBirth, CITY_TIERS, WEALTH_BANDS, PARENT_PROFILES, envOf } from '@game/births';
import { ATTRIBUTES, TOTAL_POINTS, MIN_PER, MAX_PER, hintFor } from '@game/attributes';
import { createInitialState, ACAD_TOP_LINE } from '@game/state';
import { currentStep, choose, segmentProgress, optionAvailable, ackEvent, ackResult, begin } from '@game/engine';
import { MONOLOGUES } from '@game/monologues';
import { soulLinesFor } from '@game/mbtiLines';
import { ARCHETYPES } from '@game/archetypes';

const { useState, useEffect } = React;

const TIER_COLOR = { 传奇: '#e0b341', 良好: '#5aa86a', 普通: '#7b8694', 一般: '#b07a4a', 凄惨: '#9a5050' };
const DIM_KEYS = ['财富', '家庭', '健康', '心境', '地位'];
const TIERS = ['传奇', '良好', '普通', '一般', '凄惨'];
const CHEAT_CODE = '2000';
const STORAGE_KEY = 'reborn_unlocked';

function loadUnlocked() {
  try { return new Set(JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')); } catch { return new Set(); }
}
function saveUnlocked(set) {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify([...set])); } catch { /* ignore */ }
}

function mbtiType(gs) {
  const pick = (dim, a, b) => (gs.mbti[dim][a] >= gs.mbti[dim][b] ? a : b);
  return pick('EI', 'E', 'I') + pick('SN', 'S', 'N') + pick('TF', 'T', 'F') + pick('JP', 'J', 'P');
}

function StatePanel({ gs }) {
  const flags = Object.keys(gs.flags);
  return (
    <div className="card panel">
      <div className="stat-grid tight">
        <div><span className="k">智力</span><span className="v">{gs.INT}</span></div>
        <div><span className="k">颜值</span><span className="v">{gs.LOOK}</span></div>
        <div><span className="k">韧性</span><span className="v">{gs.RES}</span></div>
        <div><span className="k">健康</span><span className="v">{gs.HP}</span></div>
        <div><span className="k">财富</span><span className="v">{gs.WEALTH}</span></div>
        <div><span className="k">心境</span><span className="v">{gs.MOOD}</span></div>
        <div><span className="k">学业</span><span className="v">{gs.ACAD.toFixed(1)}<span className="dim">/≥{ACAD_TOP_LINE}</span></span></div>
        <div><span className="k">事业</span><span className="v">{gs.CAREER}</span></div>
        <div><span className="k">家庭</span><span className="v">{gs.family}</span></div>
        <div><span className="k">风险</span><span className="v">{gs.RISK}</span></div>
      </div>
      <div className="flags">
        <span className="k">flag</span>
        <span className="v">{flags.length ? flags.join('、') : '—'}</span>
      </div>
    </div>
  );
}

function Pips({ dims }) {
  return (
    <div className="dims">
      {DIM_KEYS.map((k) => (
        <div className="dim-row" key={k}>
          <span className="dim-k">{k}</span>
          <span className="dim-bar">{[1, 2, 3, 4, 5].map((i) => <i key={i} className={'pip' + (i <= dims[k] ? ' on' : '')} />)}</span>
        </div>
      ))}
    </div>
  );
}

function ArchetypeCard({ result }) {
  const a = result.archetype;
  const [num, title] = a.name.split(' · ');
  return (
    <div className="card arch-card" style={{ borderColor: TIER_COLOR[a.tier] }}>
      <div className="arch-tier" style={{ color: TIER_COLOR[a.tier], borderColor: TIER_COLOR[a.tier] }}>{a.tier} · 第 {a.id} 号</div>
      <div className="arch-name">{num}</div>
      <div className="arch-sub">{title}</div>
      <Pips dims={a.dims} />
    </div>
  );
}

function EndSummary({ gs, onRestart, onCodex }) {
  const type = mbtiType(gs);
  const mono = gs.result ? MONOLOGUES[gs.result.archetype.id] : '';
  const soul = soulLinesFor(type, gs.result ? gs.result.luck : 0.5);
  return (
    <div className="sheet">
      <header className="title">
        <h1>你的人生写照</h1>
        <p>三十岁只是一张快照——往后的路，还长着呢。从这里望去，你大抵会活成这样一个人。</p>
      </header>
      {gs.result ? <ArchetypeCard result={gs.result} /> : null}
      <div className="card mono-card">
        <p className="mono">{mono}</p>
        <div className="soul">
          <div className="soul-type">MBTI · {type}</div>
          {soul.map((line, i) => <p className="soul-line" key={i}>{line}</p>)}
        </div>
      </div>
      <div className="card">
        <h2>{gs.birth.city} · {gs.birth.gender} · {gs.birth.band}家庭</h2>
        <p className="bio">{gs.birth.bio}</p>
      </div>
      <StatePanel gs={gs} />
      <button className="primary" onClick={onRestart}>再活一次</button>
      <button className="ghost wide-btn" onClick={onCodex}>人生图鉴</button>
    </div>
  );
}

const FIELD_LABEL = { INT: '智力', LOOK: '颜值', RES: '韧性', HP: '健康', WEALTH: '财富', MOOD: '心境', CAREER: '事业', family: '家庭', RISK: '风险', ACAD: '学业' };
const fmt = (n) => { const r = Math.round(n * 10) / 10; return Number.isInteger(r) ? r.toString() : r.toFixed(1); };

function ResultCard({ gs, result, onAck, onRestart }) {
  const visibleDeltas = result.deltas.filter((d) => FIELD_LABEL[d.key]);
  return (
    <div className="sheet">
      <div className="prog">
        <span className="prog-stage">🎲 掷骰结果</span>
        <div className="prog-bar"><div className="prog-fill" style={{ width: '100%', background: 'var(--accent)' }} /></div>
        <span className="prog-num">见分晓</span>
      </div>
      <StatePanel gs={gs} />
      <div className="card result-card">
        <div className="result-pick">你选择：{result.name}</div>
        <h2 className="result-name">{result.text}</h2>
        {visibleDeltas.length ? (
          <div className="result-deltas">
            {visibleDeltas.map((d) => {
              const diff = d.to - d.from;
              const cls = diff > 0 ? 'pos' : 'neg';
              return (
                <div className={'delta-row ' + cls} key={d.key}>
                  <span className="dk">{FIELD_LABEL[d.key]}</span>
                  <span className="dv">{fmt(d.from)} → {fmt(d.to)}</span>
                  <span className="dd">{diff > 0 ? '+' : ''}{fmt(diff)}</span>
                </div>
              );
            })}
          </div>
        ) : null}
        {result.flagsAdded.length ? (
          <div className="result-flags-block">
            <span className="rfb-k">新增标记</span>
            <span className="rfb-chips">{result.flagsAdded.map((f) => <span className="flag-chip" key={f}>{f}</span>)}</span>
          </div>
        ) : null}
        <button className="primary" onClick={onAck}>继续</button>
      </div>
      <button className="ghost wide-btn" onClick={onRestart}>重开一局</button>
    </div>
  );
}

function EventCard({ gs, event, onAck, onRestart }) {
  return (
    <div className="sheet">
      <div className="prog">
        <span className="prog-stage">历史 · {event.year}</span>
        <div className="prog-bar"><div className="prog-fill" style={{ width: '100%', background: '#5a4a8a' }} /></div>
        <span className="prog-num">大事记</span>
      </div>
      <StatePanel gs={gs} />
      <div className="card event-card">
        <div className="event-badge">{event.year} · {event.name}</div>
        <p className="scene">{event.intro}</p>
        {event.react ? (
          <div className="opts">
            {event.react.map((o, i) => (
              <button key={i} className="opt" onClick={() => onAck(i)}>
                <span className="opt-label">{o.label}</span>
                {o.desc ? <span className="opt-desc">{o.desc}</span> : null}
              </button>
            ))}
          </div>
        ) : (
          <>
            <p className="event-result">{event.text}</p>
            <button className="primary" onClick={() => onAck(0)}>继续</button>
          </>
        )}
      </div>
      <button className="ghost wide-btn" onClick={onRestart}>重开一局</button>
    </div>
  );
}

function Play({ gs, setGs, onRestart, onCodex }) {
  const step = currentStep(gs);
  if (step.type === 'end') return <EndSummary gs={gs} onRestart={onRestart} onCodex={onCodex} />;
  if (step.type === 'result') return <ResultCard gs={gs} result={step.result} onAck={() => setGs(ackResult(gs))} onRestart={onRestart} />;
  if (step.type === 'event') return <EventCard gs={gs} event={step.event} onAck={(i) => setGs(ackEvent(gs, i))} onRestart={onRestart} />;
  const q = step.question;
  const prog = segmentProgress(gs);
  return (
    <div className="sheet">
      <div className="prog">
        <span className="prog-stage">{q.stage}</span>
        <div className="prog-bar"><div className="prog-fill" style={{ width: `${(prog.done / prog.total) * 100}%` }} /></div>
        <span className="prog-num">{prog.done + 1} / {prog.total}</span>
      </div>
      <StatePanel gs={gs} />
      <div className="card">
        <p className="scene">{q.scene}</p>
        <h2 className="qprompt">{q.prompt}</h2>
        <div className="opts">
          {q.options.map((o, i) => ({ o, i }))
            .filter(({ o }) => optionAvailable(o, gs) || !o.hideIfLocked)
            .map(({ o, i }) => {
              const ok = optionAvailable(o, gs);
              return (
                <button key={i} className="opt" disabled={!ok} onClick={() => ok && setGs(choose(gs, i))}>
                  <span className="opt-label">{o.label}</span>
                  {o.desc ? <span className="opt-desc">{o.desc}</span> : null}
                  {!ok && o.lockHint ? <span className="opt-lock">🔒 {o.lockHint}</span> : null}
                </button>
              );
            })}
        </div>
      </div>
      <button className="ghost wide-btn" onClick={onRestart}>重开一局</button>
    </div>
  );
}

function BirthCard({ birth, rerolls, onReroll }) {
  const economy = birth.familyEconomy.length ? birth.familyEconomy.join('、') : '普通工薪';
  return (
    <div className="card birth">
      <div className="card-head">
        <h2>你的出身</h2>
        <button className="ghost" onClick={onReroll} disabled={rerolls <= 0}>重投世界（剩 {rerolls} 次）</button>
      </div>
      <div className="birth-grid">
        <div><span className="k">性别</span><span className="v">{birth.gender}</span></div>
        <div><span className="k">出生地</span><span className="v">{birth.city}</span></div>
        <div><span className="k">户口</span><span className="v">{birth.hukou}</span></div>
        <div><span className="k">家境</span><span className="v">{birth.band}（财富初值 {birth.initialWealth}）</span></div>
        <div><span className="k">父亲</span><span className="v">{birth.parents.father}</span></div>
        <div><span className="k">母亲</span><span className="v">{birth.parents.mother}</span></div>
        <div className="wide"><span className="k">家庭经济</span><span className="v">{economy}</span></div>
      </div>
      <p className="bio">{birth.bio}</p>
    </div>
  );
}

function CheatPanel({ onApply }) {
  const [gender, setGender] = useState('男');
  const [tierKey, setTierKey] = useState('一线');
  const [city, setCity] = useState(CITY_TIERS[0].cities[0]);
  const [band, setBand] = useState('普通');
  const tier = CITY_TIERS.find((t) => t.key === tierKey);
  const pool = PARENT_PROFILES[envOf(tierKey)][band];
  const [profileId, setProfileId] = useState(pool[0].id);
  const [stock, setStock] = useState(false);

  function onTier(k) {
    setTierKey(k);
    const t = CITY_TIERS.find((x) => x.key === k);
    setCity(t.cities[0]);
    setProfileId(PARENT_PROFILES[envOf(k)][band][0].id);
  }
  function onBand(b) {
    setBand(b);
    setProfileId(PARENT_PROFILES[envOf(tierKey)][b][0].id);
  }
  function apply() {
    onApply(makeBirth({ tier: tierKey, city, band, gender, profileId, stock }));
  }

  return (
    <div className="card cheat">
      <h2>秘籍：自选出身</h2>
      <div className="cheat-grid">
        <label>性别
          <select value={gender} onChange={(e) => setGender(e.target.value)}>
            <option>男</option><option>女</option>
          </select>
        </label>
        <label>城市档
          <select value={tierKey} onChange={(e) => onTier(e.target.value)}>
            {CITY_TIERS.map((t) => <option key={t.key} value={t.key}>{t.key}</option>)}
          </select>
        </label>
        <label>城市
          <select value={city} onChange={(e) => setCity(e.target.value)}>
            {tier.cities.map((c) => <option key={c} value={c}>{c}</option>)}
          </select>
        </label>
        <label>家境
          <select value={band} onChange={(e) => onBand(e.target.value)}>
            {WEALTH_BANDS.map((b) => <option key={b} value={b}>{b}</option>)}
          </select>
        </label>
        <label className="wide">父母传记
          <select value={profileId} onChange={(e) => setProfileId(e.target.value)}>
            {pool.map((p) => <option key={p.id} value={p.id}>{p.father} / {p.mother}</option>)}
          </select>
        </label>
        <label className="check"><input type="checkbox" checked={stock} onChange={(e) => setStock(e.target.checked)} /> 家有炒股倾向</label>
      </div>
      <button className="ghost" onClick={apply}>应用此出身</button>
    </div>
  );
}

function Codex({ unlocked, onBack }) {
  const [sel, setSel] = useState(null);
  return (
    <div className="sheet">
      <header className="title">
        <h1>人生图鉴</h1>
        <p>已解锁 {unlocked.size} / 108 —— 多走几条路，解锁更多人生。</p>
      </header>
      {sel ? (
        <div className="card mono-card">
          <div className="arch-tier" style={{ color: TIER_COLOR[sel.tier], borderColor: TIER_COLOR[sel.tier] }}>{sel.tier} · 第 {sel.id} 号</div>
          <div className="arch-name" style={{ fontSize: '22px' }}>{sel.name.split(' · ')[0]}</div>
          <div className="arch-sub">{sel.name.split(' · ')[1]}</div>
          <Pips dims={sel.dims} />
          <p className="mono" style={{ marginTop: 16 }}>{MONOLOGUES[sel.id]}</p>
          <button className="ghost" onClick={() => setSel(null)}>收起</button>
        </div>
      ) : null}
      {TIERS.map((t) => (
        <div className="codex-tier" key={t}>
          <h2 style={{ color: TIER_COLOR[t] }}>{t}</h2>
          <div className="codex-grid">
            {ARCHETYPES.filter((a) => a.tier === t).map((a) => {
              const got = unlocked.has(a.id);
              return (
                <button key={a.id} className={'codex-cell' + (got ? ' got' : '')} disabled={!got} onClick={() => got && setSel(a)}
                  style={got ? { borderColor: TIER_COLOR[t] } : null}>
                  <span className="codex-id">{a.id}</span>
                  <span className="codex-name">{got ? a.name.split(' · ')[0] : '？？？'}</span>
                </button>
              );
            })}
          </div>
        </div>
      ))}
      <button className="primary" onClick={onBack}>返回</button>
    </div>
  );
}

function App() {
  const [phase, setPhase] = useState('create'); // create | play | codex
  const [codexFrom, setCodexFrom] = useState('create');
  const [attrs, setAttrs] = useState({ INT: 5, LOOK: 5, RES: 5, HP: 5 });
  const [birth, setBirth] = useState(() => rollBirth());
  const [rerolls, setRerolls] = useState(3);
  const [gs, setGs] = useState(null);
  const [unlocked, setUnlocked] = useState(loadUnlocked);
  const [cheatInput, setCheatInput] = useState('');

  const resultId = gs && gs.result ? gs.result.archetype.id : null;
  useEffect(() => {
    if (resultId == null) return;
    setUnlocked((prev) => {
      if (prev.has(resultId)) return prev;
      const next = new Set(prev); next.add(resultId); saveUnlocked(next); return next;
    });
  }, [resultId]);

  const used = ATTRIBUTES.reduce((s, a) => s + attrs[a.key], 0);
  const remaining = TOTAL_POINTS - used;
  const cheatOn = cheatInput.trim() === CHEAT_CODE;

  function inc(key) { if (remaining > 0 && attrs[key] < MAX_PER) setAttrs((p) => ({ ...p, [key]: p[key] + 1 })); }
  function dec(key) { if (attrs[key] > MIN_PER) setAttrs((p) => ({ ...p, [key]: p[key] - 1 })); }
  function reroll() { if (rerolls > 0) { setBirth(rollBirth()); setRerolls((r) => r - 1); } }
  function confirm() { if (remaining !== 0) return; setGs(begin(createInitialState({ attributes: attrs, birth }))); setPhase('play'); }
  function restart() { setAttrs({ INT: 5, LOOK: 5, RES: 5, HP: 5 }); setBirth(rollBirth()); setRerolls(3); setGs(null); setPhase('create'); }
  function openCodex(from) { setCodexFrom(from); setPhase('codex'); }

  if (phase === 'codex') return <Codex unlocked={unlocked} onBack={() => setPhase(codexFrom)} />;
  if (phase === 'play') return <Play gs={gs} setGs={setGs} onRestart={restart} onCodex={() => openCodex('play')} />;

  return (
    <div className="sheet">
      <header className="title">
        <h1>重生 2000</h1>
        <p>你将以 2000 年生于中国大陆的身份重生，历经真实历史，走出一条只属于你的人生。</p>
        <button className="ghost codex-btn" onClick={() => openCodex('create')}>人生图鉴 {unlocked.size}/108</button>
      </header>
      <BirthCard birth={birth} rerolls={rerolls} onReroll={reroll} />
      {cheatOn ? <CheatPanel onApply={setBirth} /> : null}
      <div className="card">
        <div className="card-head">
          <h2>分配天赋</h2>
          <span className={'points' + (remaining === 0 ? ' ok' : '')}>剩余 {remaining} 点</span>
        </div>
        <p className="hint-sub">共 20 点，每项 1–10，须全部用尽。</p>
        {ATTRIBUTES.map((a) => {
          const v = attrs[a.key];
          const hint = hintFor(a.key, v);
          return (
            <div className="attr-row" key={a.key}>
              <div className="attr-meta">
                <span className="attr-name">{a.name}</span>
                <span className="attr-desc">{a.desc}</span>
              </div>
              <div className="stepper">
                <button onClick={() => dec(a.key)} disabled={v <= MIN_PER}>−</button>
                <span className="attr-val">{v}</span>
                <button onClick={() => inc(a.key)} disabled={remaining <= 0 || v >= MAX_PER}>+</button>
              </div>
              <span className={'flavor' + (hint ? ' show' : '')}>{hint}</span>
            </div>
          );
        })}
      </div>
      <button className="primary" onClick={confirm} disabled={remaining !== 0}>
        {remaining === 0 ? '开始这一生' : `还需分配 ${remaining} 点`}
      </button>
      <input className="cheat-input" value={cheatInput} onChange={(e) => setCheatInput(e.target.value)} placeholder="秘籍…" />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
