"use client";

import { useQuery } from "@tanstack/react-query";
import { ChevronDown, Lock, Search } from "lucide-react";
import { useMemo, useState } from "react";
import {
  CONNECTOR_ORDER,
  ConnectorIcon,
  connectorTitle,
  toolConnectorKey,
} from "@/components/connector-icon";
import { Badge, Button, Field, Input, Select, Textarea } from "@/components/ui";
import { api } from "@/lib/api";
import type { Agent, Tool } from "@/lib/types";
import { cn } from "@/lib/utils";

export interface AgentDraft {
  name: string;
  description: string;
  provider: string;
  model: string;
  system_prompt: string;
  tools: string[];
  guardrails_json: Record<string, unknown>;
}

// Curated, beginner-friendly model choices per provider. "Custom" lets power
// users type any model id the provider supports.
const MODELS: Record<string, string[]> = {
  openrouter: [
    "openai/gpt-4o",
    "openai/gpt-4o-mini",
    "anthropic/claude-3.5-sonnet",
    "anthropic/claude-3.5-haiku",
    "google/gemini-1.5-pro",
    "meta-llama/llama-3.1-70b-instruct",
  ],
  ollama: ["llama3.1", "llama3.2", "mistral", "qwen2.5", "phi3"],
};
const CUSTOM = "__custom__";

export function AgentForm({
  initial,
  submitLabel,
  onSubmit,
  busy,
}: {
  initial?: Partial<Agent>;
  submitLabel: string;
  onSubmit: (draft: AgentDraft) => void;
  busy?: boolean;
}) {
  const tools = useQuery({ queryKey: ["tools"], queryFn: api.listTools });
  const [name, setName] = useState(initial?.name ?? "");
  const [description, setDescription] = useState(initial?.description ?? "");
  const [provider, setProvider] = useState(initial?.provider ?? "openrouter");
  const [model, setModel] = useState(initial?.model ?? "");
  const [customModel, setCustomModel] = useState(() => {
    const p = initial?.provider ?? "openrouter";
    const m = initial?.model ?? "";
    return !!m && !(MODELS[p] ?? []).includes(m);
  });
  const [prompt, setPrompt] = useState(initial?.system_prompt ?? "");
  const [selected, setSelected] = useState<string[]>(initial?.tools ?? []);
  const guard = (initial?.guardrails_json ?? {}) as Record<string, number>;
  const [maxSteps, setMaxSteps] = useState(String(guard.max_steps ?? ""));
  const [maxTokens, setMaxTokens] = useState(String(guard.max_tokens ?? ""));

  const [toolQuery, setToolQuery] = useState("");
  const [expanded, setExpanded] = useState<Set<string>>(new Set());

  const toggleExpand = (key: string) =>
    setExpanded((cur) => {
      const next = new Set(cur);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });

  const toggle = (t: string) =>
    setSelected((cur) => (cur.includes(t) ? cur.filter((x) => x !== t) : [...cur, t]));

  const toggleGroup = (names: string[], allOn: boolean) =>
    setSelected((cur) =>
      allOn ? cur.filter((n) => !names.includes(n)) : Array.from(new Set([...cur, ...names]))
    );

  const groups = useMemo(() => {
    const all = tools.data ?? [];
    const needle = toolQuery.trim().toLowerCase();
    const matched = needle
      ? all.filter((t) => `${t.name} ${t.description}`.toLowerCase().includes(needle))
      : all;
    const byKey: Record<string, Tool[]> = {};
    for (const t of matched) (byKey[toolConnectorKey(t.name)] ||= []).push(t);
    return Object.keys(byKey)
      .sort((a, b) => {
        const ia = CONNECTOR_ORDER.indexOf(a);
        const ib = CONNECTOR_ORDER.indexOf(b);
        return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib);
      })
      .map((key) => ({ key, items: byKey[key] }));
  }, [tools.data, toolQuery]);

  return (
    <form
      className="space-y-8"
      onSubmit={(e) => {
        e.preventDefault();
        const guardrails: Record<string, number> = {};
        if (maxSteps) guardrails.max_steps = Number(maxSteps);
        if (maxTokens) guardrails.max_tokens = Number(maxTokens);
        onSubmit({
          name,
          description,
          provider,
          model,
          system_prompt: prompt,
          tools: selected,
          guardrails_json: guardrails,
        });
      }}
    >
      <div className="grid gap-5 sm:grid-cols-2">
        <Field label="Name">
          <Input
            required
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="Support triage"
          />
        </Field>
        <Field label="Description">
          <Input
            value={description}
            onChange={(e) => setDescription(e.target.value)}
            placeholder="Handles inbound support requests"
          />
        </Field>
        <Field label="Provider">
          <Select
            value={provider}
            onChange={(e) => {
              setProvider(e.target.value);
              setModel("");
              setCustomModel(false);
            }}
          >
            <option value="openrouter">OpenRouter</option>
            <option value="ollama">Ollama (local)</option>
          </Select>
        </Field>
        <Field
          label="Model"
          hint={
            provider === "ollama"
              ? "Must be pulled in your Ollama instance."
              : "Pick a model, or choose Custom to enter any id."
          }
        >
          <Select
            value={
              customModel || (model && !(MODELS[provider] ?? []).includes(model)) ? CUSTOM : model
            }
            onChange={(e) => {
              if (e.target.value === CUSTOM) {
                setCustomModel(true);
              } else {
                setCustomModel(false);
                setModel(e.target.value);
              }
            }}
          >
            <option value="" disabled>
              Select a model…
            </option>
            {(MODELS[provider] ?? []).map((m) => (
              <option key={m} value={m}>
                {m}
              </option>
            ))}
            <option value={CUSTOM}>Custom…</option>
          </Select>
          {(customModel || (model && !(MODELS[provider] ?? []).includes(model))) && (
            <Input
              className="mt-2"
              value={model}
              onChange={(e) => setModel(e.target.value)}
              placeholder={provider === "ollama" ? "llama3.1" : "provider/model-id"}
            />
          )}
        </Field>
      </div>

      <Field label="System prompt" hint="Instructions only come from here, never from tool output.">
        <Textarea
          rows={5}
          value={prompt}
          onChange={(e) => setPrompt(e.target.value)}
          placeholder="You are a diligent support agent. Be concise and cite sources."
        />
      </Field>

      <div>
        <div className="flex items-start justify-between gap-3">
          <div>
            <span className="eyebrow">Tools · allow-list</span>
            <p className="mt-1 text-xs text-faint">
              The agent can only ever call tools you grant here. Sensitive tools route through
              approval.
            </p>
          </div>
          <span className="shrink-0 rounded-md border border-line px-2 py-1 font-mono text-[11px] text-muted">
            {selected.length} selected
          </span>
        </div>

        <div className="relative mt-3">
          <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-faint" />
          <Input
            value={toolQuery}
            onChange={(e) => setToolQuery(e.target.value)}
            placeholder="Search tools…"
            className="pl-9"
          />
        </div>

        <div className="mt-4 space-y-2">
          {groups.map(({ key, items }) => {
            const names = items.map((t) => t.name);
            const onCount = names.filter((n) => selected.includes(n)).length;
            const allOn = onCount === names.length;
            const open = toolQuery.trim() !== "" || expanded.has(key);
            return (
              <div key={key} className="overflow-hidden rounded-xl border border-line">
                <div className="flex items-center gap-2 px-3 py-2.5">
                  <button
                    type="button"
                    onClick={() => toggleExpand(key)}
                    className="flex min-w-0 flex-1 items-center gap-3 text-left"
                  >
                    <ConnectorIcon type={key} className="h-9 w-9" />
                    <span className="min-w-0">
                      <span className="block font-display text-sm font-semibold text-fg">
                        {connectorTitle(key)}
                      </span>
                      <span className="font-mono text-[11px]">
                        <span className={onCount > 0 ? "text-accent" : "text-faint"}>
                          {onCount}
                        </span>
                        <span className="text-faint"> of {names.length} selected</span>
                      </span>
                    </span>
                  </button>
                  <button
                    type="button"
                    onClick={() => toggleGroup(names, allOn)}
                    className="shrink-0 text-xs text-muted transition-colors hover:text-accent"
                  >
                    {allOn ? "Clear" : "Select all"}
                  </button>
                  <button
                    type="button"
                    onClick={() => toggleExpand(key)}
                    className="shrink-0 rounded-md p-1 text-faint transition-colors hover:text-fg"
                    aria-label={open ? "Collapse" : "Expand"}
                  >
                    <ChevronDown
                      className={cn("h-4 w-4 transition-transform", open && "rotate-180")}
                    />
                  </button>
                </div>
                {open && (
                  <div className="grid gap-2 border-t border-line p-3 sm:grid-cols-2">
                    {items.map((tool) => {
                      const on = selected.includes(tool.name);
                      return (
                        <button
                          type="button"
                          key={tool.name}
                          onClick={() => toggle(tool.name)}
                          className={cn(
                            "flex items-start gap-3 rounded-xl border p-3 text-left transition-colors",
                            on
                              ? "border-accent/50 bg-accent/5"
                              : "border-line hover:border-line-strong"
                          )}
                        >
                          <span
                            className={cn(
                              "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border",
                              on ? "border-accent bg-accent text-accent-fg" : "border-line-strong"
                            )}
                          >
                            {on && <span className="text-[10px] font-bold">✓</span>}
                          </span>
                          <span className="min-w-0">
                            <span className="flex items-center gap-2">
                              <span className="font-mono text-[13px] text-fg">{tool.name}</span>
                              {tool.is_sensitive && (
                                <Badge tone="accent">
                                  <Lock className="h-3 w-3" /> sensitive
                                </Badge>
                              )}
                            </span>
                            <span className="mt-0.5 block truncate text-xs text-muted">
                              {tool.description}
                            </span>
                          </span>
                        </button>
                      );
                    })}
                  </div>
                )}
              </div>
            );
          })}
          {groups.length === 0 && (
            <p className="py-6 text-center text-sm text-muted">No tools match “{toolQuery}”.</p>
          )}
        </div>
      </div>

      <div className="grid gap-5 sm:grid-cols-2">
        <Field label="Max steps" hint="Budget: reasoning turns per run.">
          <Input
            type="number"
            value={maxSteps}
            onChange={(e) => setMaxSteps(e.target.value)}
            placeholder="25"
          />
        </Field>
        <Field label="Max tokens" hint="Budget: total tokens per run.">
          <Input
            type="number"
            value={maxTokens}
            onChange={(e) => setMaxTokens(e.target.value)}
            placeholder="200000"
          />
        </Field>
      </div>

      <div className="flex justify-end gap-2 border-t border-line pt-5">
        <Button variant="primary" type="submit" loading={busy}>
          {submitLabel}
        </Button>
      </div>
    </form>
  );
}
