"use client";

/**
 * Grades 页面 - 成绩查询 + 录入 + 分析图表
 *
 * 数据来源（contract.md §2.4）：
 * - GraphQL ExamGradesQuery（P3 扩展，MSW mock）拉取成绩列表
 * - GraphQL RecordGradeMutation（P3 扩展，MSW mock）录入成绩
 * - 通过 URL ?examId=xxx 指定考试
 * - 成绩分析：平均分/最高分/最低分/及格率 + 纯 SVG 柱状图（不引入 recharts，P4 再迁移）
 *
 * 维护者：ai13（teacher-portal）
 */

import { useState, useMemo, useRef, Suspense } from "react";
import { useQuery, useMutation } from "urql";
import { useSearchParams } from "next/navigation";
import Link from "next/link";
import { Loading, Empty } from "@edu/ui-components";
import { ExamGradesQuery, RecordGradeMutation } from "@/lib/graphql";
import type { GradeItem } from "@/lib/graphql";
import { SaveGradeEntriesMutation } from "@/lib/graphql-p7-grades";
import type { SaveGradeEntryInput } from "@/lib/graphql-p7-grades";

/** 柱状图分段（成绩分布） */
interface ScoreBand {
  label: string;
  min: number;
  max: number;
  count: number;
}

/** 计算成绩统计 */
function computeStats(grades: GradeItem[]) {
  if (grades.length === 0) {
    return {
      average: 0,
      max: 0,
      min: 0,
      passRate: 0,
      bands: [] as ScoreBand[],
    };
  }
  const scores = grades.map((g) => g.score);
  const sum = scores.reduce((acc, s) => acc + s, 0);
  const average = sum / scores.length;
  const max = Math.max(...scores);
  const min = Math.min(...scores);
  const passCount = scores.filter((s) => s >= 60).length;
  const passRate = (passCount / scores.length) * 100;

  // 分段：0-59, 60-69, 70-79, 80-89, 90-100
  const bandDefs = [
    { label: "0-59", min: 0, max: 59 },
    { label: "60-69", min: 60, max: 69 },
    { label: "70-79", min: 70, max: 79 },
    { label: "80-89", min: 80, max: 89 },
    { label: "90-100", min: 90, max: 100 },
  ];
  const bands: ScoreBand[] = bandDefs.map((b) => ({
    ...b,
    count: scores.filter((s) => s >= b.min && s <= b.max).length,
  }));

  return { average, max, min, passRate, bands };
}

function GradesContent() {
  const searchParams = useSearchParams();
  const initialExamId = searchParams.get("examId") ?? "";
  const [examId, setExamId] = useState(initialExamId);

  const [gradesResult, reexecuteQuery] = useQuery({
    query: ExamGradesQuery,
    variables: { examId },
    pause: !examId,
  });

  const [recordResult, recordGrade] = useMutation(RecordGradeMutation);
  // P7：批量导入成绩 mutation
  const [, saveEntries] = useMutation(SaveGradeEntriesMutation);

  // 录入表单状态
  const [showForm, setShowForm] = useState(false);
  const [studentId, setStudentId] = useState("");
  const [score, setScore] = useState("");
  const [feedback, setFeedback] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);
  // P7：Excel 导入状态
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const [importMsg, setImportMsg] = useState<string | null>(null);

  const grades = (gradesResult.data?.examGrades ?? []) as GradeItem[];

  // 成绩统计（useMemo 避免重复计算）
  const stats = useMemo(() => computeStats(grades), [grades]);
  const maxBandCount = Math.max(1, ...stats.bands.map((b) => b.count));

  const handleRecordGrade = async (e: React.FormEvent) => {
    e.preventDefault();
    setFormError(null);

    if (!studentId.trim()) {
      setFormError("请填写学生 ID");
      return;
    }
    if (!examId) {
      setFormError("请先指定考试 ID");
      return;
    }
    const scoreNum = Number(score);
    if (Number.isNaN(scoreNum)) {
      setFormError("分数必须为数字");
      return;
    }

    setSubmitting(true);
    // 乐观更新：本地表单先清空，失败后保留输入由错误提示
    const res = await recordGrade({
      input: {
        studentId: studentId.trim(),
        examId,
        score: scoreNum,
        feedback: feedback.trim() || null,
      },
    });
    setSubmitting(false);

    if (res.error) {
      setFormError(res.error.message);
      return;
    }
    // 成功后刷新成绩列表
    reexecuteQuery({ requestPolicy: "network-only" });
    setStudentId("");
    setScore("");
    setFeedback("");
    setShowForm(false);
  };

  // P7：Excel 导入处理（解析 CSV/文本为 entries，调用 SaveGradeEntriesMutation）
  const handleExcelImport = async (
    e: React.ChangeEvent<HTMLInputElement>,
  ) => {
    const file = e.target.files?.[0];
    if (!file || !examId) {
      setImportMsg(examId ? "请选择文件" : "请先指定考试 ID");
      return;
    }
    setImportMsg(null);
    try {
      const text = await file.text();
      const lines = text.split(/\r?\n/).filter((l) => l.trim());
      const entries: SaveGradeEntryInput[] = [];
      for (const line of lines) {
        const parts = line.split(/[,\t]/).map((p) => p.trim());
        const sid = parts[0];
        const sc = parts[1];
        if (!sid || !sc) continue;
        const scoreNum = Number(sc);
        if (Number.isNaN(scoreNum)) continue;
        entries.push({ studentId: sid, score: scoreNum });
      }
      if (entries.length === 0) {
        setImportMsg("未解析到有效数据（格式：学号,分数）");
        return;
      }
      const res = await saveEntries({
        input: { examId, classId: examId, entries },
      });
      if (res.error) {
        setImportMsg(`导入失败：${res.error.message}`);
        return;
      }
      setImportMsg(`已导入 ${entries.length} 条成绩`);
      reexecuteQuery({ requestPolicy: "network-only" });
    } catch {
      setImportMsg("文件读取失败");
    }
    // 清空 file input 以便重复选择同一文件
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  };

  // P7：导出当前成绩列表为 CSV
  const handleExportCsv = () => {
    if (grades.length === 0) return;
    const header = "学生ID,学生姓名,分数,反馈\n";
    const rows = grades
      .map(
        (g) =>
          `${g.studentId},${g.studentName},${g.score},${g.feedback ?? ""}`,
      )
      .join("\n");
    const csv = "\uFEFF" + header + rows;
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `成绩_${examId}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div className="px-10 py-10">
      <header className="mb-8 flex items-baseline justify-between">
        <div>
          <h1 className="text-3xl font-serif text-ink">成绩查询</h1>
          <p className="mt-1 text-sm text-ink-muted">
            GraphQL ExamGradesQuery + RecordGradeMutation · core-edu 域（P3 扩展，MSW mock）
          </p>
        </div>
        <div className="flex items-center gap-3">
          <button
            type="button"
            onClick={handleExportCsv}
            disabled={grades.length === 0}
            className="px-3 py-2 text-sm text-ink border border-rule rounded-button hover:bg-subtle disabled:opacity-50"
          >
            导出 CSV
          </button>
          <button
            type="button"
            onClick={() => fileInputRef.current?.click()}
            disabled={!examId}
            className="px-3 py-2 text-sm text-ink border border-rule rounded-button hover:bg-subtle disabled:opacity-50"
          >
            Excel 导入
          </button>
          <input
            ref={fileInputRef}
            type="file"
            accept=".xlsx,.csv"
            onChange={handleExcelImport}
            className="hidden"
          />
          {examId && (
            <button
              type="button"
              onClick={() => setShowForm((v) => !v)}
              className="px-4 py-2 text-sm text-ink-on-accent bg-accent rounded-button hover:bg-accent-hover"
            >
              {showForm ? "收起录入" : "录入成绩"}
            </button>
          )}
        </div>
      </header>

      {/* P7：子模块导航 */}
      <nav className="mb-6 flex items-center gap-4">
        <Link
          href="/grades/entry"
          className="text-sm text-accent hover:opacity-70"
        >
          → 录入成绩
        </Link>
        <Link
          href="/grades/stats"
          className="text-sm text-accent hover:opacity-70"
        >
          → 统计
        </Link>
        <Link
          href="/grades/analytics"
          className="text-sm text-accent hover:opacity-70"
        >
          → 分析
        </Link>
        <Link
          href="/grades/report-card"
          className="text-sm text-accent hover:opacity-70"
        >
          → 报告卡
        </Link>
      </nav>

      {importMsg && (
        <p className="mb-4 text-tiny text-ink-muted">{importMsg}</p>
      )}

      <div className="rule-thin mb-8" />

      <div className="mb-6 flex items-baseline gap-3">
        <label className="text-tiny uppercase tracking-wide text-ink-muted">
          考试 ID
        </label>
        <input
          type="text"
          value={examId}
          onChange={(e) => setExamId(e.target.value)}
          className="flex-1 max-w-md px-3 py-2 bg-transparent border-b border-rule text-sm font-mono"
          placeholder="输入考试 UUID"
        />
      </div>

      {/* 录入表单 */}
      {showForm && examId && (
        <section className="mb-8 p-4 border border-rule rounded-card bg-subtle">
          <h2 className="text-base font-serif text-ink mb-3">录入成绩</h2>
          <form onSubmit={handleRecordGrade} className="grid grid-cols-3 gap-4">
            <div>
              <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                学生 ID <span className="text-danger">*</span>
              </label>
              <input
                type="text"
                value={studentId}
                onChange={(e) => setStudentId(e.target.value)}
                className="w-full px-3 py-2 bg-paper border border-rule rounded-button text-sm text-ink focus:outline-none"
                placeholder="学生 UUID"
                required
              />
            </div>
            <div>
              <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                分数 <span className="text-danger">*</span>
              </label>
              <input
                type="number"
                min={0}
                max={100}
                value={score}
                onChange={(e) => setScore(e.target.value)}
                className="w-full px-3 py-2 bg-paper border border-rule rounded-button text-sm text-ink focus:outline-none"
                placeholder="0-100"
                required
              />
            </div>
            <div>
              <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
                反馈
              </label>
              <input
                type="text"
                value={feedback}
                onChange={(e) => setFeedback(e.target.value)}
                className="w-full px-3 py-2 bg-paper border border-rule rounded-button text-sm text-ink focus:outline-none"
                placeholder="可选：批改意见"
              />
            </div>
            <div className="col-span-3 flex items-center gap-3">
              <button
                type="submit"
                disabled={submitting}
                className="px-4 py-2 text-sm text-ink-on-accent bg-accent rounded-button hover:bg-accent-hover disabled:opacity-50"
              >
                {submitting ? "录入中..." : "保存成绩"}
              </button>
              <button
                type="button"
                onClick={() => setShowForm(false)}
                className="text-tiny uppercase tracking-wide text-ink-muted hover:opacity-70"
              >
                取消
              </button>
              {formError && (
                <span className="text-tiny text-danger">{formError}</span>
              )}
              {recordResult.data && !formError && !submitting && (
                <span className="text-tiny text-success">已保存</span>
              )}
            </div>
          </form>
        </section>
      )}

      {gradesResult.fetching ? (
        <Loading lines={4} />
      ) : gradesResult.error ? (
        <div className="mark-left mb-4 py-2 border-l-2 border-danger pl-md">
          <p className="text-sm px-3 text-danger">
            加载失败：{gradesResult.error.message}
          </p>
        </div>
      ) : !examId ? (
        <Empty title="请输入考试 ID" description="输入考试 UUID 后查询成绩" />
      ) : grades.length === 0 ? (
        <Empty title="暂无成绩" description="该考试尚未录入成绩" />
      ) : (
        <>
          {/* 成绩分析 */}
          <section className="mb-8">
            <h2 className="text-xl font-serif text-ink mb-2">成绩分析</h2>
            <div className="rule-thin mb-4" />
            <dl className="grid grid-cols-4 gap-4 mb-6">
              <div className="p-3 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  平均分
                </dt>
                <dd className="mt-1 text-2xl font-serif text-accent">
                  {stats.average.toFixed(1)}
                </dd>
              </div>
              <div className="p-3 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  最高分
                </dt>
                <dd className="mt-1 text-2xl font-serif text-success">
                  {stats.max}
                </dd>
              </div>
              <div className="p-3 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  最低分
                </dt>
                <dd className="mt-1 text-2xl font-serif text-danger">
                  {stats.min}
                </dd>
              </div>
              <div className="p-3 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  及格率
                </dt>
                <dd className="mt-1 text-2xl font-serif text-ink">
                  {stats.passRate.toFixed(1)}%
                </dd>
              </div>
            </dl>

            {/* 柱状图（纯 SVG，无外部依赖） */}
            <div className="p-4 border border-rule rounded-card bg-surface">
              <h3 className="text-sm font-serif text-ink mb-4">分数段分布</h3>
              <div className="flex items-end gap-4 h-40">
                {stats.bands.map((band) => {
                  const heightPct = (band.count / maxBandCount) * 100;
                  return (
                    <div
                      key={band.label}
                      className="flex-1 flex flex-col items-center"
                    >
                      <div className="w-full flex flex-col items-center justify-end h-32">
                        <span className="text-tiny text-ink-muted mb-1">
                          {band.count}
                        </span>
                        <div
                          className="w-full bg-accent rounded-t-button"
                          style={{ height: `${heightPct}%`, minHeight: band.count > 0 ? "4px" : "0" }}
                          aria-label={`${band.label} 段 ${band.count} 人`}
                        />
                      </div>
                      <span className="mt-2 text-tiny font-mono text-ink-muted">
                        {band.label}
                      </span>
                    </div>
                  );
                })}
              </div>
            </div>
          </section>

          {/* 成绩列表 */}
          <section>
            <h2 className="text-xl font-serif text-ink mb-2">成绩列表</h2>
            <div className="rule-thin mb-4" />
            <ul className="space-y-0">
              {grades.map((g) => (
                <li
                  key={g.id}
                  className="py-4 grid grid-cols-12 gap-4 items-baseline border-b border-rule"
                >
                  <div className="col-span-6">
                    <h3 className="text-lg font-serif text-ink">
                      {g.studentName}
                    </h3>
                    <p className="mt-1 text-tiny text-ink-muted">
                      学生 ID: {g.studentId}
                    </p>
                    {g.feedback && (
                      <p className="mt-1 text-sm text-ink-muted">
                        反馈: {g.feedback}
                      </p>
                    )}
                  </div>
                  <div className="col-span-2 text-2xl font-serif text-accent">
                    {g.score}
                  </div>
                  <div className="col-span-2 text-tiny text-ink-muted">
                    {g.examId ? `考试: ${g.examId.slice(0, 8)}...` : "作业成绩"}
                  </div>
                  <div className="col-span-2 text-right">
                    <button
                      type="button"
                      onClick={handleExportCsv}
                      className="text-tiny uppercase tracking-wide text-accent hover:opacity-70"
                    >
                      导出 CSV
                    </button>
                    <p className="mt-1 text-tiny font-mono text-ink-muted">
                      {g.id.slice(0, 8)}...
                    </p>
                  </div>
                </li>
              ))}
            </ul>
          </section>
        </>
      )}
    </div>
  );
}

export default function GradesPage() {
  return (
    <Suspense
      fallback={
        <div className="px-10 py-10">
          <Loading lines={3} />
        </div>
      }
    >
      <GradesContent />
    </Suspense>
  );
}
