"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { CheckCircle2, Plug, Plus, Search, Trash2, XCircle, Zap } from "lucide-react";
import { useMemo, useState } from "react";
import { ConnectorIcon } from "@/components/connector-icon";
import { Modal } from "@/components/modal";
import { PageHeader } from "@/components/page-header";
import { StatusPill } from "@/components/status";
import { Badge, Button, EmptyState, Field, Input, Mono, Panel, PageLoader } from "@/components/ui";
import { api, ApiError } from "@/lib/api";
import type { ConnectorType } from "@/lib/types";
import { can, useAuth } from "@/lib/auth";

interface JsonSchema {
  properties?: Record<string, { type?: string; description?: string }>;
  required?: string[];
}

function SchemaFields({
  schema,
  values,
  onChange,
  secret,
}: {
  schema: JsonSchema;
  values: Record<string, string>;
  onChange: (k: string, v: string) => void;
  secret?: boolean;
}) {
  const props = schema.properties ?? {};
  const required = new Set(schema.required ?? []);
  return (
    <>
      {Object.entries(props).map(([key, def]) => (
        <Field key={key} label={`${key}${required.has(key) ? " *" : ""}`} hint={def.description}>
          <Input
            type={secret ? "password" : def.type === "integer" ? "number" : "text"}
            required={required.has(key)}
            value={values[key] ?? ""}
            onChange={(e) => onChange(key, e.target.value)}
          />
        </Field>
      ))}
    </>
  );
}

function InstallWizard({ types, onClose }: { types: ConnectorType[]; onClose: () => void }) {
  const qc = useQueryClient();
  const [type, setType] = useState<ConnectorType | null>(null);
  const [name, setName] = useState("");
  const [config, setConfig] = useState<Record<string, string>>({});
  const [secrets, setSecrets] = useState<Record<string, string>>({});
  const [error, setError] = useState<string | null>(null);
  const [q, setQ] = useState("");

  const filtered = useMemo(() => {
    const needle = q.trim().toLowerCase();
    if (!needle) return types;
    return types.filter((t) =>
      `${t.title} ${t.type} ${t.tools.join(" ")}`.toLowerCase().includes(needle)
    );
  }, [types, q]);

  const install = useMutation({
    mutationFn: () => {
      const num = (schema: JsonSchema, vals: Record<string, string>) => {
        const out: Record<string, unknown> = {};
        for (const [k, v] of Object.entries(vals)) {
          if (v === "") continue;
          out[k] = schema.properties?.[k]?.type === "integer" ? Number(v) : v;
        }
        return out;
      };
      return api.installConnector(
        type!.type,
        name || type!.title,
        num(type!.config_schema as JsonSchema, config),
        num(type!.secret_schema as JsonSchema, secrets)
      );
    },
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["connectors"] });
      onClose();
    },
    onError: (e) => setError(e instanceof ApiError ? e.message : "Install failed"),
  });

  return (
    <Modal
      open
      onClose={onClose}
      title="Install a connector"
      description="Credentials are encrypted at rest and never returned."
    >
      {!type ? (
        <div className="space-y-3">
          <div className="relative">
            <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-faint" />
            <Input
              autoFocus
              value={q}
              onChange={(e) => setQ(e.target.value)}
              placeholder="Search connectors…"
              className="pl-9"
            />
          </div>
          <div className="grid max-h-[52vh] gap-2 overflow-y-auto pr-1 sm:grid-cols-2">
            {filtered.map((t) => (
              <button
                key={t.type}
                onClick={() => setType(t)}
                className="flex items-start gap-3 rounded-xl border border-line p-3 text-left transition-colors hover:border-accent/50 hover:bg-surface-2/40"
              >
                <ConnectorIcon type={t.type} />
                <span className="min-w-0 flex-1">
                  <span className="block font-display font-semibold text-fg">{t.title}</span>
                  <span className="mt-1 flex flex-wrap gap-1">
                    {t.tools.slice(0, 3).map((tool) => (
                      <Mono key={tool} className="text-faint">
                        {tool}
                      </Mono>
                    ))}
                    {t.tools.length > 3 && (
                      <Mono className="text-faint">+{t.tools.length - 3}</Mono>
                    )}
                  </span>
                </span>
              </button>
            ))}
            {filtered.length === 0 && (
              <p className="col-span-full py-8 text-center text-sm text-muted">
                No connectors match “{q}”.
              </p>
            )}
          </div>
        </div>
      ) : (
        <form
          className="space-y-4"
          onSubmit={(e) => {
            e.preventDefault();
            setError(null);
            install.mutate();
          }}
        >
          <div className="flex items-center gap-3">
            <ConnectorIcon type={type.type} />
            <span className="font-display font-semibold text-fg">{type.title}</span>
            <button
              type="button"
              onClick={() => setType(null)}
              className="ml-auto text-xs text-muted hover:text-fg"
            >
              change
            </button>
          </div>
          <Field label="Name">
            <Input
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder={type.title}
            />
          </Field>
          <SchemaFields
            schema={type.config_schema as JsonSchema}
            values={config}
            onChange={(k, v) => setConfig((c) => ({ ...c, [k]: v }))}
          />
          <div className="eyebrow pt-2">Secrets</div>
          <SchemaFields
            schema={type.secret_schema as JsonSchema}
            values={secrets}
            onChange={(k, v) => setSecrets((c) => ({ ...c, [k]: v }))}
            secret
          />
          {error && (
            <div className="rounded-lg border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">
              {error}
            </div>
          )}
          <div className="flex justify-end gap-2 pt-2">
            <Button type="button" variant="ghost" onClick={onClose}>
              Cancel
            </Button>
            <Button type="submit" variant="primary" loading={install.isPending}>
              Install connector
            </Button>
          </div>
        </form>
      )}
    </Modal>
  );
}

export default function ConnectorsPage() {
  const { role } = useAuth();
  const qc = useQueryClient();
  const connectors = useQuery({ queryKey: ["connectors"], queryFn: api.listConnectors });
  const types = useQuery({ queryKey: ["connector-types"], queryFn: api.listConnectorTypes });
  const [wizard, setWizard] = useState(false);
  const [testing, setTesting] = useState<string | null>(null);
  const [tested, setTested] = useState<Record<string, { ok: boolean; message: string }>>({});

  const runTest = async (id: string) => {
    setTesting(id);
    try {
      const res = await api.testConnector(id);
      setTested((t) => ({ ...t, [id]: { ok: res.ok, message: res.message } }));
      await qc.invalidateQueries({ queryKey: ["connectors"] });
    } finally {
      setTesting(null);
    }
  };

  return (
    <div>
      <PageHeader
        eyebrow="Build"
        title="Connectors"
        description="Real-world tools your agents can act through: Slack, HTTP, email, and more."
        actions={
          can(role, "connectors") && (
            <Button variant="primary" onClick={() => setWizard(true)}>
              <Plus className="h-4 w-4" /> Add connector
            </Button>
          )
        }
      />

      {connectors.isLoading ? (
        <PageLoader />
      ) : (connectors.data ?? []).length === 0 ? (
        <EmptyState
          icon={<Plug className="h-8 w-8" />}
          title="No connectors installed"
          description="Install a connector to let your agents post to Slack, call APIs, or send email."
          action={
            can(role, "connectors") && (
              <Button variant="primary" onClick={() => setWizard(true)}>
                <Plus className="h-4 w-4" /> Add connector
              </Button>
            )
          }
        />
      ) : (
        <div className="grid gap-4 sm:grid-cols-2">
          {(connectors.data ?? []).map((c) => (
            <Panel key={c.id}>
              <div className="flex items-start justify-between">
                <div className="flex items-start gap-3">
                  <ConnectorIcon type={c.type} className="h-10 w-10" />
                  <div>
                    <div className="flex items-center gap-2">
                      <span className="font-display text-lg font-semibold text-fg">{c.name}</span>
                      <Badge tone="accent">{c.type}</Badge>
                    </div>
                    <div className="mt-1">
                      <StatusPill status={c.status} />
                    </div>
                  </div>
                </div>
                {can(role, "connectors") && (
                  <button
                    onClick={async () => {
                      if (!confirm("Remove this connector?")) return;
                      await api.deleteConnector(c.id);
                      await qc.invalidateQueries({ queryKey: ["connectors"] });
                    }}
                    className="rounded-lg p-2 text-faint hover:bg-surface-2 hover:text-danger"
                  >
                    <Trash2 className="h-4 w-4" />
                  </button>
                )}
              </div>
              {(tested[c.id] || c.status_detail) && (
                <p className="mt-3 flex items-center gap-1.5 text-xs text-muted">
                  {(tested[c.id]?.ok ?? c.status === "ok") ? (
                    <CheckCircle2 className="h-3.5 w-3.5 text-success" />
                  ) : (
                    <XCircle className="h-3.5 w-3.5 text-danger" />
                  )}
                  {tested[c.id]?.message ?? c.status_detail}
                </p>
              )}
              {can(role, "connectors") && (
                <div className="mt-4 border-t border-line pt-4">
                  <Button
                    size="sm"
                    variant="outline"
                    loading={testing === c.id}
                    onClick={() => runTest(c.id)}
                  >
                    <Zap className="h-3.5 w-3.5" /> Test connection
                  </Button>
                </div>
              )}
            </Panel>
          ))}
        </div>
      )}

      {wizard && <InstallWizard types={types.data ?? []} onClose={() => setWizard(false)} />}
    </div>
  );
}
