import { useEffect, useState } from "react";
import { listAudit, listGuardrailEvents, type AuditEntry, type GuardrailEventItem } from "../api";

// 操作方法配色。
const ACTION_STYLE: Record<string, string> = {
  POST: "bg-emerald-50 text-emerald-600",
  PUT: "bg-amber-50 text-amber-600",
  DELETE: "bg-rose-50 text-rose-600",
  PATCH: "bg-violet-50 text-violet-600",
};
const statusTone = (s: number) => (s < 300 ? "text-emerald-600" : s < 500 ? "text-amber-600" : "text-rose-500");

// uid 太长，展示时截断（保留首尾，hover 看全）。
const shortId = (id: string) => (id && id.length > 10 ? `${id.slice(0, 4)}…${id.slice(-4)}` : id || "系统");
const fmt = (at: string) => new Date(at).toLocaleString("zh-CN", { hour12: false });

export function AuditPage() {
  const [audit, setAudit] = useState<AuditEntry[]>([]);
  const [events, setEvents] = useState<GuardrailEventItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [updatedAt, setUpdatedAt] = useState<Date | null>(null);
  const [err, setErr] = useState("");

  const load = async () => {
    setRefreshing(true);
    try {
      const [a, e] = await Promise.all([listAudit(80), listGuardrailEvents(80)]);
      setAudit(a);
      setEvents(e);
      setUpdatedAt(new Date());
      setErr("");
    } catch (er) {
      setErr((er as Error).message);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  };

  useEffect(() => {
    void load();
    const t = setInterval(() => void load(), 30000);
    return () => clearInterval(t);
  }, []);

  if (loading) return <div className="text-sm text-gray-400">加载审计记录中…</div>;
  if (err) return <div className="text-sm text-rose-500">加载失败：{err}</div>;

  const blocked = events.filter((e) => e.kind === "blocked").length;
  const suspect = events.filter((e) => e.kind === "suspect").length;

  return (
    <div className="space-y-5">
      {/* 顶栏 */}
      <div className="flex flex-wrap items-center gap-4 rounded-2xl border border-gray-200/70 bg-white p-5">
        <div className="mr-auto">
          <h3 className="text-sm font-semibold tracking-tight text-gray-900">审计 & 安全事件</h3>
          <p className="text-xs text-gray-400">敏感操作留痕 + 输入护栏命中 · 只增不改，供运维溯源</p>
        </div>
        <div className="grid grid-cols-3 divide-x divide-gray-100">
          <Stat value={audit.length} label="操作留痕" />
          <Stat value={blocked} label="护栏拦截" bad={blocked > 0} />
          <Stat value={suspect} label="灰区放行" warn={suspect > 0} />
        </div>
        <div className="flex items-center gap-2 text-xs text-gray-400">
          {updatedAt && <span>更新于 {updatedAt.toLocaleTimeString("zh-CN", { hour12: false })}</span>}
          <button
            onClick={() => void load()}
            disabled={refreshing}
            className="flex items-center gap-1 rounded border border-gray-200 px-2.5 py-1 text-gray-500 hover:bg-gray-50 disabled:opacity-40"
          >
            <svg viewBox="0 0 24 24" className={`h-3.5 w-3.5 ${refreshing ? "animate-spin" : ""}`} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M23 4v6h-6 M1 20v-6h6 M3.51 9a9 9 0 0 1 14.85-3.36L23 10 M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
            </svg>
            刷新
          </button>
        </div>
      </div>

      {/* 安全事件（护栏命中） */}
      <section className="rounded-2xl border border-gray-200/70 bg-white p-5">
        <div className="mb-3 flex items-baseline gap-2.5">
          <h3 className="text-sm font-semibold tracking-tight text-gray-900">安全事件</h3>
          <span className="text-xs text-gray-400">输入护栏拦截 / 灰区放行（{events.length}）</span>
        </div>
        {events.length === 0 ? (
          <div className="rounded-xl bg-gray-50/70 py-8 text-center text-xs text-gray-400">暂无护栏命中 🎉</div>
        ) : (
          <div className="divide-y divide-gray-100">
            {events.map((e) => (
              <div key={e.id} className="flex items-center gap-3 py-2.5 text-xs">
                <span className={`rounded px-1.5 py-0.5 text-[10px] font-semibold ${e.kind === "blocked" ? "bg-rose-50 text-rose-600" : "bg-amber-50 text-amber-600"}`}>
                  {e.kind === "blocked" ? "拦截" : "灰区"}
                </span>
                <span className="min-w-0 flex-1 truncate text-gray-700" title={e.reason}>{e.reason || "（无原因）"}</span>
                <code className="hidden shrink-0 font-mono text-[10px] text-gray-400 sm:inline">{e.method} {e.path}</code>
                <span className="shrink-0 font-mono text-[10px] text-gray-300" title={e.actor}>{shortId(e.actor)}</span>
                <span className="hidden shrink-0 text-[10px] text-gray-300 md:inline">{e.ip}</span>
                <span className="shrink-0 text-[10px] text-gray-300">{fmt(e.at)}</span>
              </div>
            ))}
          </div>
        )}
      </section>

      {/* 操作审计 */}
      <section className="rounded-2xl border border-gray-200/70 bg-white p-5">
        <div className="mb-3 flex items-baseline gap-2.5">
          <h3 className="text-sm font-semibold tracking-tight text-gray-900">操作审计</h3>
          <span className="text-xs text-gray-400">改配置 / 改密钥 / 激活提示词 / 审批 等变更操作（{audit.length}）</span>
        </div>
        {audit.length === 0 ? (
          <div className="rounded-xl bg-gray-50/70 py-8 text-center text-xs text-gray-400">暂无操作留痕</div>
        ) : (
          <div className="divide-y divide-gray-100">
            {audit.map((a) => (
              <div key={a.id} className="flex items-center gap-3 py-2.5 text-xs">
                <span className={`w-14 shrink-0 rounded px-1.5 py-0.5 text-center text-[10px] font-semibold ${ACTION_STYLE[a.action] ?? "bg-gray-100 text-gray-500"}`}>
                  {a.action}
                </span>
                <code className="min-w-0 flex-1 truncate font-mono text-[11px] text-gray-600" title={a.path}>{a.path}</code>
                <span className={`shrink-0 font-mono text-[10px] ${statusTone(a.status)}`}>{a.status}</span>
                <span className="shrink-0 font-mono text-[10px] text-gray-300" title={a.actor}>{shortId(a.actor)}</span>
                <span className="hidden shrink-0 text-[10px] text-gray-300 md:inline">{a.ip}</span>
                <span className="shrink-0 text-[10px] text-gray-300">{fmt(a.at)}</span>
              </div>
            ))}
          </div>
        )}
      </section>
    </div>
  );
}

function Stat({ value, label, bad, warn }: { value: number; label: string; bad?: boolean; warn?: boolean }) {
  return (
    <div className="px-4 first:pl-0">
      <div className={`text-xl font-semibold tracking-tight ${bad ? "text-rose-500" : warn ? "text-amber-600" : "text-gray-900"}`}>{value}</div>
      <div className="text-[10px] text-gray-400">{label}</div>
    </div>
  );
}
