"use client";

import { useEffect, useRef, useState } from "react";
import { Sparkles, Send, Loader2, Check, X, AlertTriangle } from "lucide-react";
import Button from "@/components/ui/Button";
import { getPB } from "@/lib/pocketbase";
import { useAuthStore, isAdmin } from "@/lib/store/useAuthStore";
import { WRITE_TOOLS } from "@/lib/agente/schema";
import { EXECUTORS, describeAction } from "@/lib/agente/executors";

type ToolCall = { id: string; type: string; function: { name: string; arguments: string } };
type Msg = {
  role: "user" | "assistant" | "tool";
  content?: string | null;
  tool_calls?: ToolCall[];
  tool_call_id?: string;
};
type Pending = { msgs: Msg[]; readResults: Msg[]; writes: ToolCall[] };

const SUGERENCIAS = [
  "¿Qué tengo hoy?",
  "¿Cómo viene la caja este mes?",
  "¿Qué pedidos están atrasados?",
  "Agendá medición mañana 10hs para el pedido 2605-0420",
];

function parseArgs(tc: ToolCall): Record<string, unknown> {
  try {
    return JSON.parse(tc.function.arguments || "{}");
  } catch {
    return {};
  }
}

async function runTool(tc: ToolCall): Promise<string> {
  const fn = EXECUTORS[tc.function.name];
  if (!fn) return `Herramienta desconocida: ${tc.function.name}`;
  try {
    return await fn(parseArgs(tc));
  } catch (e) {
    return `Error al ejecutar ${tc.function.name}: ${(e as Error).message}`;
  }
}

export default function AgentePanel({ onClose }: { onClose?: () => void }) {
  const user = useAuthStore((s) => s.user);
  const [messages, setMessages] = useState<Msg[]>([]);
  const [input, setInput] = useState("");
  const [busy, setBusy] = useState(false);
  const [pending, setPending] = useState<Pending | null>(null);
  const [err, setErr] = useState("");
  const scrollRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" });
  }, [messages, busy, pending]);

  if (user && !isAdmin(user)) return null;

  async function callRoute(msgs: Msg[]): Promise<{ message?: Msg; error?: string }> {
    const token = getPB().authStore.token;
    const r = await fetch("/api/agente", {
      method: "POST",
      headers: { "Content-Type": "application/json", Authorization: token },
      body: JSON.stringify({ messages: msgs }),
    });
    const data = await r.json().catch(() => ({}));
    if (!r.ok) return { error: data?.error || `Error ${r.status}` };
    return { message: data.message as Msg };
  }

  async function advance(initial: Msg[]) {
    let msgs = initial;
    setBusy(true);
    setErr("");
    try {
      for (let i = 0; i < 8; i++) {
        const { message, error } = await callRoute(msgs);
        if (error) {
          setErr(error);
          return;
        }
        if (!message) return;
        msgs = [...msgs, message];
        setMessages(msgs);

        const calls = message.tool_calls || [];
        if (!calls.length) return; // respuesta final

        const reads = calls.filter((c) => !WRITE_TOOLS.has(c.function.name));
        const writes = calls.filter((c) => WRITE_TOOLS.has(c.function.name));

        const readResults: Msg[] = [];
        for (const c of reads) {
          readResults.push({ role: "tool", tool_call_id: c.id, content: await runTool(c) });
        }

        if (writes.length) {
          setPending({ msgs, readResults, writes }); // pausa para confirmar
          return;
        }

        msgs = [...msgs, ...readResults];
        setMessages(msgs);
      }
      setErr("Demasiados pasos seguidos, frené para no colgarme. Probá de nuevo.");
    } finally {
      setBusy(false);
    }
  }

  async function resolveWrites(approved: boolean) {
    if (!pending) return;
    const { msgs, readResults, writes } = pending;
    setPending(null);
    setBusy(true);
    const writeResults: Msg[] = [];
    for (const c of writes) {
      const content = approved
        ? await runTool(c)
        : "El usuario canceló esta acción. No se ejecutó.";
      writeResults.push({ role: "tool", tool_call_id: c.id, content });
    }
    setBusy(false);
    await advance([...msgs, ...readResults, ...writeResults]);
  }

  async function send(text?: string) {
    const msg = (text ?? input).trim();
    if (!msg || busy || pending) return;
    setInput("");
    await advance([...messages, { role: "user", content: msg }]);
  }

  return (
    <div className="flex h-full flex-col">
      {/* Header */}
      <div className="flex items-center gap-2.5 border-b border-line px-4 py-3">
        <div className="grid h-9 w-9 place-items-center rounded-xl bg-gradient-to-br from-violet-500 to-fuchsia-500 text-white shadow-sm">
          <Sparkles className="h-5 w-5" />
        </div>
        <div className="flex-1 leading-tight">
          <h2 className="text-base font-extrabold text-ink">Richard</h2>
          <p className="text-[11px] text-ink-soft">Asistente de IA · consultá y cargá cosas hablando</p>
        </div>
        {onClose && (
          <button
            onClick={onClose}
            aria-label="Cerrar"
            className="grid h-8 w-8 place-items-center rounded-lg text-faint transition-colors hover:bg-canvas hover:text-ink"
          >
            <X size={18} />
          </button>
        )}
      </div>

      {/* Mensajes */}
      <div ref={scrollRef} className="flex-1 space-y-3 overflow-y-auto bg-canvas/40 p-4">
        {messages.length === 0 && !busy && (
          <div className="grid h-full place-items-center text-center">
            <div className="max-w-md">
              <div className="mx-auto mb-3 grid h-12 w-12 place-items-center rounded-2xl bg-gradient-to-br from-violet-500/15 to-fuchsia-500/15">
                <Sparkles className="h-7 w-7 text-violet-500" />
              </div>
              <p className="mb-4 text-sm text-ink-soft">Preguntame o pedime algo. Por ejemplo:</p>
              <div className="flex flex-col gap-2">
                {SUGERENCIAS.map((s) => (
                  <button
                    key={s}
                    onClick={() => send(s)}
                    className="rounded-xl border border-line bg-surface px-3 py-2 text-left text-sm text-ink hover:border-brand"
                  >
                    {s}
                  </button>
                ))}
              </div>
            </div>
          </div>
        )}

        {messages.map((m, i) => <MessageRow key={i} m={m} />)}

        {busy && (
          <div className="flex items-center gap-2 text-sm text-faint">
            <Loader2 size={15} className="animate-spin" /> Richard está pensando…
          </div>
        )}

        {pending && (
          <div className="rounded-xl border border-amber-300 bg-amber-50 p-3">
            <div className="mb-2 flex items-center gap-2 text-sm font-bold text-amber-800">
              <AlertTriangle size={15} /> Confirmá antes de escribir en la base:
            </div>
            <ul className="mb-3 space-y-1.5">
              {pending.writes.map((w) => (
                <li key={w.id} className="whitespace-pre-wrap rounded-lg border border-amber-200 bg-surface px-3 py-2 text-sm text-ink">
                  {describeAction(w.function.name, parseArgs(w))}
                </li>
              ))}
            </ul>
            <div className="flex justify-end gap-2">
              <Button type="button" variant="ghost" onClick={() => resolveWrites(false)}>
                <X size={15} /> Cancelar
              </Button>
              <Button type="button" onClick={() => resolveWrites(true)}>
                <Check size={15} /> Confirmar y ejecutar
              </Button>
            </div>
          </div>
        )}

        {err && <div className="rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-sm text-bad">{err}</div>}
      </div>

      {/* Input */}
      <div className="flex items-end gap-2 border-t border-line p-3">
        <textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              send();
            }
          }}
          rows={1}
          placeholder="Escribile a Richard…  (Enter para enviar)"
          disabled={!!pending}
          className="flex-1 resize-none rounded-xl border border-line bg-surface px-3 py-2.5 text-sm text-ink outline-none focus:border-brand disabled:opacity-50"
        />
        <Button type="button" onClick={() => send()} loading={busy} disabled={!input.trim() || !!pending}>
          <Send size={16} />
        </Button>
      </div>
    </div>
  );
}

function MessageRow({ m }: { m: Msg }) {
  if (m.role === "tool") return null;

  if (m.role === "user") {
    return (
      <div className="flex justify-end">
        <div className="max-w-[80%] whitespace-pre-wrap rounded-2xl rounded-br-sm bg-brand px-3.5 py-2 text-sm text-white">
          {m.content}
        </div>
      </div>
    );
  }

  // assistant
  const hasText = !!(m.content && m.content.trim());
  const toolNames = (m.tool_calls || []).map((c) => c.function.name);
  return (
    <div className="flex flex-col items-start gap-1">
      {hasText && (
        <div className="max-w-[85%] whitespace-pre-wrap rounded-2xl rounded-bl-sm border border-line bg-surface px-3.5 py-2 text-sm text-ink">
          {m.content}
        </div>
      )}
      {!hasText && toolNames.length > 0 && (
        <div className="text-xs text-faint">🔧 consultando: {toolNames.join(", ")}</div>
      )}
    </div>
  );
}
