"use client";

import { useMemo, useState } from "react";

import { useMutation, useQuery } from "@tanstack/react-query";

import type { GatewayRead } from "@/api/generated/model";
import { ApiError } from "@/api/mutator";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  getGatewayAgentImportPreview,
  importGatewayAgents,
  type GatewayAgentImportCandidate,
  type GatewayAgentImportPreviewResponse,
  type GatewayAgentImportResponse,
} from "@/lib/api-gateway-agent-import";

type ImportMode = "import_only" | "import_and_reconcile";

type GatewayAgentImportDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  gateway: GatewayRead | null;
  onImported: (result: GatewayAgentImportResponse) => void;
};

function shortUuid(value: string | null): string {
  if (!value) {
    return "—";
  }
  return value.length > 14 ? `${value.slice(0, 6)}…${value.slice(-6)}` : value;
}

export function GatewayAgentImportDialog({
  open,
  onOpenChange,
  gateway,
  onImported,
}: GatewayAgentImportDialogProps) {
  const [manualSelectedAgentIds, setManualSelectedAgentIds] = useState<Set<string> | null>(null);
  const [importMode, setImportMode] = useState<ImportMode>("import_and_reconcile");
  const [resultMessage, setResultMessage] = useState<string | null>(null);

  const previewQuery = useQuery<GatewayAgentImportPreviewResponse, ApiError>({
    queryKey: ["gateway-agent-import-preview", gateway?.id],
    queryFn: async () => {
      if (!gateway) {
        throw new Error("Gateway is required");
      }
      return getGatewayAgentImportPreview(gateway.id);
    },
    enabled: open && Boolean(gateway?.id),
    staleTime: 0,
    refetchOnMount: "always",
  });

  const importableCandidates = useMemo(
    () =>
      (previewQuery.data?.candidates ?? []).filter(
        (candidate) => candidate.importable,
      ),
    [previewQuery.data?.candidates],
  );
  const defaultSelectedAgentIds = useMemo(
    () =>
      new Set(
        importableCandidates.map((candidate) => candidate.gateway_agent_id),
      ),
    [importableCandidates],
  );
  const selectedAgentIds = manualSelectedAgentIds ?? defaultSelectedAgentIds;

  const importMutation = useMutation<
    GatewayAgentImportResponse,
    ApiError,
    string[]
  >({
    mutationFn: async (gatewayAgentIds) => {
      if (!gateway) {
        throw new Error("Gateway is required");
      }
      return importGatewayAgents(gateway.id, {
        gateway_agent_ids: gatewayAgentIds,
        reconcile_after_import: importMode === "import_and_reconcile",
        rotate_tokens: importMode === "import_and_reconcile",
        reset_sessions: importMode === "import_and_reconcile",
        force_bootstrap: importMode === "import_and_reconcile",
      });
    },
    onSuccess: (result) => {
      const reconcileText = result.reconcile
        ? ` Reconcile updated ${result.reconcile.updated}/${result.reconcile.attempted}.`
        : "";
      setResultMessage(
        `Imported ${result.imported_count} agent${result.imported_count === 1 ? "" : "s"}.${reconcileText}`,
      );
      onImported(result);
    },
  });

  const selectedCount = selectedAgentIds.size;
  const canImport = selectedCount > 0 && !importMutation.isPending;

  const toggleCandidate = (candidate: GatewayAgentImportCandidate) => {
    if (!candidate.importable) {
      return;
    }
    setManualSelectedAgentIds((prev) => {
      const next = new Set(prev ?? selectedAgentIds);
      if (next.has(candidate.gateway_agent_id)) {
        next.delete(candidate.gateway_agent_id);
      } else {
        next.add(candidate.gateway_agent_id);
      }
      return next;
    });
  };

  const selectAllImportable = () => {
    setManualSelectedAgentIds(
      new Set(importableCandidates.map((candidate) => candidate.gateway_agent_id)),
    );
  };

  const clearSelection = () => {
    setManualSelectedAgentIds(new Set());
  };

  const handleImport = () => {
    importMutation.mutate([...selectedAgentIds]);
  };

  const handleOpenChange = (nextOpen: boolean) => {
    if (!nextOpen) {
      setManualSelectedAgentIds(null);
      setResultMessage(null);
    }
    onOpenChange(nextOpen);
  };

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      <DialogContent className="max-w-4xl">
        <DialogHeader>
          <DialogTitle>Import Existing Gateway Agents</DialogTitle>
          <DialogDescription>
            Preview gateway runtime agents for <strong>{gateway?.name}</strong>,
            then import selected entries into Pipeline.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          <div className="grid gap-3 sm:grid-cols-3">
            <div className="rounded-lg border border-border bg-muted/30 p-3 text-sm">
              <div className="text-muted-foreground">Discovered</div>
              <div className="text-base font-semibold text-foreground">
                {previewQuery.data?.discovered_count ?? 0}
              </div>
            </div>
            <div className="rounded-lg border border-border bg-muted/30 p-3 text-sm">
              <div className="text-muted-foreground">Importable</div>
              <div className="text-base font-semibold text-foreground">
                {previewQuery.data?.importable_count ?? 0}
              </div>
            </div>
            <div className="rounded-lg border border-border bg-muted/30 p-3 text-sm">
              <div className="text-muted-foreground">Already Tracked</div>
              <div className="text-base font-semibold text-foreground">
                {previewQuery.data?.already_tracked_count ?? 0}
              </div>
            </div>
          </div>

          <div className="flex flex-col gap-2 rounded-lg border border-border bg-card p-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="text-sm text-muted-foreground">
              Selected {selectedCount} of {importableCandidates.length} importable
              agents
            </div>
            <div className="flex items-center gap-2">
              <Button
                type="button"
                variant="secondary"
                size="sm"
                onClick={selectAllImportable}
              >
                Select All
              </Button>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                onClick={clearSelection}
              >
                Clear
              </Button>
            </div>
          </div>

          <div className="max-h-[360px] overflow-auto rounded-lg border border-border">
            <table className="w-full text-sm">
              <thead className="sticky top-0 bg-muted/70 text-xs uppercase text-muted-foreground">
                <tr>
                  <th className="px-3 py-2 text-left">Agent</th>
                  <th className="px-3 py-2 text-left">Session</th>
                  <th className="px-3 py-2 text-left">Board</th>
                  <th className="px-3 py-2 text-left">Status</th>
                  <th className="px-3 py-2 text-right">Select</th>
                </tr>
              </thead>
              <tbody>
                {previewQuery.isLoading ? (
                  <tr>
                    <td colSpan={5} className="px-3 py-6 text-center text-muted-foreground">
                      Loading import preview…
                    </td>
                  </tr>
                ) : previewQuery.error ? (
                  <tr>
                    <td colSpan={5} className="px-3 py-6 text-center text-red-500">
                      {previewQuery.error.message}
                    </td>
                  </tr>
                ) : previewQuery.data?.candidates.length ? (
                  previewQuery.data.candidates.map((candidate) => {
                    const isSelected = selectedAgentIds.has(
                      candidate.gateway_agent_id,
                    );
                    return (
                      <tr
                        key={candidate.gateway_agent_id}
                        className="border-t border-border"
                      >
                        <td className="px-3 py-2">
                          <div className="font-medium text-foreground">
                            {candidate.gateway_agent_name ?? candidate.gateway_agent_id}
                          </div>
                          <div className="text-xs text-muted-foreground">
                            {candidate.gateway_agent_id}
                          </div>
                        </td>
                        <td className="px-3 py-2 text-xs text-muted-foreground">
                          {candidate.session_key ?? "—"}
                        </td>
                        <td className="px-3 py-2 text-xs text-muted-foreground">
                          {shortUuid(candidate.inferred_board_id)}
                        </td>
                        <td className="px-3 py-2">
                          {candidate.importable ? (
                            <Badge variant="outline">Importable</Badge>
                          ) : (
                            <Badge>Tracked</Badge>
                          )}
                        </td>
                        <td className="px-3 py-2 text-right">
                          {candidate.importable ? (
                            <Button
                              type="button"
                              size="sm"
                              variant={isSelected ? "primary" : "secondary"}
                              onClick={() => toggleCandidate(candidate)}
                            >
                              {isSelected ? "Selected" : "Select"}
                            </Button>
                          ) : (
                            <span className="text-xs text-muted-foreground">
                              —
                            </span>
                          )}
                        </td>
                      </tr>
                    );
                  })
                ) : (
                  <tr>
                    <td colSpan={5} className="px-3 py-6 text-center text-muted-foreground">
                      No gateway agents found.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          <div className="grid gap-2 sm:max-w-sm">
            <label className="text-sm font-medium text-foreground">Import Mode</label>
            <Select
              value={importMode}
              onValueChange={(value) => setImportMode(value as ImportMode)}
            >
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="import_and_reconcile">
                  Import + Reconcile
                </SelectItem>
                <SelectItem value="import_only">Import Only</SelectItem>
              </SelectContent>
            </Select>
            <p className="text-xs text-muted-foreground">
              Reconcile rotates tokens and pushes templates so imported agents can
              check in with Pipeline auth.
            </p>
          </div>

          {resultMessage ? (
            <p className="text-sm text-foreground">{resultMessage}</p>
          ) : null}
          {importMutation.error ? (
            <p className="text-sm text-red-500">{importMutation.error.message}</p>
          ) : null}
        </div>

        <DialogFooter>
          <Button
            type="button"
            variant="ghost"
            onClick={() => handleOpenChange(false)}
          >
            Close
          </Button>
          <Button type="button" onClick={handleImport} disabled={!canImport}>
            {importMutation.isPending ? "Importing…" : "Import Selected"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
