import { useCallback, useEffect, useState } from "react";
import { Button, Icon, SettingsCard, StatusBadge, TextField } from "@nodedc/ui-react";

interface FoundryAgentDevice {
  id: string;
  name: string;
  createdAt: string;
  lastUsedAt: string | null;
  lastCheckAt: string | null;
  revokedAt: string | null;
}

interface FoundryAgent {
  id: string;
  name: string;
  avatarUrl: string | null;
  status: "active" | "revoked";
  devices: FoundryAgentDevice[];
  deviceCount: number;
  lastUsedAt: string | null;
  lastCheckAt: string | null;
  createdAt: string;
  updatedAt: string;
}

interface SetupCommand {
  command: string;
  expiresAt: string;
}

async function api<T>(pathname: string, init?: RequestInit): Promise<T> {
  const response = await fetch(pathname, {
    cache: "no-store",
    ...init,
    headers: {
      accept: "application/json",
      ...(init?.body ? { "content-type": "application/json" } : {}),
      ...init?.headers,
    },
  });
  const payload = await response.json().catch(() => ({}));
  if (!response.ok || payload?.ok === false) throw new Error(payload?.error || `foundry_agent_api_${response.status}`);
  return payload as T;
}

function formatMoment(value: string | null) {
  if (!value) return "—";
  const date = new Date(value);
  return Number.isFinite(date.getTime()) ? date.toLocaleString("ru-RU") : value;
}

export function FoundryCodexAgentSettings() {
  const [agents, setAgents] = useState<FoundryAgent[]>([]);
  const [newAgentName, setNewAgentName] = useState("Foundry Codex");
  const [draftNames, setDraftNames] = useState<Record<string, string>>({});
  const [setupByAgent, setSetupByAgent] = useState<Record<string, SetupCommand>>({});
  const [loading, setLoading] = useState(true);
  const [pending, setPending] = useState("");
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");

  const load = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const payload = await api<{ agents: FoundryAgent[] }>("/api/foundry-agent-api/agents");
      setAgents(payload.agents);
      setDraftNames(Object.fromEntries(payload.agents.map((agent) => [agent.id, agent.name])));
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : "foundry_agent_load_failed");
    } finally {
      setLoading(false);
    }
  }, []);

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

  const run = async (key: string, action: () => Promise<void>) => {
    setPending(key);
    setError("");
    setMessage("");
    try {
      await action();
    } catch (actionError) {
      setError(actionError instanceof Error ? actionError.message : "foundry_agent_operation_failed");
    } finally {
      setPending("");
    }
  };

  const createAgent = () => run("create", async () => {
    const payload = await api<{ agent: FoundryAgent }>("/api/foundry-agent-api/agents", {
      method: "POST",
      body: JSON.stringify({ name: newAgentName.trim() || "Foundry Codex" }),
    });
    setAgents((current) => [payload.agent, ...current]);
    setDraftNames((current) => ({ ...current, [payload.agent.id]: payload.agent.name }));
    setMessage("Foundry Agent создан. Теперь можно получить одноразовую setup-команду.");
  });

  const saveAgent = (agent: FoundryAgent) => run(`save:${agent.id}`, async () => {
    const payload = await api<{ agent: FoundryAgent }>(`/api/foundry-agent-api/agents/${encodeURIComponent(agent.id)}`, {
      method: "PATCH",
      body: JSON.stringify({ name: draftNames[agent.id]?.trim() || agent.name }),
    });
    setAgents((current) => current.map((item) => item.id === agent.id ? payload.agent : item));
    setMessage("Имя агента сохранено.");
  });

  const revokeAgent = (agent: FoundryAgent) => run(`revoke:${agent.id}`, async () => {
    const payload = await api<{ agent: FoundryAgent }>(`/api/foundry-agent-api/agents/${encodeURIComponent(agent.id)}/revoke`, {
      method: "POST",
      body: "{}",
    });
    setAgents((current) => current.map((item) => item.id === agent.id ? payload.agent : item));
    setSetupByAgent((current) => {
      const next = { ...current };
      delete next[agent.id];
      return next;
    });
    setMessage("Agent отозван. Foundry и Ontology credentials этого агента больше не принимаются.");
  });

  const issueSetup = (agent: FoundryAgent) => run(`setup:${agent.id}`, async () => {
    const payload = await api<{ install: SetupCommand }>(`/api/foundry-agent-api/agents/${encodeURIComponent(agent.id)}/setup-code`, {
      method: "POST",
      body: "{}",
    });
    setSetupByAgent((current) => ({ ...current, [agent.id]: payload.install }));
    setMessage("Одноразовая команда выпущена. Она установит Foundry MCP и отдельный read-only Ontology MCP.");
  });

  const copySetup = async (agentId: string) => {
    const command = setupByAgent[agentId]?.command;
    if (!command) return;
    await navigator.clipboard.writeText(command);
    setMessage("Setup-команда скопирована.");
  };

  return (
    <div className="catalog-codex-agent-settings">
      <header className="catalog-codex-agent-settings__header">
        <div><span>NODE.DC / SOURCE-FREE DEVELOPMENT</span><h2>Codex Agent API</h2></div>
        <StatusBadge tone="success">Foundry + Ontology</StatusBadge>
      </header>
      <p className="catalog-codex-agent-settings__lead">
        Одна setup-команда добавляет в Codex два независимых MCP: полный текущий Foundry contour и отдельную read-only Ontology. Sharing, роли и межпользовательская видимость в этот срез не входят.
      </p>

      {error ? <div className="catalog-codex-agent-settings__message" data-tone="error">{error}</div> : null}
      {message ? <div className="catalog-codex-agent-settings__message" data-tone="success">{message}</div> : null}

      <SettingsCard eyebrow="NEW AGENT" title="Подключить Codex" description="Agent принадлежит текущему пользователю Foundry. Credentials долговечны до явного revoke.">
        <div className="catalog-codex-agent-settings__create">
          <TextField label="Имя агента" value={newAgentName} onChange={(event) => setNewAgentName(event.target.value)} />
          <Button variant="primary" shape="pill" icon={<Icon name="plus" />} disabled={pending === "create"} onClick={() => { void createAgent(); }}>
            {pending === "create" ? "Создание…" : "Создать агента"}
          </Button>
        </div>
      </SettingsCard>

      <div className="catalog-codex-agent-settings__agents">
        {loading ? <span className="catalog-codex-agent-settings__empty">Загружаю agents…</span> : null}
        {!loading && agents.length === 0 ? <span className="catalog-codex-agent-settings__empty">Агенты ещё не созданы.</span> : null}
        {agents.map((agent) => {
          const setup = setupByAgent[agent.id];
          const active = agent.status === "active";
          return (
            <SettingsCard
              key={agent.id}
              eyebrow={`AGENT · ${agent.deviceCount} DEVICE`}
              title={agent.name}
              description={`Последнее использование: ${formatMoment(agent.lastUsedAt)} · doctor: ${formatMoment(agent.lastCheckAt)}`}
              actions={<StatusBadge tone={active ? "success" : "danger"}>{active ? "Активен" : "Отозван"}</StatusBadge>}
            >
              <div className="catalog-codex-agent-settings__agent-grid">
                <TextField
                  label="Имя"
                  value={draftNames[agent.id] ?? agent.name}
                  disabled={!active}
                  onChange={(event) => setDraftNames((current) => ({ ...current, [agent.id]: event.target.value }))}
                />
                <div className="catalog-codex-agent-settings__actions">
                  <Button disabled={!active || pending === `save:${agent.id}`} onClick={() => { void saveAgent(agent); }}>Сохранить</Button>
                  <Button variant="primary" shape="pill" disabled={!active || pending === `setup:${agent.id}`} onClick={() => { void issueSetup(agent); }}>Получить команду</Button>
                  <Button variant="danger" disabled={!active || pending === `revoke:${agent.id}`} onClick={() => { void revokeAgent(agent); }}>Revoke</Button>
                </div>
              </div>
              {setup ? (
                <div className="catalog-codex-agent-settings__setup">
                  <div><strong>Одноразовая setup-команда</strong><small>Действует до {formatMoment(setup.expiresAt)}. После выполнения полностью перезапустите Codex Desktop.</small></div>
                  <code>{setup.command}</code>
                  <Button icon={<Icon name="copy" />} onClick={() => { void copySetup(agent.id); }}>Копировать</Button>
                </div>
              ) : null}
            </SettingsCard>
          );
        })}
      </div>
    </div>
  );
}
