// 医療情報技師 試験対策SPA
const { useState, useEffect, useMemo, useRef } = React;

// ---------- ストレージ ----------
const STORAGE_KEY = "miit_quiz_state_v1";
const loadState = () => {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return defaultState();
    const s = JSON.parse(raw);
    return { ...defaultState(), ...s };
  } catch { return defaultState(); }
};
const saveState = (s) => {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch {}
};
function defaultState() {
  return {
    // qid -> { attempts, correct, lastResult: 'correct'|'wrong', lastAt }
    history: {},
  };
}
const qid = (q) => `${q.year}-${q.subject}-${q.question_number}`;

// ---------- ユーティリティ ----------
const shuffle = (arr) => {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
};
const arrEq = (a, b) => a.length === b.length && a.every((v) => b.includes(v));

// ---------- アプリ ----------
function App() {
  const all = window.QUESTIONS || [];
  const [state, setState] = useState(loadState);
  const [screen, setScreen] = useState("start"); // start | quiz | result | stats
  const [filters, setFilters] = useState({
    years: [],     // 空 = すべて
    subjects: [],  // 空 = すべて
    unseenOnly: false,
  });
  const [queue, setQueue] = useState([]); // 出題予定の問題リスト（順番固定）
  const [cursor, setCursor] = useState(0);
  const [sessionLog, setSessionLog] = useState([]); // {qid, result}

  useEffect(() => { saveState(state); }, [state]);

  const years = useMemo(() => [...new Set(all.map((q) => q.year))].sort(), [all]);
  const subjects = useMemo(() => [...new Set(all.map((q) => q.subject))], [all]);

  const startSession = () => {
    let pool = all.filter((q) => {
      if (filters.years.length && !filters.years.includes(q.year)) return false;
      if (filters.subjects.length && !filters.subjects.includes(q.subject)) return false;
      if (filters.unseenOnly) {
        const h = state.history[qid(q)];
        if (h && h.attempts > 0) return false;
      }
      return true;
    });
    if (filters.unseenOnly && pool.length === 0) {
      // 未出題が無ければ全体から選ぶ
      pool = all.filter((q) => {
        if (filters.years.length && !filters.years.includes(q.year)) return false;
        if (filters.subjects.length && !filters.subjects.includes(q.subject)) return false;
        return true;
      });
    }
    if (pool.length === 0) return;
    const shuffled = shuffle(pool);
    setQueue(shuffled);
    setCursor(0);
    setSessionLog([]);
    setScreen("quiz");
  };

  const recordResult = (q, result) => {
    setState((prev) => {
      const id = qid(q);
      const h = prev.history[id] || { attempts: 0, correct: 0 };
      return {
        ...prev,
        history: {
          ...prev.history,
          [id]: {
            attempts: h.attempts + 1,
            correct: h.correct + (result === "correct" ? 1 : 0),
            lastResult: result,
            lastAt: Date.now(),
          },
        },
      };
    });
    setSessionLog((s) => [...s, { qid: qid(q), result }]);
  };

  const goNext = () => {
    if (cursor + 1 >= queue.length) {
      setScreen("result");
    } else {
      setCursor((c) => c + 1);
    }
  };

  const resetHistory = () => {
    if (confirm("学習履歴をすべて削除します。よろしいですか？")) {
      setState(defaultState());
    }
  };

  return (
    <div className="app">
      <Header onHome={() => setScreen("start")} onStats={() => setScreen("stats")} screen={screen} />
      <main className="main">
        {screen === "start" && (
          <StartScreen
            years={years}
            subjects={subjects}
            filters={filters}
            setFilters={setFilters}
            history={state.history}
            all={all}
            onStart={startSession}
          />
        )}
        {screen === "quiz" && queue.length > 0 && (
          <QuizScreen
            key={cursor}
            question={queue[cursor]}
            index={cursor}
            total={queue.length}
            onResult={recordResult}
            onNext={goNext}
            onQuit={() => setScreen("start")}
          />
        )}
        {screen === "result" && (
          <ResultScreen
            log={sessionLog}
            queue={queue}
            onRestart={() => setScreen("start")}
            onAgain={startSession}
          />
        )}
        {screen === "stats" && (
          <StatsScreen
            all={all}
            history={state.history}
            onReset={resetHistory}
            onClose={() => setScreen("start")}
          />
        )}
      </main>
    </div>
  );
}

// ---------- ヘッダー ----------
function Header({ onHome, onStats, screen }) {
  return (
    <header className="header">
      <button className="brand" onClick={onHome} aria-label="ホーム">
        <span className="brand-mark">医</span>
        <span className="brand-text">医療情報技師<br/><small>試験対策</small></span>
      </button>
      {screen !== "stats" && (
        <button className="icon-btn" onClick={onStats} aria-label="統計を見る">
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
        </button>
      )}
    </header>
  );
}

// ---------- スタート画面 ----------
function StartScreen({ years, subjects, filters, setFilters, history, all, onStart }) {
  const toggleYear = (y) => setFilters((f) => ({
    ...f,
    years: f.years.includes(y) ? f.years.filter((x) => x !== y) : [...f.years, y],
  }));
  const toggleSubject = (s) => setFilters((f) => ({
    ...f,
    subjects: f.subjects.includes(s) ? f.subjects.filter((x) => x !== s) : [...f.subjects, s],
  }));

  // 該当問題数のプレビュー
  const matched = all.filter((q) => {
    if (filters.years.length && !filters.years.includes(q.year)) return false;
    if (filters.subjects.length && !filters.subjects.includes(q.subject)) return false;
    if (filters.unseenOnly) {
      const h = history[qid(q)];
      if (h && h.attempts > 0) return false;
    }
    return true;
  }).length;

  const totalAttempts = Object.values(history).reduce((a, h) => a + h.attempts, 0);

  return (
    <div className="screen start">
      <div className="hero">
        <p className="hero-eyebrow">こんにちは</p>
        <h1 className="hero-title">今日も<br/>少しずつ進めよう。</h1>
        <p className="hero-meta">
          全 {all.length} 問 ／ これまで {totalAttempts} 回回答
        </p>
      </div>

      <section className="filter-card">
        <h2 className="filter-title">年度</h2>
        <div className="chips">
          {years.map((y) => (
            <button
              key={y}
              className={`chip ${filters.years.includes(y) ? "is-on" : ""}`}
              onClick={() => toggleYear(y)}
            >{y}</button>
          ))}
        </div>

        <h2 className="filter-title">科目</h2>
        <div className="chips">
          {subjects.map((s) => (
            <button
              key={s}
              className={`chip ${filters.subjects.includes(s) ? "is-on" : ""}`}
              onClick={() => toggleSubject(s)}
            >{s}</button>
          ))}
        </div>

        <label className="toggle">
          <input
            type="checkbox"
            checked={filters.unseenOnly}
            onChange={(e) => setFilters((f) => ({ ...f, unseenOnly: e.target.checked }))}
          />
          <span className="toggle-track"><span className="toggle-thumb"/></span>
          <span className="toggle-label">未出題の問題を優先する</span>
        </label>
      </section>

      <div className="start-footer">
        <p className="match-count">
          <span className="match-num">{matched}</span> 問が出題されます
        </p>
        <button className="primary-btn" disabled={matched === 0} onClick={onStart}>
          スタート
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
        </button>
      </div>
    </div>
  );
}

// ---------- 出題画面 ----------
function QuizScreen({ question, index, total, onResult, onNext, onQuit }) {
  // 選択肢シャッフル＋インデックスマッピング
  const shuffled = useMemo(() => {
    const idx = question.choices.map((_, i) => i + 1); // 元の番号 1..n
    return shuffle(idx);
  }, [question]);

  const [selected, setSelected] = useState([]); // 元の番号配列
  const [revealed, setRevealed] = useState(false);

  const isMulti = (question.answer || []).length > 1
    || /\d\s*つ選/.test(question.question_text)
    || /複数/.test(question.question_text);

  // 必要な解答数（answer配列の長さで判定）
  const requiredCount = (question.answer || []).length;

  const toggleChoice = (n) => {
    if (revealed) return;
    setSelected((prev) => {
      let next;
      if (isMulti) {
        next = prev.includes(n) ? prev.filter((x) => x !== n) : [...prev, n];
      } else {
        next = [n];
      }
      // 必要数に達したら即座に答え合わせ
      if (next.length >= requiredCount) {
        const correct = arrEq(next, question.answer);
        setRevealed(true);
        onResult(question, correct ? "correct" : "wrong");
      }
      return next;
    });
  };

  const isCorrect = revealed && arrEq(selected, question.answer);

  return (
    <div className="screen quiz">
      <div className="quiz-top">
        <button className="back-btn" onClick={onQuit} aria-label="やめる">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
        </button>
        <div className="progress">
          <div className="progress-text">{index + 1} / {total}</div>
          <div className="progress-bar">
            <div className="progress-fill" style={{ width: `${((index + (revealed ? 1 : 0)) / total) * 100}%` }}/>
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-meta">
          <span className="meta-pill">{question.year}年</span>
          <span className="meta-sep">·</span>
          <span className="meta-text">{question.subject}</span>
          <span className="meta-sep">·</span>
          <span className="meta-text">第{question.question_number}問</span>
        </div>
        <h2 className="question-text">{question.question_text}</h2>
        {isMulti && !revealed && (
          <p className="multi-hint">{requiredCount}つ選んでください（{selected.length}/{requiredCount}）</p>
        )}

        <div className="choices">
          {shuffled.map((n) => {
            const isSel = selected.includes(n);
            const isAns = (question.answer || []).includes(n);
            let cls = "choice";
            if (revealed) {
              if (isAns) cls += " is-correct";
              else if (isSel) cls += " is-wrong";
              else cls += " is-dim";
            } else if (isSel) cls += " is-selected";
            return (
              <button
                key={n}
                className={cls}
                onClick={() => toggleChoice(n)}
                disabled={revealed}
              >
                <span className="choice-mark">
                  {revealed && isAns && (
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
                  )}
                  {revealed && !isAns && isSel && (
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
                  )}
                  {!revealed && isSel && (
                    <span className="dot"/>
                  )}
                </span>
                <span className="choice-text">{question.choices[n - 1]}</span>
              </button>
            );
          })}
        </div>

        {revealed && (
          <div className={`result-banner ${isCorrect ? "correct" : "wrong"}`}>
            <div className="result-label">
              {isCorrect ? "正解" : "不正解"}
            </div>
            <div className="result-answer">
              正解: {question.answer.map((n) => shuffled.indexOf(n) + 1).sort((a, b) => a - b).join(", ")}
            </div>
          </div>
        )}

        {revealed && (
          <div className="explanation">
            <h3>解説</h3>
            <p>{question.explanation}</p>
            {question.source_url && (
              <a className="source-link" href={question.source_url} target="_blank" rel="noopener noreferrer">
                出典を見る
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
              </a>
            )}
          </div>
        )}

        {revealed && (
          <button className="primary-btn full" onClick={onNext}>
            {index + 1 >= total ? "結果を見る" : "次の問題へ"}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        )}

        {!revealed && (
          <button
            className="pass-btn"
            onClick={onNext}
          >
            スキップ
          </button>
        )}
      </div>
    </div>
  );
}

// ---------- 結果画面 ----------
function ResultScreen({ log, queue, onRestart, onAgain }) {
  const correct = log.filter((l) => l.result === "correct").length;
  const total = log.length;
  const pct = total > 0 ? Math.round((correct / total) * 100) : 0;

  return (
    <div className="screen result">
      <div className="result-hero">
        <div className="circle">
          <svg viewBox="0 0 100 100" width="160" height="160">
            <circle cx="50" cy="50" r="44" fill="none" stroke="#EAE3D8" strokeWidth="8"/>
            <circle
              cx="50" cy="50" r="44" fill="none"
              stroke="var(--accent)" strokeWidth="8"
              strokeDasharray={`${pct * 2.764} 999`}
              strokeLinecap="round"
              transform="rotate(-90 50 50)"
            />
          </svg>
          <div className="circle-text">
            <div className="circle-num">{pct}<small>%</small></div>
            <div className="circle-sub">{correct} / {total}</div>
          </div>
        </div>
        <h2 className="result-title">
          {pct === 100 ? "全問正解！素晴らしい" :
           pct >= 70 ? "よくできました" :
           pct >= 40 ? "もう一歩、復習しよう" :
           "間違えた問題から学ぼう"}
        </h2>
      </div>

      <ul className="review-list">
        {log.map((l, i) => {
          const q = queue.find((item) => qid(item) === l.qid);
          if (!q) return null;
          return (
            <li key={i} className={`review-item ${l.result}`}>
              <span className={`review-mark ${l.result}`}>
                {l.result === "correct" ? "○" : "×"}
              </span>
              <div className="review-body">
                <div className="review-meta">{q.year} · {q.subject} · 第{q.question_number}問</div>
                <div className="review-text">{q.question_text}</div>
              </div>
            </li>
          );
        })}
      </ul>

      <div className="result-actions">
        <button className="secondary-btn" onClick={onRestart}>ホームへ</button>
        <button className="primary-btn" onClick={onAgain}>もう一度</button>
      </div>
    </div>
  );
}

// ---------- 統計画面 ----------
function StatsScreen({ all, history, onReset, onClose }) {
  const subjects = [...new Set(all.map((q) => q.subject))];

  // 科目別正答率
  const bySubject = subjects.map((s) => {
    const qs = all.filter((q) => q.subject === s);
    let attempts = 0, correct = 0, seen = 0;
    qs.forEach((q) => {
      const h = history[qid(q)];
      if (h) {
        attempts += h.attempts;
        correct += h.correct;
        seen += 1;
      }
    });
    return { subject: s, total: qs.length, seen, attempts, correct, rate: attempts ? Math.round(correct / attempts * 100) : null };
  });

  // 間違えた問題の履歴
  const wrongList = all
    .map((q) => ({ q, h: history[qid(q)] }))
    .filter((x) => x.h && x.h.lastResult === "wrong")
    .sort((a, b) => (b.h.lastAt || 0) - (a.h.lastAt || 0));

  const totalAttempts = Object.values(history).reduce((a, h) => a + h.attempts, 0);
  const totalCorrect = Object.values(history).reduce((a, h) => a + h.correct, 0);
  const overallRate = totalAttempts ? Math.round(totalCorrect / totalAttempts * 100) : 0;

  return (
    <div className="screen stats">
      <div className="stats-top">
        <button className="back-btn" onClick={onClose} aria-label="閉じる">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
        </button>
        <h2 className="stats-title">学習の記録</h2>
      </div>

      <section className="overall">
        <div className="overall-num">{overallRate}<small>%</small></div>
        <div className="overall-meta">通算正答率 · {totalCorrect}/{totalAttempts} 回</div>
      </section>

      <section className="block">
        <h3 className="block-title">科目別</h3>
        <ul className="subject-list">
          {bySubject.map((s) => (
            <li key={s.subject} className="subject-row">
              <div className="subject-head">
                <span className="subject-name">{s.subject}</span>
                <span className="subject-rate">
                  {s.rate === null ? "—" : `${s.rate}%`}
                </span>
              </div>
              <div className="subject-bar">
                <div className="subject-fill" style={{ width: `${s.rate || 0}%` }}/>
              </div>
              <div className="subject-meta">
                出題済 {s.seen}/{s.total} · 回答 {s.attempts}回
              </div>
            </li>
          ))}
        </ul>
      </section>

      <section className="block">
        <h3 className="block-title">最近間違えた問題 ({wrongList.length})</h3>
        {wrongList.length === 0 ? (
          <p className="empty">まだありません。</p>
        ) : (
          <ul className="wrong-list">
            {wrongList.slice(0, 30).map((x, i) => (
              <li key={i} className="wrong-item">
                <div className="wrong-meta">
                  {x.q.year} · {x.q.subject} · 第{x.q.question_number}問
                  <span className="wrong-rate">{x.h.correct}/{x.h.attempts}</span>
                </div>
                <div className="wrong-text">{x.q.question_text}</div>
              </li>
            ))}
          </ul>
        )}
      </section>

      <button className="reset-btn" onClick={onReset}>学習履歴をリセット</button>
    </div>
  );
}

// ---------- マウント ----------
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App/>);
