import { Fragment, useEffect, useState, type ReactNode } from "react";
import { adminEvals, type EvalDay, type EvalSummary, type PoorEval } from "../api";

// 自动评测观测：真数据(来自 sundynix_eval，评测经 JetStream eval 流持久落库)。
// 质量趋势 + 计数总览 + 错题本(低分评测 + 评语 + 纠偏标记)。
// 注：纠偏前后全文轨迹后端未持久化，错题本展示评语(Reason)与「已纠偏」标记，不含 before/after 对照。
const pct = (v: number) => `${Math.round(v * 100)}%`;
const LEVEL_BADGE: Record<string, string> = { poor: "bg-rose-50 text-rose-600", warn: "bg-amber-50 text-amber-600", ok: "bg-emerald-50 text-emerald-600" };
const LEVEL_LABEL: Record<string, string> = { poor: "低分", warn: "警告", ok: "合格" };
const mmdd = (ymd: string) => (ymd.length === 8 ? `${ymd.slice(4, 6)}-${ymd.slice(6, 8)}` : ymd);

export function EvalsPage() {
  const [days, setDays] = useState(14);
  const [trend, setTrend] = useState<EvalDay[]>([]);
  const [summary, setSummary] = useState<EvalSummary | null>(null);
  const [poor, setPoor] = useState<PoorEval[]>([]);
  const [open, setOpen] = useState<string | null>(null); // 展开评语的 task_id
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState("");

  useEffect(() => {
    setLoading(true);
    adminEvals(days)
      .then((r) => {
        setTrend(r.trend);
        setSummary(r.summary);
        setPoor(r.poor);
        setErr("");
      })
      .catch((e) => setErr((e as Error).message))
      .finally(() => setLoading(false));
  }, [days]);

  if (loading) return <div className="text-sm text-gray-400">加载评测数据中…</div>;
  if (err) return <div className="text-sm text-rose-500">评测加载失败：{err}</div>;

  const s = summary!;
  const correctRate = s.poor + s.warn > 0 ? s.corrected / (s.poor + s.warn) : 0;

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div>
          <h2 className="text-base font-semibold text-gray-800">自动评测</h2>
          <p className="text-xs text-gray-400">质量趋势 · 忠实度 · 低分错题本与纠偏成效（全平台真实评测）</p>
        </div>
        <div className="flex overflow-hidden rounded-lg border border-gray-200 text-xs">
          {[7, 14, 30].map((d) => (
            <button key={d} onClick={() => setDays(d)}
              className={`px-3 py-1.5 ${days === d ? "bg-violet-600 text-white" : "bg-white text-gray-500 hover:bg-gray-50"}`}>
              近 {d} 天
            </button>
          ))}
        </div>
      </div>

      {/* 总览计数 */}
      <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
        <Stat label="综合质量分" value={pct(s.avg_overall)} tone="violet" sub={`${s.total} 次评测`} />
        <Stat label="合格率" value={s.total ? pct(s.ok / s.total) : "—"} tone="emerald" sub={`${s.ok} 合格 · ${s.warn} 警告 · ${s.poor} 低分`} />
        <Stat label="低分占比" value={s.total ? pct(s.poor / s.total) : "—"} tone="rose" sub="幻觉/规则违背/低质" />
        <Stat label="纠偏采纳率" value={s.poor + s.warn ? pct(correctRate) : "—"} tone="cyan" sub={`${s.corrected} 次自动纠偏被采纳`} />
      </div>

      {/* 质量 & 忠实度趋势 */}
      <div className="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
        <div className="mb-4 flex items-center justify-between">
          <h4 className="text-sm font-semibold text-gray-700">质量与忠实度趋势</h4>
          <div className="flex gap-4 text-[11px]">
            <span className="flex items-center gap-1"><span className="h-2 w-2 rounded-full bg-violet-500" />综合分</span>
            <span className="flex items-center gap-1"><span className="h-2 w-2 rounded-full bg-cyan-500" />忠实度</span>
            <span className="flex items-center gap-1"><span className="h-2 w-2 rounded-full bg-rose-300" />低分数</span>
          </div>
        </div>
        <TrendChart trend={trend} />
      </div>

      {/* 错题本 */}
      <div className="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
        <div className="mb-3 flex items-center justify-between">
          <h4 className="text-sm font-semibold text-gray-700">错题本（低分/警告评测）</h4>
          <span className="text-[11px] text-gray-400">点行展开评语；「已纠偏」= 自动重生成后采纳</span>
        </div>
        {poor.length === 0 ? (
          <div className="py-8 text-center text-xs text-gray-400">区间内没有低分评测 —— 质量良好</div>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-gray-100 text-left text-[11px] uppercase tracking-wide text-gray-400">
                  <th className="py-2 pr-3 font-medium">时间</th>
                  <th className="py-2 pr-3 font-medium">任务 / 租户</th>
                  <th className="py-2 pr-3 text-right font-medium">综合</th>
                  <th className="py-2 pr-3 text-right font-medium">规则</th>
                  <th className="py-2 pr-3 text-right font-medium">质量</th>
                  <th className="py-2 pr-3 text-right font-medium">忠实</th>
                  <th className="py-2 font-medium">等级</th>
                </tr>
              </thead>
              <tbody>
                {poor.map((r) => (
                  <Fragment key={r.task_id}>
                    <tr onClick={() => setOpen(open === r.task_id ? null : r.task_id)}
                      className="cursor-pointer border-b border-gray-50 hover:bg-gray-50">
                      <td className="py-2 pr-3 text-xs text-gray-500">{r.created_at}</td>
                      <td className="py-2 pr-3">
                        <div className="font-mono text-[11px] text-gray-600">{r.task_id}</div>
                        <div className="text-[11px] text-gray-400">{r.tenant_name || "—"}</div>
                      </td>
                      <td className="py-2 pr-3 text-right tabular-nums text-gray-800">{pct(r.overall)}</td>
                      <td className="py-2 pr-3 text-right tabular-nums text-gray-500">{pct(r.rule)}</td>
                      <td className="py-2 pr-3 text-right tabular-nums text-gray-500">{pct(r.llm)}</td>
                      <td className="py-2 pr-3 text-right tabular-nums text-gray-500">{r.sources > 0 ? pct(r.faithful) : "—"}</td>
                      <td className="py-2">
                        <div className="flex items-center gap-1">
                          <span className={`rounded px-1.5 py-0.5 text-[10px] ${LEVEL_BADGE[r.level] ?? "bg-gray-100 text-gray-500"}`}>{LEVEL_LABEL[r.level] ?? r.level}</span>
                          {r.corrected && <span className="rounded bg-cyan-50 px-1.5 py-0.5 text-[10px] text-cyan-600">已纠偏</span>}
                        </div>
                      </td>
                    </tr>
                    {open === r.task_id && (
                      <tr className="bg-gray-50/60">
                        <td colSpan={7} className="px-3 py-3">
                          <div className="text-[11px] font-medium text-gray-500">评测评语</div>
                          <p className="mt-1 whitespace-pre-wrap text-xs leading-relaxed text-gray-700">{r.reason || "（无评语）"}</p>
                          <div className="mt-2 text-[11px] text-gray-400">检索来源 {r.sources} 处 · 提交者 {r.owner || "—"}</div>
                        </td>
                      </tr>
                    )}
                  </Fragment>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  );
}

const TONE: Record<string, string> = { violet: "text-violet-600", emerald: "text-emerald-600", rose: "text-rose-500", cyan: "text-cyan-600" };
function Stat({ label, value, sub, tone }: { label: string; value: ReactNode; sub?: ReactNode; tone: string }) {
  return (
    <div className="rounded-xl border border-gray-100 bg-white p-4 shadow-sm">
      <div className="text-xs text-gray-400">{label}</div>
      <div className={`mt-1 text-2xl font-semibold tabular-nums ${TONE[tone] ?? "text-gray-800"}`}>{value}</div>
      {sub && <div className="mt-1 text-[11px] text-gray-400">{sub}</div>}
    </div>
  );
}

// TrendChart：综合分/忠实度折线（左轴 [0,1]）+ 低分条数背景条。纯 SVG，无依赖。
function TrendChart({ trend }: { trend: EvalDay[] }) {
  if (trend.length === 0) return <div className="py-8 text-center text-xs text-gray-400">区间内暂无评测</div>;
  const w = 720, h = 160, pad = 24;
  const n = trend.length;
  const x = (i: number) => pad + (n === 1 ? (w - 2 * pad) / 2 : (i * (w - 2 * pad)) / (n - 1));
  const y = (v: number) => h - pad - v * (h - 2 * pad);
  const maxPoor = Math.max(1, ...trend.map((d) => d.poor_count));
  const line = (get: (d: EvalDay) => number) => trend.map((d, i) => `${i === 0 ? "M" : "L"}${x(i).toFixed(1)},${y(get(d)).toFixed(1)}`).join(" ");

  return (
    <div className="overflow-x-auto">
      <svg viewBox={`0 0 ${w} ${h + 20}`} className="w-full" style={{ minWidth: 480 }}>
        {[0, 0.5, 1].map((g) => (
          <g key={g}>
            <line x1={pad} y1={y(g)} x2={w - pad} y2={y(g)} stroke="#f1f1f4" />
            <text x={4} y={y(g) + 3} fontSize="9" fill="#bbb">{g}</text>
          </g>
        ))}
        {/* 低分条数背景条 */}
        {trend.map((d, i) => (
          <rect key={i} x={x(i) - 6} y={h - pad - (d.poor_count / maxPoor) * (h - 2 * pad) * 0.5} width={12}
            height={(d.poor_count / maxPoor) * (h - 2 * pad) * 0.5} fill="#fecdd3" opacity={0.6} rx={2} />
        ))}
        <path d={line((d) => d.avg_overall)} fill="none" stroke="#7c3aed" strokeWidth={2} />
        <path d={line((d) => d.avg_faithful || 0)} fill="none" stroke="#06b6d4" strokeWidth={2} strokeDasharray="3 2" />
        {trend.map((d, i) => (
          <text key={i} x={x(i)} y={h + 12} fontSize="9" fill="#999" textAnchor="middle">{mmdd(d.day)}</text>
        ))}
      </svg>
    </div>
  );
}
