import { useEffect, useState } from "react";
import { apiGet, apiPut, apiDelete } from "../../lib/api";

type Tab = "overview" | "teachers" | "sessions" | "students";

interface Stats {
  teachers: number;
  students: number;
  quizzes: number;
  reports: number;
  student_results: number;
  prompts: number;
  schema_version: string | null;
}

interface TeacherRow {
  id: number;
  email: string;
  full_name: string;
  school: string;
  is_admin: boolean;
  created_at: string;
  quiz_count: number;
  student_count: number;
}

interface SessionRow {
  id: number;
  title: string;
  subject: string | null;
  status: string;
  teacher_email: string;
  report_count: number;
  created_at: string;
}

interface StudentRow {
  id: number;
  name: string;
  teacher_email: string;
  result_count: number;
  avg_score: number | null;
}

interface TimelineEntry {
  quiz_id: number;
  quiz_title: string;
  quiz_subject: string | null;
  quiz_created_at: string;
  total_questions: number;
  correct_count: number;
  score: number;
  answers: { answers?: (string | null)[] };
}

interface QuestionMeta {
  number: number;
  text: string;
  options: string[];
}

interface RawFile {
  id: number;
  data_type: string;
  file_name: string;
  content_type: string;
  size_bytes: number;
  storage_path: string;
  download_url: string | null;
}

interface QuizResult {
  student_id: number;
  student_name: string;
  total_questions: number;
  correct_count: number;
  score: number;
  answers: { answers?: (string | null)[] };
}

interface QuizDetailData {
  quiz: { id: number; title: string; subject: string | null; status: string; created_at: string };
  raw_files: RawFile[];
  parsed_data: {
    questions?: { questions: QuestionMeta[] };
    student_answers?: { students: { name: string; id?: string; answers: { question_number: number; answer: string }[] }[] };
    teacher_answers?: { answers: { question_number: number; correct_answer: string; explanation?: string | null }[] };
    answer_grid?: { total_questions: number; official_answers: (string | null)[]; students: { name: string; answers: (string | null)[] }[]; questions: QuestionMeta[] };
  };
  results: QuizResult[];
}

const TABS: { key: Tab; label: string }[] = [
  { key: "overview", label: "總覽" },
  { key: "teachers", label: "教師" },
  { key: "sessions", label: "測驗" },
  { key: "students", label: "學生" },
];

export function AdminDashboard() {
  const [tab, setTab] = useState<Tab>("overview");

  return (
    <main className="max-w-6xl mx-auto px-4 pb-12">
      <div className="text-center mb-6">
        <h2 className="font-display text-2xl font-bold text-[var(--color-text)]">管理後台</h2>
        <p className="text-[var(--color-text-muted)] mt-1">資料庫管理與使用分析</p>
      </div>

      <div className="flex justify-center gap-2 mb-6">
        {TABS.map((t) => (
          <button
            key={t.key}
            onClick={() => setTab(t.key)}
            className={`px-4 py-2 text-sm font-medium rounded-lg transition-colors ${
              tab === t.key
                ? "bg-[var(--color-primary)] text-white"
                : "text-[var(--color-text-muted)] hover:text-[var(--color-text)] border border-[var(--color-border)]"
            }`}
          >
            {t.label}
          </button>
        ))}
      </div>

      {tab === "overview" && <Overview />}
      {tab === "teachers" && <Teachers />}
      {tab === "sessions" && <Sessions />}
      {tab === "students" && <Students />}
    </main>
  );
}

function useFetch<T>(path: string, deps: unknown[] = []) {
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(true);
  const [nonce, setNonce] = useState(0);
  const reload = () => setNonce((n) => n + 1);

  useEffect(() => {
    let active = true;
    setLoading(true);
    apiGet<T>(path)
      .then((d) => active && setData(d))
      .catch((e) => active && setError(e instanceof Error ? e.message : "Error"))
      .finally(() => active && setLoading(false));
    return () => {
      active = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [path, nonce, ...deps]);

  return { data, error, loading, reload };
}

function StatCard({ label, value }: { label: string; value: number | string }) {
  return (
    <div className="card p-6 text-center">
      <div className="text-3xl font-bold text-[var(--color-primary)]">{value}</div>
      <div className="text-sm text-[var(--color-text-muted)] mt-1">{label}</div>
    </div>
  );
}

function Overview() {
  const { data, loading, error } = useFetch<Stats>("/api/admin/stats");
  if (loading) return <Spinner />;
  if (error || !data) return <ErrorBox msg={error} />;
  return (
    <div>
      <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
        <StatCard label="教師" value={data.teachers} />
        <StatCard label="學生" value={data.students} />
        <StatCard label="測驗" value={data.quizzes} />
        <StatCard label="已生成報告" value={data.reports} />
        <StatCard label="學生成績紀錄" value={data.student_results} />
        <StatCard label="提示詞" value={data.prompts} />
      </div>
      <p className="text-center text-xs text-[var(--color-text-muted)] mt-6">
        資料庫結構版本：{data.schema_version ?? "未知"}
      </p>
    </div>
  );
}

function Teachers() {
  const { data, loading, error, reload } = useFetch<{ users: TeacherRow[] }>("/api/admin/users");
  if (loading) return <Spinner />;
  if (error || !data) return <ErrorBox msg={error} />;

  const toggleAdmin = async (u: TeacherRow) => {
    await apiPut(`/api/admin/users/${u.id}/admin`, { is_admin: !u.is_admin });
    reload();
  };
  const remove = async (u: TeacherRow) => {
    if (!confirm(`刪除教師 ${u.email}？此操作會一併刪除其所有測驗與報告。`)) return;
    await apiDelete(`/api/admin/users/${u.id}`);
    reload();
  };

  return (
    <Table headers={["Email", "姓名", "學校", "測驗", "學生", "管理員", ""]}>
      {data.users.map((u) => (
        <tr key={u.id} className="border-t border-[var(--color-border)]">
          <Td>{u.email}</Td>
          <Td>{u.full_name || "—"}</Td>
          <Td>{u.school || "—"}</Td>
          <Td>{u.quiz_count}</Td>
          <Td>{u.student_count}</Td>
          <Td>
            <button onClick={() => toggleAdmin(u)} className="text-sm underline text-[var(--color-primary)]">
              {u.is_admin ? "是" : "否"}
            </button>
          </Td>
          <Td>
            <button onClick={() => remove(u)} className="text-sm text-red-400 hover:underline">
              刪除
            </button>
          </Td>
        </tr>
      ))}
    </Table>
  );
}

function Sessions() {
  const { data, loading, error, reload } = useFetch<{ sessions: SessionRow[] }>("/api/admin/sessions");
  const [detailId, setDetailId] = useState<number | null>(null);

  if (detailId !== null) {
    return <QuizDetail quizId={detailId} onBack={() => setDetailId(null)} />;
  }
  if (loading) return <Spinner />;
  if (error || !data) return <ErrorBox msg={error} />;

  const remove = async (s: SessionRow) => {
    if (!confirm(`刪除測驗「${s.title}」？`)) return;
    await apiDelete(`/api/admin/sessions/${s.id}`);
    reload();
  };

  return (
    <Table headers={["標題", "科目", "教師", "狀態", "報告", "建立時間", ""]}>
      {data.sessions.map((s) => (
        <tr key={s.id} className="border-t border-[var(--color-border)]">
          <Td>{s.title}</Td>
          <Td>{s.subject || "—"}</Td>
          <Td>{s.teacher_email}</Td>
          <Td>{s.status}</Td>
          <Td>{s.report_count}</Td>
          <Td>{new Date(s.created_at).toLocaleDateString()}</Td>
          <Td>
            <div className="flex gap-3">
              <button onClick={() => setDetailId(s.id)} className="text-sm underline text-[var(--color-primary)]">
                查看詳情
              </button>
              <button onClick={() => remove(s)} className="text-sm text-red-400 hover:underline">
                刪除
              </button>
            </div>
          </Td>
        </tr>
      ))}
    </Table>
  );
}

function Students() {
  const { data, loading, error } = useFetch<{ students: StudentRow[] }>("/api/admin/students");
  const [selected, setSelected] = useState<number | null>(null);

  if (selected !== null) {
    return <StudentDetail studentId={selected} onBack={() => setSelected(null)} />;
  }
  if (loading) return <Spinner />;
  if (error || !data) return <ErrorBox msg={error} />;

  return (
    <Table headers={["姓名", "教師", "測驗次數", "平均分數", ""]}>
      {data.students.map((s) => (
        <tr key={s.id} className="border-t border-[var(--color-border)]">
          <Td>{s.name}</Td>
          <Td>{s.teacher_email}</Td>
          <Td>{s.result_count}</Td>
          <Td>{s.avg_score ?? "—"}</Td>
          <Td>
            <button onClick={() => setSelected(s.id)} className="text-sm underline text-[var(--color-primary)]">
              查看歷程
            </button>
          </Td>
        </tr>
      ))}
    </Table>
  );
}

function StudentDetail({ studentId, onBack }: { studentId: number; onBack: () => void }) {
  const { data, loading, error } = useFetch<{
    student: { name: string };
    timeline: TimelineEntry[];
  }>(`/api/admin/students/${studentId}`);
  const [quizId, setQuizId] = useState<number | null>(null);
  const [openRow, setOpenRow] = useState<number | null>(null);

  if (quizId !== null) {
    return <QuizDetail quizId={quizId} onBack={() => setQuizId(null)} />;
  }
  if (loading) return <Spinner />;
  if (error || !data) return <ErrorBox msg={error} />;

  return (
    <div>
      <button onClick={onBack} className="text-sm text-[var(--color-text-muted)] hover:underline mb-4">
        ← 返回學生列表
      </button>
      <h3 className="font-display text-xl font-semibold mb-4 text-[var(--color-text)]">
        {data.student.name} 的跨測驗歷程
      </h3>
      {data.timeline.length === 0 ? (
        <p className="text-[var(--color-text-muted)]">尚無成績紀錄</p>
      ) : (
        <div className="space-y-3">
          {data.timeline.map((t, i) => (
            <div key={i} className="card p-4">
              <div className="flex flex-wrap items-center justify-between gap-2">
                <div>
                  <span className="font-semibold text-[var(--color-text)]">{t.quiz_title}</span>
                  <span className="text-sm text-[var(--color-text-muted)] ml-2">
                    {t.quiz_subject || "—"} · {new Date(t.quiz_created_at).toLocaleDateString()}
                  </span>
                </div>
                <div className="flex items-center gap-4 text-sm">
                  <span>
                    {t.correct_count}/{t.total_questions} 答對 ·{" "}
                    <span className="font-semibold text-[var(--color-primary)]">{t.score} 分</span>
                  </span>
                  <button
                    onClick={() => setOpenRow(openRow === i ? null : i)}
                    className="underline text-[var(--color-primary)]"
                  >
                    {openRow === i ? "收合作答" : "查看作答"}
                  </button>
                  <button onClick={() => setQuizId(t.quiz_id)} className="underline text-[var(--color-primary)]">
                    測驗詳情
                  </button>
                </div>
              </div>
              {openRow === i && (
                <div className="mt-3 border-t border-[var(--color-border)] pt-3">
                  <p className="text-xs text-[var(--color-text-muted)] mb-2">
                    原始作答資料（= 代表答對；字母為作答選項；空白為未作答）
                  </p>
                  <AnswerChips answers={t.answers?.answers ?? []} />
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function QuizDetail({ quizId, onBack }: { quizId: number; onBack: () => void }) {
  const { data, loading, error } = useFetch<QuizDetailData>(`/api/admin/sessions/${quizId}`);
  const [view, setView] = useState<"questions" | "answers" | "raw">("questions");

  if (loading) return <Spinner />;
  if (error || !data) return <ErrorBox msg={error} />;

  const questions = data.parsed_data.questions?.questions ?? [];
  const grid = data.parsed_data.answer_grid;
  const teacher = data.parsed_data.teacher_answers?.answers ?? [];

  const subTabs: { key: typeof view; label: string }[] = [
    { key: "questions", label: `題目結構資料 (${questions.length})` },
    { key: "answers", label: `作答結構資料 (${data.results.length})` },
    { key: "raw", label: `原始檔案 (${data.raw_files.length})` },
  ];

  return (
    <div>
      <button onClick={onBack} className="text-sm text-[var(--color-text-muted)] hover:underline mb-4">
        ← 返回
      </button>
      <h3 className="font-display text-xl font-semibold mb-1 text-[var(--color-text)]">
        測驗詳情：{data.quiz.title}
      </h3>
      <p className="text-sm text-[var(--color-text-muted)] mb-4">
        {data.quiz.subject || "—"} · 狀態 {data.quiz.status} ·{" "}
        {new Date(data.quiz.created_at).toLocaleString()}
      </p>

      <div className="flex gap-2 mb-4">
        {subTabs.map((t) => (
          <button
            key={t.key}
            onClick={() => setView(t.key)}
            className={`px-3 py-1.5 text-sm rounded-lg transition-colors ${
              view === t.key
                ? "bg-[var(--color-primary)] text-white"
                : "text-[var(--color-text-muted)] border border-[var(--color-border)]"
            }`}
          >
            {t.label}
          </button>
        ))}
      </div>

      {view === "questions" && (
        questions.length === 0 ? (
          <Empty msg="尚無題目結構資料" />
        ) : (
          <div className="space-y-2">
            {questions.map((q, i) => {
              // Prefer the number-keyed teacher answer (gap-tolerant); fall back to the
              // positional grid cell. '=' means "no authoritative key" → don't show it.
              const rawOfficial =
                teacher.find((a) => a.question_number === q.number)?.correct_answer ??
                grid?.official_answers?.[q.number - 1] ??
                null;
              const official = rawOfficial === "=" ? null : rawOfficial;
              return (
                <div key={`${q.number}-${i}`} className="card p-3">
                  <div className="flex items-start gap-2">
                    <span className="font-semibold text-[var(--color-primary)] shrink-0">Q{q.number}</span>
                    <div className="min-w-0">
                      <p className="text-sm text-[var(--color-text)] whitespace-pre-wrap break-words">{q.text || "（無題目文字）"}</p>
                      {q.options?.length > 0 && (
                        <ul className="mt-1 text-sm text-[var(--color-text-muted)] list-disc ml-5">
                          {q.options.map((o, j) => <li key={j}>{o}</li>)}
                        </ul>
                      )}
                      {official && (
                        <p className="mt-1 text-sm">
                          正解：<span className="font-semibold text-[var(--color-success)]">{official}</span>
                        </p>
                      )}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )
      )}

      {view === "answers" && (
        <div className="space-y-4">
          {grid?.official_answers && (
            <div className="card p-3">
              <p className="text-xs text-[var(--color-text-muted)] mb-2">標準答案</p>
              <AnswerChips answers={grid.official_answers} hideEquals />
            </div>
          )}
          {data.results.length === 0 ? (
            <Empty msg="尚無學生作答結構資料" />
          ) : (
            data.results.map((r) => (
              <div key={r.student_id} className="card p-3">
                <div className="flex items-center justify-between mb-2">
                  <span className="font-semibold text-[var(--color-text)]">{r.student_name}</span>
                  <span className="text-sm">
                    {r.correct_count}/{r.total_questions} ·{" "}
                    <span className="font-semibold text-[var(--color-primary)]">{r.score} 分</span>
                  </span>
                </div>
                <AnswerChips answers={r.answers?.answers ?? []} />
              </div>
            ))
          )}
        </div>
      )}

      {view === "raw" && (
        data.raw_files.length === 0 ? (
          <Empty msg="此測驗沒有原始檔案（PDF/CSV）。較早上傳的資料未保存原始檔；之後上傳的會自動保存到 Supabase Storage。" />
        ) : (
          <Table headers={["類型", "檔名", "格式", "大小", "下載"]}>
            {data.raw_files.map((f) => (
              <tr key={f.id} className="border-t border-[var(--color-border)]">
                <Td>{f.data_type}</Td>
                <Td>{f.file_name}</Td>
                <Td>{f.content_type || "—"}</Td>
                <Td>{f.size_bytes ? `${(f.size_bytes / 1024).toFixed(1)} KB` : "—"}</Td>
                <Td>
                  {f.download_url ? (
                    <a href={f.download_url} target="_blank" rel="noreferrer" className="underline text-[var(--color-primary)]">
                      下載 / 檢視
                    </a>
                  ) : (
                    <span className="text-[var(--color-text-muted)]">不可用</span>
                  )}
                </Td>
              </tr>
            ))}
          </Table>
        )
      )}
    </div>
  );
}

function AnswerChips({ answers, hideEquals }: { answers: (string | null)[]; hideEquals?: boolean }) {
  return (
    <div className="flex flex-wrap gap-1.5">
      {answers.map((a, i) => {
        const isEq = a === "=";
        const blank = a === null || a === "";
        // '=' means "answered correctly" in a student row (show ✓), but "no
        // authoritative key" in the official-answer row (hideEquals → neutral).
        const showCorrect = isEq && !hideEquals;
        const neutral = blank || (isEq && hideEquals);
        const label = neutral ? "·" : showCorrect ? "✓" : a;
        return (
          <span
            key={i}
            title={`Q${i + 1}`}
            className={`inline-flex items-center justify-center min-w-[2.2rem] px-1.5 py-0.5 rounded text-xs border ${
              showCorrect
                ? "bg-[var(--color-success)]/10 border-[var(--color-success)]/30 text-[var(--color-success)]"
                : neutral
                ? "border-[var(--color-border)] text-[var(--color-text-muted)]"
                : "border-[var(--color-border)] text-[var(--color-text)]"
            }`}
          >
            <span className="opacity-50 mr-0.5">{i + 1}</span>
            {label}
          </span>
        );
      })}
    </div>
  );
}

function Empty({ msg }: { msg: string }) {
  return <div className="card p-6 text-center text-[var(--color-text-muted)] text-sm">{msg}</div>;
}

function Table({ headers, children }: { headers: string[]; children: React.ReactNode }) {
  return (
    <div className="card overflow-x-auto">
      <table className="w-full text-sm">
        <thead>
          <tr className="text-left text-[var(--color-text-muted)]">
            {headers.map((h, i) => (
              <th key={i} className="px-4 py-3 font-medium">
                {h}
              </th>
            ))}
          </tr>
        </thead>
        <tbody className="text-[var(--color-text)]">{children}</tbody>
      </table>
    </div>
  );
}

function Td({ children }: { children: React.ReactNode }) {
  return <td className="px-4 py-3">{children}</td>;
}

function Spinner() {
  return (
    <div className="flex justify-center py-12">
      <div className="w-6 h-6 border-2 border-[var(--color-primary)] border-t-transparent rounded-full animate-spin" />
    </div>
  );
}

function ErrorBox({ msg }: { msg: string }) {
  return <div className="card p-6 text-center text-red-400">{msg || "載入失敗"}</div>;
}
