// v2-app.jsx — Tagico Web v2 プロトタイプ: ホーム / 統計 / 復習 / ルート
// 依存: v2-data.js, v2-store.js, v2-quiz.jsx, tweaks-panel.jsx

// レベル内で「次にやるべき単語」の位置を cleared から算出（着手済みはスキップ）。
// resume.pos に頼らず cleared を真実のソースにすることで、状態がずれても自己修復する。
function tgNextPos(levelNo, store) {
  const lv = TAGICO_LEVELS.find(l => l.no === levelNo);
  if (!lv) return 0;
  for (let i = 0; i < lv.count; i++) {
    const w = TAGICO_WORDS[lv.start + i].word;
    if (!store.cleared[w]) return i;       // 未着手の最初の単語
  }
  return 0;                                 // 全単語クリア済み → 最初から（復習）
}

// ── 共通: ナビ ─────────────────────────────────────────────
function V2Nav({ route, go, streak }) {
  const items = [['home', 'ホーム'], ['words', '単語帳'], ['review', '復習'], ['stats', '統計']];
  return (
    <nav className="tg-nav">
      <span className="tg-logo" onClick={() => go('home')}>Tagico</span>
      <div className="tg-nav-tabs">
        {items.map(([id, label]) => (
          <button key={id} className={`tg-nav-tab ${route === id ? 'active' : ''}`} onClick={() => go(id)}>{label}</button>
        ))}
      </div>
      <div className="tg-streakpill" title="連続学習日数">
        <span className="flame">🔥</span>
        <b>{streak}</b><span className="unit">日連続</span>
      </div>
    </nav>
  );
}

// ── ホーム ─────────────────────────────────────────────────
function V2Home({ store, startLevel, startReview, resumeQuiz, setFormat }) {
  const reviewCount = Object.keys(store.missCounts).length;
  const clearedCount = Object.keys(store.cleared).length;
  return (
    <div className="tg-home">
      <div className="tg-home-left">
        <p className="tg-eyebrow">the many faces of one word</p>
        <h1 className="tg-h1">Tagico</h1>
        <p className="tg-sub">
          同じ単語の「いくつもの顔」を、文脈の手がかりから見抜く練習。訳を覚えるのではなく、<b>どの意味かを当てる</b>ためのトレーニング。
        </p>

        {store.resume ? (() => {
          const lvNo = store.resume.levelNo;
          const lv = TAGICO_LEVELS.find(l => l.no === lvNo);
          const p = tgNextPos(lvNo, store);            // cleared から「次の単語」を算出
          const wordIdx = lv.start + p;
          return (
          <button className="tg-continue" onClick={resumeQuiz}>
            <span className="label">つづきから</span>
            <span className="line">
              <b>Level {lvNo}</b>
              <em>次は {TAGICO_WORDS[wordIdx].word}</em>
            </span>
            <span className="bar"><span className="fill" style={{ width: `${p / lv.count * 100}%` }}></span></span>
            <span className="cnt">{p}/{lv.count}語</span>
          </button>
          );
        })() : (
          <button className="tg-continue" onClick={() => startLevel(1)}>
            <span className="label">はじめる</span>
            <span className="line">
              <b>Level 1</b>
              <em>some から</em>
            </span>
          </button>
        )}

        {reviewCount > 0 && (
          <button className="tg-reviewbanner" onClick={startReview}>
            <span className="ico">↻</span>
            <span className="txt"><b>{reviewCount}語</b> が復習どき</span>
            <span className="go">復習する →</span>
          </button>
        )}
      </div>

      <div className="tg-home-right">
        <div className="tg-levels-head">
          <span className="t">クイズを始める</span>
          <span className="c">{clearedCount}/{TAGICO_WORDS.length}語クリア</span>
        </div>
        <div className="tg-levels">
          {TAGICO_LEVELS.map(lv => {
            const words = TAGICO_WORDS.slice(lv.start, lv.start + lv.count);
            const done = words.filter(w => store.cleared[w.word] && store.cleared[w.word].best === store.cleared[w.word].total).length;
            return (
              <button key={lv.no} className="tg-levelcard" onClick={() => startLevel(lv.no)} data-comment-anchor={`level-${lv.no}`}>
                <span className={`tg-levelbadge ${done === lv.count ? 'done' : ''}`}>
                  <span className="lv">Lv</span><span className="no">{lv.no}</span>
                </span>
                <span className="main">
                  <span className="words">
                    {words.map(w => <em key={w.word} className="w">{w.word}</em>)}
                  </span>
                  <span className="prog">
                    <span className="bar"><span className="fill" style={{ width: `${done / lv.count * 100}%`, background: done === lv.count ? 'var(--green)' : 'var(--vermilion)' }}></span></span>
                    <span className="cnt">{done}/{lv.count}語クリア</span>
                  </span>
                </span>
                <span className="go">→</span>
              </button>
            );
          })}
          <div className="tg-levelcard locked">
            <span className="tg-levelbadge"><span className="lv">Lv</span><span className="no">3</span></span>
            <span className="main">
              <span className="note">近日公開 — 単語をどんどん追加していきます</span>
            </span>
          </div>
        </div>
        <p className="tg-homenote">進捗はこのブラウザに自動保存されます</p>
      </div>
    </div>
  );
}

// ── 統計 ───────────────────────────────────────────────────
function V2Stats({ store }) {
  const streak = tgv2.streak(store.history);
  const week = tgv2.week(store.history);
  const max = Math.max(...week.map(w => w.n), 1);
  const weekTotal = week.reduce((a, w) => a + w.n, 0);
  const clearedCount = Object.keys(store.cleared).length;
  const { hits, avoids } = store.trapStats;
  const trapPct = (hits + avoids) ? Math.round(avoids / (hits + avoids) * 100) : null;
  const worst = Object.entries(store.missCounts)
    .sort((a, b) => b[1].count - a[1].count).slice(0, 3);
  const empty = clearedCount === 0 && weekTotal === 0;

  return (
    <div className="tg-page">
      <h1 className="tg-pagetitle">統計</h1>
      {empty && <p className="tg-empty">まだ記録がありません。クイズを1語クリアすると、ここに学習の足あとが残ります。</p>}
      <div className="tg-stats-grid">
        <div className="tg-statcard">
          <div className="big">🔥 {streak}<small>日連続</small></div>
          <p className="sub">{streak > 0 ? '今日もつなげよう' : '今日1語クリアで点火'}</p>
        </div>
        <div className="tg-statcard">
          <div className="big">{clearedCount}<small>/{TAGICO_WORDS.length}語</small></div>
          <div className="bar"><span className="fill" style={{ width: `${clearedCount / TAGICO_WORDS.length * 100}%` }}></span></div>
          <p className="sub">クリアした単語</p>
        </div>
        <div className="tg-statcard cream">
          <div className="big">{trapPct === null ? '—' : `${trapPct}%`}</div>
          <p className="sub"><b>罠回避率</b> — 思い込み訳にひっかからなかった割合</p>
        </div>
      </div>
      <div className="tg-stats-cols">
        <div className="tg-statcard">
          <div className="head"><span>今週の学習</span><span className="faint">合計 {weekTotal}語</span></div>
          <div className="tg-weekbars">
            {week.map((w, i) => (
              <div key={i} className="col">
                <div className={`bar ${w.isToday ? 'today' : ''}`} style={{ height: `${Math.max(w.n / max * 100, w.n > 0 ? 12 : 4)}%` }}></div>
                <span className={`d ${w.isToday ? 'today' : ''}`}>{w.label}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="tg-statcard">
          <div className="head"><span>にがての顔 トップ3</span></div>
          {worst.length === 0
            ? <p className="tg-empty small">間違いゼロ。きれいなものです。</p>
            : worst.map(([word, m]) => {
              const topSense = Object.entries(m.senses).sort((a, b) => b[1] - a[1])[0];
              const W = TAGICO_WORDS.find(x => x.word === word);
              const senseLabel = W && topSense ? `「${W.senses[topSense[0]].answer}」の顔` : '';
              return (
                <div key={word} className="tg-worstrow">
                  <em className="w">{word}</em>
                  <span className="f">{senseLabel}</span>
                  <span className="n">{m.count}回ミス</span>
                </div>
              );
            })}
        </div>
      </div>
    </div>
  );
}

// ── 復習 ───────────────────────────────────────────────────
function V2Review({ store, startReview }) {
  const entries = Object.entries(store.missCounts).sort((a, b) => b[1].count - a[1].count);
  return (
    <div className="tg-page">
      <h1 className="tg-pagetitle">復習</h1>
      {entries.length === 0 ? (
        <p className="tg-empty">復習リストは空です。クイズで間違えた単語が、ここに溜まっていきます。</p>
      ) : (
        <div className="tg-review-grid">
          <div>
            <div className="tg-reviewhero">
              <p className="label">今日の復習</p>
              <div className="num">{entries.length}<small>語</small></div>
              <p className="desc">間違えた顔だけ、もう一度。<br></br>完璧に答えると卒業に近づきます。</p>
              <button className="tg-btn white" onClick={startReview}>▶ まとめて復習する</button>
            </div>
            <p className="tg-homenote">ノーミスで2回クリアすると、リストから卒業します</p>
          </div>
          <div className="tg-reviewlist">
            {entries.map(([word, m]) => {
              const W = TAGICO_WORDS.find(x => x.word === word);
              const topSense = Object.entries(m.senses).sort((a, b) => b[1] - a[1])[0];
              return (
                <div key={word} className="tg-reviewrow">
                  <em className="w">{word}</em>
                  <span className="main">
                    <span className="miss">{W && topSense ? `「${W.senses[topSense[0]].answer}」の顔` : ''}{m.count >= 2 ? ` ほか — ${m.count}回ミス` : ` — ${m.count}回ミス`}</span>
                    <span className="grad">卒業まで {2 - (m.grad || 0)} 回</span>
                  </span>
                  <span className="dots">
                    {[0, 1].map(j => <span key={j} className={`gd ${j < (m.grad || 0) ? 'on' : ''}`}></span>)}
                  </span>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

// ── 単語帳（クリアした単語の用法一覧） ───────────────────────
function V2Words({ store }) {
  const [open, setOpen] = React.useState(null);
  const clearedCount = TAGICO_WORDS.filter(w => store.cleared[w.word]).length;
  return (
    <div className="tg-page">
      <h1 className="tg-pagetitle">単語帳</h1>
      <p className="tg-pagesub">クリアした単語の用法まとめを、いつでも見返せます（{clearedCount}/{TAGICO_WORDS.length}語）</p>
      {clearedCount === 0 && <p className="tg-empty">まだ1語もクリアしていません。クイズをクリアすると、ここに用法まとめが並びます。</p>}
      <div className="tg-wordbook">
        {TAGICO_WORDS.map((w) => {
          const cleared = !!store.cleared[w.word];
          const J = TAGICO_JUDGING[w.word];
          const isOpen = open === w.word;
          if (!cleared) {
            return (
              <div key={w.word} className="tg-wbrow locked">
                <em className="w">{w.word}</em>
                <span className="hl">？？？</span>
                <span className="lock">クリアで解放</span>
              </div>
            );
          }
          return (
            <div key={w.word} className="tg-wbrow">
              <button className="head" onClick={() => setOpen(isOpen ? null : w.word)}>
                <em className="w">{w.word}</em>
                <span className="hl">{w.coreImage.headline}</span>
                {J && <span className="n">{J.faces.length}つの顔</span>}
                <span className="arrow">{isOpen ? '−' : '+'}</span>
              </button>
              {isOpen && (
                <div className="body">
                  <p className="lead">{w.coreImage.lead}</p>
                  {J && (
                    <React.Fragment>
                      <div className="tg-faces">
                        {J.faces.map((f, i) => (
                          <div key={i} className="tg-face">
                            <span className="f">{'①②③④⑤⑥⑦⑧⑨⑩'[i] || ''}{f.face}</span>
                            <span className="j">{f.jp}</span>
                            <span className="u">
                              {f.pattern && <code className="pat">{f.pattern}</code>}
                              {f.note && <span className="note">{f.note}</span>}
                            </span>
                          </div>
                        ))}
                      </div>
                      {(J.trivia || []).map((tr, i) => (
                        <p key={i} className="tg-trivia" dangerouslySetInnerHTML={{ __html: '✍️ ' + tr }}></p>
                      ))}
                    </React.Fragment>
                  )}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ── ルート ─────────────────────────────────────────────────
const V2_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#C8442A",
  "enSize": 20
}/*EDITMODE-END*/;

function V2App() {
  // 本番では Tweaks パネルを無効化（固定値を使用）
  const t = V2_TWEAK_DEFAULTS;
  const setTweak = function(){};
  const [route, setRoute] = React.useState('home');
  const [store, setStore] = React.useState(tgv2.load);
  const [session, setSession] = React.useState(null); // { queue, pos, mode, levelNo, results }

  React.useEffect(() => {
    document.documentElement.style.setProperty('--vermilion', t.accent);
    document.documentElement.style.setProperty('--en-size', t.enSize + 'px');
  }, [t.accent, t.enSize]);

  const streak = tgv2.streak(store.history);

  function go(r) { setRoute(r); }

  function setFormat(f) {
    const s = tgv2.load(); s.quizFormat = f; tgv2.save(s); setStore(tgv2.load());
  }

  function startLevel(no) {
    const lv = TAGICO_LEVELS.find(l => l.no === no);
    const queue = Array.from({ length: lv.count }, (_, i) => lv.start + i);
    // cleared から「次にやるべき単語」を算出（着手済みはスキップ・自己修復）
    const startPos = tgNextPos(no, tgv2.load());
    setSession({ queue, pos: startPos, mode: 'level', levelNo: no, results: [], format: 'en' });
    tgv2.setResume({ levelNo: no, wordIdx: queue[startPos], pos: startPos, queueLen: queue.length });
    setStore(tgv2.load());
    setRoute('quiz');
  }
  function startReview() {
    const words = Object.keys(tgv2.load().missCounts);
    if (words.length === 0) return;
    const queue = words.map(w => TAGICO_WORDS.findIndex(x => x.word === w)).filter(i => i >= 0);
    setSession({ queue, pos: 0, mode: 'review', levelNo: null, results: [], format: 'en' });
    setRoute('quiz');
  }
  function resumeQuiz() {
    const r = tgv2.load().resume;
    startLevel(r ? r.levelNo : 1);   // startLevel が cleared から続きを判定（一元化）
  }
  function onWordDone(result) {
    const s = { ...session, results: session.results.concat([result]) };
    if (s.pos + 1 < s.queue.length) {
      s.pos++;
      if (s.mode === 'level') tgv2.setResume({ levelNo: s.levelNo, wordIdx: s.queue[s.pos], pos: s.pos, queueLen: s.queue.length });
      setSession(s);
    } else {
      if (s.mode === 'level') tgv2.setResume(null);
      setSession(s);
      setRoute('result');
    }
    setStore(tgv2.load());
  }
  function exitQuiz() { setStore(tgv2.load()); setRoute('home'); }

  return (
    <div className="tg-app">
      {route !== 'quiz' && <V2Nav route={route} go={go} streak={streak}></V2Nav>}
      <main className="tg-main">
        {route === 'home' && <V2Home store={store} startLevel={startLevel} startReview={startReview} resumeQuiz={resumeQuiz} setFormat={setFormat}></V2Home>}
        {route === 'words' && <V2Words store={store}></V2Words>}
        {route === 'stats' && <V2Stats store={store}></V2Stats>}
        {route === 'review' && <V2Review store={store} startReview={startReview}></V2Review>}
        {route === 'quiz' && session && (
          <QuizScreen key={`${session.mode}-${session.pos}`} queue={session.queue} pos={session.pos}
            mode={session.mode} levelNo={session.levelNo} format={session.format || 'en'} onWordDone={onWordDone} onExit={exitQuiz}></QuizScreen>
        )}
        {route === 'result' && session && (
          <ResultScreen session={session}
            onHome={() => { setSession(null); exitQuiz(); }}
            onRetry={() => { session.mode === 'review' ? startReview() : startLevel(session.levelNo); }}
            onNextLevel={() => startLevel(session.levelNo + 1)}></ResultScreen>
        )}
      </main>
      <footer className="tg-footer">
        <p className="en">One core, blurred five ways.</p>
        <p>Tagico β — <a href="https://x.com/toto_aidev" style={{color:'var(--ink-faint)',textDecoration:'underline',textUnderlineOffset:'3px'}}>@toto_aidev</a></p>
      </footer>
    </div>
  );
}

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