"use client";

import type { CSSProperties } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";

import type { AgentCompletionStep, AgentRunLog, AgentToolEvent } from "@/lib/agent-run-log-types";
import { buildDebugTrace } from "@/lib/agent-debug-trace";
import { appToast } from "@/lib/app-toast";

function formatRelativeTime(ts: number): string {
  const sec = Math.round((Date.now() - ts) / 1000);
  if (sec < 45) return "just now";
  if (sec < 3600) return `${Math.round(sec / 60)} min ago`;
  if (sec < 86400) return `${Math.round(sec / 3600)} h ago`;
  return `${Math.round(sec / 86400)} d ago`;
}

function stoppedBadgeStyle(s: AgentRunLog["stoppedBecause"]): CSSProperties {
  if (s === "completed") return { background: "rgba(34,197,94,0.15)", color: "#16a34a", border: "1px solid rgba(34,197,94,0.35)" };
  if (s === "budget_exhausted" || s === "timeout" || s === "partial_results_awaiting_resume")
    return { background: "rgba(245,158,11,0.15)", color: "#d97706", border: "1px solid rgba(245,158,11,0.35)" };
  return { background: "rgba(239,68,68,0.12)", color: "#dc2626", border: "1px solid rgba(239,68,68,0.3)" };
}

function toolStatusSymbol(st: AgentToolEvent["status"]): string {
  if (st === "ok") return "✓";
  if (st === "error") return "✗";
  return "⚠";
}

type HirebaseProbeResult = {
  configured: boolean;
  ok: boolean;
  httpStatus?: number;
  message: string;
  keySuffix?: string;
  hint?: string;
  mode?: "lexical" | "neural";
};

export function AgentRunsDebugger() {
  const [runs, setRuns] = useState<AgentRunLog[]>([]);
  const [meta, setMeta] = useState<{ labInferenceLogging: boolean; redisConfigured: boolean } | null>(null);
  const [hirebaseProbe, setHirebaseProbe] = useState<HirebaseProbeResult | null>(null);
  const [hirebaseProbeLoading, setHirebaseProbeLoading] = useState(false);
  const [loading, setLoading] = useState(true);
  const [detail, setDetail] = useState<AgentRunLog | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [expandedTools, setExpandedTools] = useState<Set<number>>(() => new Set());
  const [expandedSteps, setExpandedSteps] = useState<Set<number>>(() => new Set());

  const refreshList = useCallback(async () => {
    setLoading(true);
    try {
      const res = await fetch("/api/lab/agent-runs", { credentials: "include" });
      if (!res.ok) {
        setRuns([]);
        setMeta(null);
        return;
      }
      const j = (await res.json()) as {
        runs?: AgentRunLog[];
        labInferenceLogging?: boolean;
        redisConfigured?: boolean;
      };
      setRuns(Array.isArray(j.runs) ? j.runs : []);
      setMeta({
        labInferenceLogging: Boolean(j.labInferenceLogging),
        redisConfigured: Boolean(j.redisConfigured),
      });
    } catch {
      setRuns([]);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void refreshList();
  }, [refreshList]);

  const runHirebaseProbe = useCallback(async () => {
    setHirebaseProbeLoading(true);
    try {
      const res = await fetch("/api/lab/hirebase-probe", { credentials: "include" });
      if (!res.ok) {
        setHirebaseProbe(null);
        appToast.error("Hirebase probe failed — check lab admin access");
        return;
      }
      const j = (await res.json()) as HirebaseProbeResult;
      setHirebaseProbe(j);
    } catch {
      setHirebaseProbe(null);
      appToast.error("Could not run Hirebase probe");
    } finally {
      setHirebaseProbeLoading(false);
    }
  }, []);

  useEffect(() => {
    void runHirebaseProbe();
  }, [runHirebaseProbe]);

  const loadDetail = useCallback(async (runId: string) => {
    setDetailLoading(true);
    try {
      const res = await fetch(`/api/lab/agent-runs?runId=${encodeURIComponent(runId)}&verbose=true`, {
        credentials: "include",
      });
      if (!res.ok) {
        setDetail(null);
        return;
      }
      const j = (await res.json()) as { run?: AgentRunLog };
      setDetail(j.run ?? null);
    } catch {
      setDetail(null);
    } finally {
      setDetailLoading(false);
    }
  }, []);

  const copyTrace = useCallback(async () => {
    if (!detail) return;
    const md = buildDebugTrace(detail);
    try {
      if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
        throw new Error("no clipboard");
      }
      await navigator.clipboard.writeText(md);
      appToast.success("Debug trace copied to clipboard");
    } catch {
      appToast.error("Could not copy — try selecting and copying manually");
    }
  }, [detail]);

  const toggleTool = useCallback((i: number) => {
    setExpandedTools((prev) => {
      const n = new Set(prev);
      if (n.has(i)) n.delete(i);
      else n.add(i);
      return n;
    });
  }, []);

  const toggleStepMessages = useCallback((i: number) => {
    setExpandedSteps((prev) => {
      const n = new Set(prev);
      if (n.has(i)) n.delete(i);
      else n.add(i);
      return n;
    });
  }, []);

  const sectionStyle = useMemo(
    () =>
      ({
        padding: 14,
        borderRadius: 10,
        border: "1px solid var(--border-subtle)",
        marginBottom: 16,
      }) as const,
    [],
  );

  return (
    <section style={sectionStyle}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
        <h2
          style={{
            fontSize: 11,
            fontWeight: 600,
            textTransform: "uppercase",
            letterSpacing: 0.5,
            color: "var(--muted)",
            margin: 0,
          }}
        >
          Agent runs
        </h2>
        <button type="button" onClick={() => void refreshList()}>
          Refresh
        </button>
      </div>
      {meta ? (
        <p style={{ fontSize: 12, color: "var(--muted)", marginTop: 0, marginBottom: 10 }}>
          Redis: {meta.redisConfigured ? "configured" : "not configured"} · Verbose inference (
          <code>LAB_LOG_INFERENCE</code>): {meta.labInferenceLogging ? "on" : "off"}
        </p>
      ) : null}
      <div
        style={{
          fontSize: 12,
          marginBottom: 12,
          padding: 10,
          borderRadius: 8,
          border: "1px solid var(--border-subtle)",
          background: "var(--surface-raised)",
        }}
      >
        <div style={{ display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center", marginBottom: 6 }}>
          <strong>Hirebase</strong>
          <button type="button" disabled={hirebaseProbeLoading} onClick={() => void runHirebaseProbe()}>
            {hirebaseProbeLoading ? "Probing…" : "Probe API key"}
          </button>
        </div>
        {hirebaseProbe ? (
          <div style={{ color: hirebaseProbe.ok ? "#16a34a" : "#dc2626" }}>
            {hirebaseProbe.configured ?
              `Key …${hirebaseProbe.keySuffix ?? "????"} · mode: ${hirebaseProbe.mode ?? "lexical"} · HTTP ${hirebaseProbe.httpStatus ?? "—"} · ${hirebaseProbe.message}`
            : "HIREBASE_API_KEY not set on server"}
          </div>
        ) : (
          <div style={{ color: "var(--muted)" }}>Run probe to verify search API auth.</div>
        )}
        {hirebaseProbe?.hint ? (
          <div style={{ marginTop: 6, color: "var(--muted)" }}>{hirebaseProbe.hint}</div>
        ) : null}
        <div style={{ marginTop: 6, color: "var(--muted)", fontSize: 11 }}>
          Server logs: filter <code>hirebase.search</code> or <code>[hirebase]</code> on your Space runtime logs.
        </div>
      </div>
      {loading ? (
        <p style={{ fontSize: 13 }}>Loading…</p>
      ) : runs.length === 0 ? (
        <p style={{ fontSize: 13, color: "var(--muted)" }}>No runs recorded yet.</p>
      ) : (
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}>
            <thead>
              <tr style={{ textAlign: "left", color: "var(--muted)" }}>
                <th style={{ padding: "6px 8px" }}>When</th>
                <th style={{ padding: "6px 8px" }}>User</th>
                <th style={{ padding: "6px 8px" }}>Duration</th>
                <th style={{ padding: "6px 8px" }}>Stop</th>
                <th style={{ padding: "6px 8px" }}>Tools</th>
                <th style={{ padding: "6px 8px" }}>Credits</th>
                <th style={{ padding: "6px 8px" }}>Verbose</th>
              </tr>
            </thead>
            <tbody>
              {runs.map((r) => (
                <tr
                  key={r.runId}
                  style={{
                    cursor: "pointer",
                    borderTop: "1px solid var(--border-subtle)",
                    background: detail?.runId === r.runId ? "var(--surface-muted)" : undefined,
                  }}
                  onClick={() => void loadDetail(r.runId)}
                >
                  <td style={{ padding: "8px", whiteSpace: "nowrap" }}>{formatRelativeTime(r.startedAt)}</td>
                  <td style={{ padding: "8px", fontFamily: "ui-monospace, monospace", maxWidth: 120 }} title={r.userId}>
                    {r.userId.length > 14 ? `${r.userId.slice(0, 10)}…` : r.userId}
                  </td>
                  <td style={{ padding: "8px" }}>{(r.durationMs / 1000).toFixed(1)}s</td>
                  <td style={{ padding: "8px" }}>
                    <span style={{ ...stoppedBadgeStyle(r.stoppedBecause), borderRadius: 6, padding: "2px 8px", fontSize: 11 }}>
                      {r.stoppedBecause}
                    </span>
                  </td>
                  <td style={{ padding: "8px" }}>{r.totalTools}</td>
                  <td style={{ padding: "8px" }}>{r.creditCost}</td>
                  <td style={{ padding: "8px" }}>{r.verboseTraceStored ? "yes" : "—"}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {detail ? (
        <div style={{ marginTop: 16, borderTop: "1px solid var(--border-subtle)", paddingTop: 14 }}>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center", marginBottom: 12 }}>
            <strong style={{ fontSize: 14 }}>Run {detail.runId.slice(0, 8)}…</strong>
            <button type="button" onClick={() => void copyTrace()}>
              Copy debug trace
            </button>
            {detailLoading ? <span style={{ fontSize: 12, color: "var(--muted)" }}>Loading…</span> : null}
          </div>
          {detail.errorMessage ? (
            <div style={{ fontSize: 12, marginBottom: 10, color: "#dc2626" }}>
              Run error: {detail.errorMessage}
              {detail.rawErrorMessage && detail.rawErrorMessage !== detail.errorMessage ? (
                <div style={{ marginTop: 4, color: "#b45309", wordBreak: "break-word" }}>
                  Raw: {detail.rawErrorMessage}
                </div>
              ) : null}
            </div>
          ) : null}
          <div
            style={{
              display: "flex",
              flexWrap: "wrap",
              gap: 14,
            }}
          >
            <div>
              <h3 style={{ fontSize: 12, margin: "0 0 8px", color: "var(--muted)" }}>Tool timeline</h3>
              <ul style={{ listStyle: "none", padding: 0, margin: 0, fontSize: 12 }}>
                {detail.tools.map((t, i) => (
                  <li
                    key={`${t.tool}-${t.startedAt}-${i}`}
                    style={{
                      marginBottom: 10,
                      padding: 8,
                      borderRadius: 8,
                      border: "1px solid var(--border-subtle)",
                      background: "var(--surface-raised)",
                    }}
                  >
                    <div>
                      {toolStatusSymbol(t.status)} <strong>{t.tool}</strong> · {t.durationMs}ms
                      {t.backend ? ` · backend: ${t.backend}` : ""}
                      {t.provider ? ` · scoring: ${t.provider}` : ""}
                      {t.creditCost ? ` · ${t.creditCost} cr` : ""}
                    </div>
                    {t.resultSummary ? (
                      <div style={{ marginTop: 4, color: "var(--muted)" }}>{t.resultSummary}</div>
                    ) : null}
                    {t.rawResultSummary && t.rawResultSummary !== t.resultSummary ? (
                      <div style={{ marginTop: 4, color: "#b45309", fontSize: 11, wordBreak: "break-word" }}>
                        Raw: {t.rawResultSummary}
                      </div>
                    ) : null}
                    {t.input && Object.keys(t.input).length > 0 ? (
                      <div style={{ marginTop: 6 }}>
                        <button type="button" style={{ fontSize: 11 }} onClick={() => toggleTool(i)}>
                          {expandedTools.has(i) ? "Hide" : "Show"} input
                        </button>
                        {expandedTools.has(i) ? (
                          <pre
                            style={{
                              marginTop: 6,
                              fontSize: 10,
                              overflow: "auto",
                              maxHeight: 160,
                              background: "#111",
                              color: "#b8c0cc",
                              padding: 8,
                              borderRadius: 6,
                            }}
                          >
                            {JSON.stringify(t.input, null, 2)}
                          </pre>
                        ) : null}
                      </div>
                    ) : null}
                  </li>
                ))}
              </ul>
            </div>
            <div style={{ flex: "1 1 320px", minWidth: 0 }}>
              <h3 style={{ fontSize: 12, margin: "0 0 8px", color: "var(--muted)" }}>LLM steps</h3>
              <ul style={{ listStyle: "none", padding: 0, margin: 0, fontSize: 12 }}>
                {detail.completionSteps.map((s: AgentCompletionStep) => (
                  <li
                    key={s.stepIndex}
                    style={{
                      marginBottom: 10,
                      padding: 8,
                      borderRadius: 8,
                      border: "1px solid var(--border-subtle)",
                      background: "var(--surface-raised)",
                    }}
                  >
                    <div>
                      <strong>Step {s.stepIndex + 1}</strong> · {s.model || "?"} ({s.provider}) · {s.durationMs}ms
                    </div>
                    {s.errorMessage ? (
                      <div style={{ color: "#dc2626", marginTop: 4 }}>{s.errorMessage}</div>
                    ) : null}
                    {s.rawErrorMessage && s.rawErrorMessage !== s.errorMessage ? (
                      <div style={{ color: "#b45309", marginTop: 4, fontSize: 11, wordBreak: "break-word" }}>
                        Raw: {s.rawErrorMessage}
                      </div>
                    ) : null}
                    {s.assistantReasoningText ? (
                      <blockquote style={{ margin: "6px 0", fontSize: 11, color: "var(--muted)" }}>
                        {s.assistantReasoningText.slice(0, 600)}
                        {s.assistantReasoningText.length > 600 ? "…" : ""}
                      </blockquote>
                    ) : null}
                    {s.toolCalls?.length ? (
                      <ul style={{ margin: "4px 0 0", paddingLeft: 16 }}>
                        {s.toolCalls.map((tc) => (
                          <li key={tc.name}>
                            <code>{tc.name}</code>
                          </li>
                        ))}
                      </ul>
                    ) : null}
                    {s.messages?.length ? (
                      <div style={{ marginTop: 6 }}>
                        <button type="button" style={{ fontSize: 11 }} onClick={() => toggleStepMessages(s.stepIndex)}>
                          {expandedSteps.has(s.stepIndex) ? "Hide" : "View"} full messages ({s.messages.length})
                        </button>
                        {expandedSteps.has(s.stepIndex) ? (
                          <pre
                            style={{
                              marginTop: 6,
                              fontSize: 10,
                              overflow: "auto",
                              maxHeight: 240,
                              background: "#111",
                              color: "#b8c0cc",
                              padding: 8,
                              borderRadius: 6,
                            }}
                          >
                            {JSON.stringify(s.messages, null, 2).slice(0, 12000)}
                          </pre>
                        ) : null}
                      </div>
                    ) : null}
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>
      ) : null}
    </section>
  );
}
