"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";
import { Activity, Archive, BrainCircuit, ChevronRight, Database, History, Lock, RefreshCw, Send, Settings2, ShieldCheck, Sparkles, Trash2, Wrench } from "lucide-react";

function apiUrl(path: string): string {
  if (typeof window === "undefined") return path;
  const configured = process.env.NEXT_PUBLIC_API_URL?.trim().replace(/\/$/, "");
  const runtimeBase = `${window.location.protocol}//${window.location.hostname}:8000`;
  return `${configured || runtimeBase}${path}`;
}

async function apiFetch(path: string, init?: RequestInit, timeoutMs = 10000): Promise<Response> {
  const controller = new AbortController();
  const timeout = window.setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(apiUrl(path), { ...init, signal: controller.signal });
  } finally {
    window.clearTimeout(timeout);
  }
}

type SystemId = "text2mem" | "mem0" | "letta" | "reme" | "memu";
type SystemInfo = { id: SystemId; name: string; paradigm: string; description: string; available: boolean; mode: string; status: string; package?: string; setup_hint?: string };
type Memory = { id: string; system: string; content: string; memory_type: string; source: string; confidence: number; created_at: string; updated_at: string; metadata: Record<string, unknown> };
type Audit = { id: string; system: string; operation: string; status: string; target?: string; details: Record<string, unknown>; created_at: string };
type Message = { role: "user" | "assistant" | "system"; content: string; mode?: string; events?: string[] };

const fallbackSystems: SystemInfo[] = [
  { id: "text2mem", name: "Text2Mem", paradigm: "IR 操作契约", description: "显式定义记忆操作、授权与生命周期。", available: true, mode: "native", status: "ready" },
  { id: "mem0", name: "Mem0", paradigm: "自动提取", description: "自动提取事实，处理更新与冲突。", available: false, mode: "unavailable", status: "not-configured" },
  { id: "letta", name: "Letta", paradigm: "有状态 Agent", description: "Core / Archival / Recall 分层工作记忆。", available: false, mode: "unavailable", status: "not-installed" },
  { id: "reme", name: "ReMe", paradigm: "文件即记忆", description: "Markdown 文件、日志和混合检索。", available: false, mode: "unavailable", status: "not-configured" },
  { id: "memu", name: "memU", paradigm: "主动式管线", description: "后台整理、候选记忆和主动检索。", available: false, mode: "unavailable", status: "not-configured" },
];

const icons: Record<SystemId, typeof BrainCircuit> = { text2mem: ShieldCheck, mem0: BrainCircuit, letta: Database, reme: Archive, memu: Sparkles };

function initialMessages(): Record<SystemId, Message[]> {
  return {
    text2mem: [{ role: "assistant", content: "你好，我是 Text2Mem Agent。告诉我你的技术偏好、项目进展或希望我记住的工程规则。" }],
    mem0: [{ role: "assistant", content: "Mem0 适配器当前未启用；完成记忆投影、删除、重置和隔离闭环后再开放对话。" }],
    letta: [{ role: "assistant", content: "Letta 适配器当前未启用；完成 Agent ID 恢复和分层记忆投影后再开放对话。" }],
    reme: [{ role: "assistant", content: "你好，我是 ReMe Agent。当前对话只会使用 ReMe 的文件记忆。" }],
    memu: [{ role: "assistant", content: "memU 适配器当前未启用；完成队列、预算、审批和停止开关后再开放对话。" }],
  };
}

function setupSummary(system: SystemInfo): string {
  if (system.setup_hint) return system.setup_hint;
  if (system.id === "text2mem") return "本项目内置教学实现，无需额外框架服务。";
  if (system.id === "reme") return "已连接 ReMe 真实 SDK；右侧每一项代表一个 Markdown 记忆文件。";
  return "当前为未启用的适配器骨架。";
}

export default function Home() {
  const [systems, setSystems] = useState<SystemInfo[]>(fallbackSystems);
  const [selected, setSelected] = useState<SystemId>("text2mem");
  const [messagesBySystem, setMessagesBySystem] = useState<Record<SystemId, Message[]>>(initialMessages);
  const [input, setInput] = useState("");
  const [memories, setMemories] = useState<Memory[]>([]);
  const [audit, setAudit] = useState<Audit[]>([]);
  const [loading, setLoading] = useState(false);
  const [resetting, setResetting] = useState(false);
  const [deletingId, setDeletingId] = useState<string | null>(null);
  const [notice, setNotice] = useState("");

  const current = useMemo(() => systems.find((item) => item.id === selected) ?? fallbackSystems[0], [systems, selected]);
  const messages = messagesBySystem[selected];
  const memoryNoun = selected === "reme" ? "记忆文件" : "记忆";

  async function loadSystems() {
    try {
      const response = await apiFetch("/api/systems");
      if (!response.ok) throw new Error("API unavailable");
      const data = await response.json();
      setSystems(data.systems);
      setNotice(`已连接：${apiUrl("")} · 存储：${data.storage}`);
    } catch (error) {
      const reason = error instanceof Error ? error.message : "未知错误";
      setNotice(`连接失败：${apiUrl("")} · ${reason}`);
    }
  }

  async function loadDetails(system: SystemId = selected) {
    try {
      const [memoryResponse, auditResponse] = await Promise.all([
        apiFetch(`/api/memories?system=${system}`),
        apiFetch(`/api/audit?system=${system}`),
      ]);
      if (memoryResponse.ok) setMemories((await memoryResponse.json()).memories);
      if (auditResponse.ok) setAudit((await auditResponse.json()).events);
    } catch {
      setMemories([]);
      setAudit([]);
    }
  }

  useEffect(() => { void loadSystems(); void loadDetails(); }, []);
  useEffect(() => { void loadDetails(selected); }, [selected]);

  async function submit(event: FormEvent) {
    event.preventDefault();
    const content = input.trim();
    if (!content || loading) return;
    const system = selected;
    setInput("");
    setMessagesBySystem((all) => ({ ...all, [system]: [...all[system], { role: "user", content }] }));
    setLoading(true);
    try {
      const response = await apiFetch("/api/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ system, message: content }) }, 120000);
      const data = await response.json();
      if (!response.ok) throw new Error(data.detail ?? "执行失败");
      setMessagesBySystem((all) => ({ ...all, [system]: [...all[system], { role: "assistant", content: data.answer, mode: data.mode, events: data.memory_events?.map((item: { event?: string }) => item.event).filter(Boolean) }] }));
      await loadDetails(system);
    } catch (error) {
      setMessagesBySystem((all) => ({ ...all, [system]: [...all[system], { role: "system", content: error instanceof Error ? error.message : "执行失败" }] }));
    } finally {
      setLoading(false);
    }
  }

  async function reset() {
    if (!window.confirm(`确定清空 ${current.name} 的本地记忆和审计记录吗？`)) return;
    const system = selected;
    setResetting(true);
    try {
      const response = await apiFetch("/api/reset", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ system }) }, 60000);
      const data = await response.json();
      if (!response.ok) throw new Error(data.detail ?? "清空失败");
      setMessagesBySystem((all) => ({ ...all, [system]: [...initialMessages()[system], { role: "system", content: `${current.name} 的记忆已清空。` }] }));
      await loadDetails(system);
    } catch (error) {
      setNotice(error instanceof Error ? error.message : "清空失败");
    } finally {
      setResetting(false);
    }
  }

  async function deleteMemory(memory: Memory) {
    const warning = selected === "reme" ? "该文件可能包含多条事实，删除后会重建 ReMe 索引。\n\n" : "";
    if (!window.confirm(`确定删除这个${current.name}${memoryNoun}吗？\n\n${warning}${memory.content.slice(0, 120)}`)) return;
    const system = selected;
    setDeletingId(memory.id);
    try {
      const response = await apiFetch(`/api/memories/${encodeURIComponent(memory.id)}?system=${system}`, { method: "DELETE" }, 60000);
      const data = await response.json();
      if (!response.ok) throw new Error(data.detail ?? "删除失败");
      await loadDetails(system);
    } catch (error) {
      setNotice(error instanceof Error ? error.message : "删除失败");
    } finally {
      setDeletingId(null);
    }
  }

  const Icon = icons[selected];
  return (
    <main className="app-shell">
      <header className="topbar">
        <div className="brand"><div className="brand-mark"><BrainCircuit size={20} /></div><div><div className="brand-title">Memory Agents Lab</div><div className="brand-subtitle">五种记忆范式 · 同一场景 · 独立证据</div></div></div>
        <div className="top-actions"><span className="workspace-pill"><Activity size={14} /> local-workspace</span><button className="icon-button" onClick={() => { void loadSystems(); void loadDetails(); }} title="刷新状态"><RefreshCw size={16} /></button></div>
      </header>

      <section className="hero"><div><p className="eyebrow">AI PROGRAMMING ASSISTANT</p><h1>把记忆从黑箱，<span>变成可观察的系统。</span></h1><p className="hero-copy">五种记忆范式使用同一套工程场景；当前可实测 Text2Mem 与 ReMe，其余适配器保留为后续扩展。</p></div><div className="hero-status"><div className="status-label"><span className="pulse" />系统状态</div><strong>{notice || "正在连接后端…"}</strong><small>模型 API、数据库和框架均可按需配置</small></div></section>

      <div className="workspace-grid">
        <aside className="system-rail panel"><div className="panel-heading"><div><span className="section-kicker">PARADIGMS</span><h2>记忆系统</h2></div><Settings2 size={17} className="muted" /></div><div className="system-list">{systems.map((system) => { const SystemIcon = icons[system.id]; return <button key={system.id} className={`system-card ${selected === system.id ? "selected" : ""}`} onClick={() => setSelected(system.id)}><div className="system-icon"><SystemIcon size={17} /></div><div className="system-copy"><strong>{system.name}</strong><span>{system.paradigm}</span></div><div className={`availability ${system.available ? "on" : "off"}`} title={system.available ? "可用" : "未配置"} />{selected === system.id && <ChevronRight size={15} className="selected-arrow" />}</button>; })}</div><div className="rail-note"><Lock size={15} /><span>当前是单工作区模式。未来可扩展用户与租户隔离。</span></div></aside>

        <section className="chat-panel panel"><div className="chat-header"><div className="chat-system-title"><div className="system-icon large"><Icon size={20} /></div><div><div className="section-kicker">ACTIVE AGENT</div><h2>{current.name}<span className="mode-chip">{current.mode}</span></h2></div></div><button className="reset-button" onClick={reset} disabled={resetting}><Trash2 size={15} />{resetting ? "清空中" : "清空记忆"}</button></div><div className="agent-description">{current.description} <span className="separator">·</span> {setupSummary(current)}</div><div className="messages">{messages.map((message, index) => <div key={`${message.role}-${index}`} className={`message-row ${message.role}`}><div className="message-avatar">{message.role === "user" ? "你" : message.role === "system" ? "!" : "M"}</div><div className="message-bubble"><div className="message-role">{message.role === "user" ? "USER" : message.role === "system" ? "SYSTEM" : current.name.toUpperCase()}{message.mode && <span className="message-mode">{message.mode}</span>}</div><div className="message-content">{message.content}</div>{message.events && message.events.length > 0 && <div className="event-tags">{message.events.map((event) => <span key={event}>{event}</span>)}</div>}</div></div>)}</div><form className="composer" onSubmit={submit}><textarea value={input} onChange={(event) => setInput(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); void submit(event); } }} placeholder={current.available ? "例如：记住我偏好用 Python + FastAPI，项目数据库选 PostgreSQL…" : "该适配器当前未启用，请先查看上方配置说明。"} rows={2} disabled={!current.available} /><button className="send-button" disabled={loading || !input.trim() || !current.available}>{loading ? <RefreshCw size={17} className="spin" /> : <Send size={17} />}<span>{loading ? "处理中" : "发送"}</span></button></form></section>

        <aside className="inspector panel"><div className="inspector-tabs"><span className="active"><Archive size={15} />记忆</span><span><History size={15} />审计</span></div><div className="inspector-content"><div className="inspector-summary"><div><span className="section-kicker">MEMORY STORE</span><h2>{memories.length}<small> {selected === "reme" ? "个记忆文件" : "条记忆"}</small></h2></div><span className="storage-badge"><Database size={13} />持久化</span></div>{memories.length === 0 ? <div className="empty-state"><Archive size={25} /><strong>还没有记忆</strong><span>在对话中使用“记住”“偏好”“项目”等表达，观察写入事件。</span></div> : <div className="memory-list">{memories.map((memory) => <article className="memory-item" key={memory.id}><div className="memory-meta"><span>{memory.memory_type}</span><time>{new Date(memory.updated_at).toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}</time><button className="memory-delete-button" type="button" aria-label={`删除${memoryNoun}：${memory.content.slice(0, 30)}`} title={`删除这个${memoryNoun}`} disabled={deletingId === memory.id} onClick={() => { void deleteMemory(memory); }}><Trash2 size={12} />{deletingId === memory.id ? "删除中" : "删除"}</button></div><p>{memory.content}</p><div className="memory-source">来源：{memory.source} · 置信度：{Math.round(memory.confidence * 100)}%</div></article>)}</div>}<div className="audit-preview"><div className="subheading"><span>最近审计</span><span className="count-badge">{audit.length}</span></div>{audit.slice(0, 5).map((event) => <div className="audit-row" key={event.id}><span className="audit-dot" /><span>{event.operation}</span><time>{new Date(event.created_at).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" })}</time></div>)}</div></div></aside>
      </div>
      <footer><Wrench size={14} /> <span>Text2Mem 和 ReMe 已完成当前阶段闭环；Mem0、Letta 和 memU 仅保留未启用适配器骨架。</span><span className="footer-link">见 README →</span></footer>
    </main>
  );
}
