"use client";

import { FormEvent, useEffect, useMemo, useRef, useState } from "react";
import { Loader2, RefreshCw, Search, Trash2 } from "lucide-react";
import { crossfadeIn, pulseFeedback, revealChildren, runScopedMotion } from "@/lib/ui/motion";

type LogLevel = "info" | "warning" | "error";

type LogEntry = {
  id: string;
  createdAt: string;
  level: LogLevel;
  source: string;
  message: string;
  status?: number;
  method?: string;
  path?: string;
  stack?: string;
  details?: unknown;
};

type LogPayload = {
  entries: LogEntry[];
  logPath: string;
  maxBytes: number;
};

const LEVEL_TABS: Array<{ id: LogLevel | "all"; label: string }> = [
  { id: "all", label: "全部" },
  { id: "error", label: "错误" },
  { id: "warning", label: "警告" },
  { id: "info", label: "信息" }
];

export function LogManager() {
  const [payload, setPayload] = useState<LogPayload | null>(null);
  const [level, setLevel] = useState<LogLevel | "all">("all");
  const [query, setQuery] = useState("");
  const [draftQuery, setDraftQuery] = useState("");
  const [loading, setLoading] = useState(true);
  const [clearing, setClearing] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);
  const logsRef = useRef<HTMLDivElement | null>(null);
  const contentRef = useRef<HTMLElement | null>(null);
  const feedbackRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    void loadLogs();
  }, [level, query]);

  useEffect(() => {
    return runScopedMotion(logsRef, (scope) => revealChildren(scope));
  }, []);

  useEffect(() => {
    crossfadeIn(contentRef.current);
  }, [payload?.entries]);

  useEffect(() => {
    pulseFeedback(feedbackRef.current);
  }, [error, message]);

  const stats = useMemo(() => {
    const entries = payload?.entries || [];
    return {
      total: entries.length,
      error: entries.filter((entry) => entry.level === "error").length,
      warning: entries.filter((entry) => entry.level === "warning").length,
      info: entries.filter((entry) => entry.level === "info").length
    };
  }, [payload]);

  async function loadLogs() {
    setLoading(true);
    setError(null);
    try {
      const params = new URLSearchParams({ level, limit: "200" });
      if (query.trim()) params.set("q", query.trim());
      const response = await fetch(`/api/logs?${params.toString()}`, { cache: "no-store" });
      const nextPayload = await response.json();
      if (!response.ok) throw new Error(nextPayload.error || "读取日志失败");
      setPayload(nextPayload);
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setLoading(false);
    }
  }

  async function clearLogs() {
    if (!window.confirm("确定清空后台日志？")) return;
    setClearing(true);
    setError(null);
    setMessage(null);
    try {
      const response = await fetch("/api/logs", { method: "DELETE" });
      const result = await response.json();
      if (!response.ok) throw new Error(result.error || "清空日志失败");
      setMessage("日志已清空。");
      await loadLogs();
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setClearing(false);
    }
  }

  function submitSearch(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setQuery(draftQuery.trim());
  }

  return (
    <div className="log-manager" ref={logsRef}>
      <div className="workspace-head" data-animate>
        <div>
          <h1 className="workspace-title">日志管理</h1>
        </div>
        <div className="workspace-meta">
          <span className="status">{stats.total} 条</span>
          <span className="status failed">{stats.error} 错误</span>
          <span className="status running">{stats.warning} 警告</span>
        </div>
      </div>

      <section className="panel log-actions" data-animate>
        <div className="segmented log-tabs" aria-label="日志级别">
          {LEVEL_TABS.map((tab) => (
            <button
              className={level === tab.id ? "active" : ""}
              aria-pressed={level === tab.id}
              type="button"
              key={tab.id}
              onClick={() => setLevel(tab.id)}
            >
              {tab.label}
            </button>
          ))}
        </div>
        <form className="log-search" onSubmit={submitSearch}>
          <Search aria-hidden="true" />
          <input
            value={draftQuery}
            placeholder="搜索消息、路径、状态"
            onChange={(event) => setDraftQuery(event.target.value)}
          />
        </form>
        <div className="toolbar">
          <button className="button" type="button" onClick={loadLogs} disabled={loading || clearing}>
            {loading ? <Loader2 className="spin" size={18} /> : <RefreshCw size={18} />}
            刷新
          </button>
          <button className="button danger" type="button" onClick={clearLogs} disabled={loading || clearing}>
            {clearing ? <Loader2 className="spin" size={18} /> : <Trash2 size={18} />}
            清空
          </button>
        </div>
      </section>

      {error || message ? (
        <div ref={feedbackRef}>
          {error ? <div className="callout" role="alert">{error}</div> : null}
          {message ? <div className="callout success-callout" role="status" aria-live="polite">{message}</div> : null}
        </div>
      ) : null}

      <section className="panel log-storage" data-animate>
        <div>
          <span>日志文件</span>
          <strong>{payload?.logPath || ".runtime/logs/server-events.jsonl"}</strong>
        </div>
        <div>
          <span>单文件上限</span>
          <strong>{formatBytes(payload?.maxBytes || 0)}</strong>
        </div>
        <div>
          <span>当前筛选</span>
          <strong>{levelLabel(level)} / {query || "全部"}</strong>
        </div>
      </section>

      <section className="panel log-list" data-animate ref={contentRef}>
        {loading && !payload ? (
          <div className="settings-loading">
            <Loader2 className="spin" size={18} />
            正在读取日志
          </div>
        ) : payload?.entries.length ? (
          payload.entries.map((entry) => <LogRow entry={entry} key={entry.id} />)
        ) : (
          <div className="log-empty">暂无日志</div>
        )}
      </section>
    </div>
  );
}

function LogRow({ entry }: { entry: LogEntry }) {
  const details = detailText(entry);
  return (
    <article className={`log-row log-row-${entry.level}`}>
      <div className="log-row-main">
        <span className={`status ${entry.level === "error" ? "failed" : entry.level === "warning" ? "running" : ""}`}>{levelLabel(entry.level)}</span>
        <div className="log-message">
          <strong>{entry.message}</strong>
          <small>{formatTime(entry.createdAt)} · {entry.source}{entry.status ? ` · ${entry.status}` : ""}{entry.method || entry.path ? ` · ${[entry.method, entry.path].filter(Boolean).join(" ")}` : ""}</small>
        </div>
      </div>
      {details ? (
        <details className="log-detail">
          <summary>详情</summary>
          <pre>{details}</pre>
        </details>
      ) : null}
    </article>
  );
}

function detailText(entry: LogEntry): string {
  const parts: string[] = [];
  if (entry.stack) parts.push(entry.stack);
  if (entry.details !== undefined) parts.push(JSON.stringify(entry.details, null, 2));
  return parts.join("\n\n");
}

function levelLabel(level: LogLevel | "all"): string {
  if (level === "error") return "错误";
  if (level === "warning") return "警告";
  if (level === "info") return "信息";
  return "全部";
}

function formatTime(value: string): string {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString("zh-CN", { hour12: false });
}

function formatBytes(value: number): string {
  if (!value) return "-";
  if (value >= 1024 * 1024) return `${(value / 1024 / 1024).toFixed(1)} MB`;
  if (value >= 1024) return `${(value / 1024).toFixed(1)} KB`;
  return `${value} B`;
}
