import { ApiError } from "../../api/client";
import type { BulkRemoveItem } from "../../api/types";
import { ConfirmDialog } from "../../components/ui/ConfirmDialog";
import { useToast } from "../../components/ui/toast-context";
import { useBulkRemoveMachines } from "./hooks";

interface BulkRemoveMachinesDialogProps {
  /** Selected agent_ids to remove, or empty when the dialog is closed. */
  agentIds: string[];
  /** Whether the dialog is open. Kept explicit so an empty list can stay open. */
  open: boolean;
  onClose: () => void;
  /** Called after a successful batch so the page can clear its selection. */
  onRemoved: () => void;
}

/** Count outcomes by status for a compact "12 removed, 1 not found" summary. */
function summarize(results: BulkRemoveItem[]): string {
  const counts = new Map<string, number>();
  for (const r of results) counts.set(r.status, (counts.get(r.status) ?? 0) + 1);
  const order = ["removed", "not_found", "invalid", "error"];
  const labels: Record<string, string> = {
    removed: "removed",
    not_found: "not found",
    invalid: "invalid",
    error: "errored",
  };
  const parts: string[] = [];
  for (const status of order) {
    const n = counts.get(status);
    if (n) parts.push(`${n} ${labels[status] ?? status}`);
  }
  // Surface any unexpected status the server may add in the future.
  for (const [status, n] of counts) {
    if (!order.includes(status)) parts.push(`${n} ${status}`);
  }
  return parts.join(", ");
}

/**
 * Confirm + bulk-remove the selected machines (Task 5). On confirm the selected
 * agent_ids are purged in one request; the per-id summary the server returns is
 * surfaced as a toast (e.g. "12 removed, 1 not found") so a partial outcome is
 * visible rather than silently swallowed.
 */
export function BulkRemoveMachinesDialog({
  agentIds,
  open,
  onClose,
  onRemoved,
}: BulkRemoveMachinesDialogProps) {
  const toast = useToast();
  const bulkRemove = useBulkRemoveMachines();
  const count = agentIds.length;

  function onConfirm() {
    if (count === 0) {
      onClose();
      return;
    }
    bulkRemove.mutate(agentIds, {
      onSuccess: (res) => {
        const summary = summarize(res.results);
        if (res.removed === res.requested) {
          toast.success(
            `Removed ${res.removed} ${res.removed === 1 ? "machine" : "machines"}`,
            summary || undefined,
          );
        } else {
          // Partial: some ids were not found / invalid. Report as info, not an
          // error — the requested removals that could happen, did.
          toast.info(
            `Removed ${res.removed} of ${res.requested}`,
            summary || undefined,
          );
        }
        onRemoved();
        onClose();
      },
      onError: (err) => {
        toast.error(
          "Could not remove machines",
          err instanceof ApiError
            ? `${err.message}${err.code ? ` (${err.code})` : ""}`
            : "The server did not respond. No machines were removed.",
        );
      },
    });
  }

  return (
    <ConfirmDialog
      open={open}
      title={`Remove ${count} ${count === 1 ? "machine" : "machines"}?`}
      danger
      busy={bulkRemove.isPending}
      confirmLabel={`Remove ${count}`}
      cancelLabel="Keep machines"
      onConfirm={onConfirm}
      onCancel={onClose}
      body={
        <p style={{ marginTop: 0 }}>
          Remove the {count} selected{" "}
          {count === 1 ? "machine" : "machines"} from the GuruConnect console.
          Their live sessions are dropped and the rows disappear from the list.
          Any that are genuinely still in service re-appear when their agents
          next check in.
        </p>
      }
    />
  );
}
