// src/components/settings/api-keys-manager.tsx — Clés API settings UI.
// Per-user management of MCP API keys: any org member manages their OWN keys.
// Super-admins also see the org-level add-on entitlement toggle. The clear key
// is shown ONCE after creation and never re-displayed.
"use client";

import { CheckIcon, CopyIcon, KeyIcon } from "lucide-react";
import Link from "next/link";
import { useState, useTransition } from "react";
import { toast } from "sonner";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import {
  createApiKeyAction,
  revokeApiKeyAction,
  setOrgAddonAction,
} from "@/lib/mcp/keys-actions";

const ADDON = "checklist_mcp";

type ApiKey = {
  id: string;
  name: string;
  prefix: string;
  createdAt: Date;
  lastUsedAt: Date | null;
  revokedAt: Date | null;
  requestCount: number;
};

function CopyButton({ value, label }: { value: string; label?: string }) {
  const [copied, setCopied] = useState(false);
  return (
    <Button
      type="button"
      variant="outline"
      size="sm"
      className="shrink-0"
      onClick={async () => {
        await navigator.clipboard.writeText(value);
        setCopied(true);
        toast.success("Copié");
        setTimeout(() => setCopied(false), 1500);
      }}
    >
      {copied ? (
        <CheckIcon data-icon="inline-start" />
      ) : (
        <CopyIcon data-icon="inline-start" />
      )}
      {label ?? "Copier"}
    </Button>
  );
}

function fmtDate(d: Date | null): string {
  if (!d) return "—";
  return new Date(d).toLocaleDateString("fr-FR", {
    year: "numeric",
    month: "short",
    day: "numeric",
  });
}

const RELATIVE = new Intl.RelativeTimeFormat("fr-FR", { numeric: "auto" });
const RELATIVE_UNITS: [Intl.RelativeTimeFormatUnit, number][] = [
  ["year", 1000 * 60 * 60 * 24 * 365],
  ["month", 1000 * 60 * 60 * 24 * 30],
  ["day", 1000 * 60 * 60 * 24],
  ["hour", 1000 * 60 * 60],
  ["minute", 1000 * 60],
];

/** « utilisée il y a … » for a date, « jamais utilisée » when null. */
function fmtLastUsed(d: Date | null): string {
  if (!d) return "jamais utilisée";
  const diff = new Date(d).getTime() - Date.now();
  const abs = Math.abs(diff);
  for (const [unit, ms] of RELATIVE_UNITS) {
    if (abs >= ms) {
      return `utilisée ${RELATIVE.format(Math.round(diff / ms), unit)}`;
    }
  }
  return "utilisée à l'instant";
}

export function ApiKeysManager({
  isMember,
  enabled,
  isSuperAdmin,
  orgId,
  appUrl,
  initialKeys,
}: {
  isMember: boolean;
  enabled: boolean;
  isSuperAdmin: boolean;
  orgId: string;
  appUrl: string;
  initialKeys: ApiKey[];
}) {
  const [keys, setKeys] = useState<ApiKey[]>(initialKeys);
  const [addonEnabled, setAddonEnabled] = useState(enabled);
  const [createOpen, setCreateOpen] = useState(false);
  const [name, setName] = useState("");
  const [newKey, setNewKey] = useState<string | null>(null);
  const [pending, startTransition] = useTransition();

  const activeCount = keys.filter((k) => k.revokedAt == null).length;
  const mcpUrl = `${appUrl.replace(/\/$/, "")}/api/mcp`;
  const clientConfig = JSON.stringify(
    {
      mcpServers: {
        "seo-insight": {
          url: mcpUrl,
          headers: { Authorization: "Bearer eli_…" },
        },
      },
    },
    null,
    2,
  );

  function toggleAddon(next: boolean) {
    startTransition(async () => {
      try {
        await setOrgAddonAction(orgId, ADDON, next);
        setAddonEnabled(next);
        toast.success(next ? "Add-on activé" : "Add-on désactivé");
      } catch {
        toast.error("Impossible de mettre à jour l'add-on");
      }
    });
  }

  function createKey() {
    startTransition(async () => {
      try {
        const { id, key } = await createApiKeyAction(name);
        setNewKey(key);
        setKeys((prev) => [
          ...prev,
          {
            id,
            name: name.trim(),
            prefix: `eli_${key.slice(4, 8)}`,
            createdAt: new Date(),
            lastUsedAt: null,
            revokedAt: null,
            requestCount: 0,
          },
        ]);
        setName("");
      } catch (e) {
        toast.error(
          e instanceof Error ? e.message : "Impossible de créer la clé",
        );
      }
    });
  }

  // Confirmation de révocation via AlertDialog shadcn (jamais de confirm() natif).
  const [revokeTarget, setRevokeTarget] = useState<string | null>(null);

  function confirmRevoke() {
    const id = revokeTarget;
    if (!id) return;
    setRevokeTarget(null);
    startTransition(async () => {
      try {
        await revokeApiKeyAction(id);
        setKeys((prev) =>
          prev.map((k) => (k.id === id ? { ...k, revokedAt: new Date() } : k)),
        );
        toast.success("Clé révoquée");
      } catch {
        toast.error("Impossible de révoquer la clé");
      }
    });
  }

  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-col gap-1">
        <h1 className="font-semibold text-xl">Clés API</h1>
        <p className="text-muted-foreground text-sm">
          Connecte tes agents IA à SEO Insight via le serveur MCP.
        </p>
      </div>

      {isSuperAdmin && (
        <Card>
          <CardHeader>
            <CardTitle>Entitlement (god-mode)</CardTitle>
            <CardDescription>
              Réservé aux super-admins. Active l'add-on Checklist MCP pour cette
              organisation.
            </CardDescription>
          </CardHeader>
          <CardContent>
            <div className="flex items-center justify-between gap-4">
              <label htmlFor="addon-toggle" className="font-medium text-sm">
                Add-on Checklist MCP activé
              </label>
              <Switch
                id="addon-toggle"
                checked={addonEnabled}
                disabled={pending}
                onCheckedChange={toggleAddon}
              />
            </div>
          </CardContent>
        </Card>
      )}

      {!isMember ? (
        <Card>
          <CardContent className="py-6 text-muted-foreground text-sm">
            Rejoins une organisation pour gérer tes clés API.
          </CardContent>
        </Card>
      ) : !addonEnabled ? (
        <Card>
          <CardContent className="flex flex-col items-start gap-3 py-6 text-muted-foreground text-sm">
            <p>
              Le serveur MCP est inclus dès le plan Solo. Passe sur un plan
              payant pour activer l'add-on Checklist MCP sur ton organisation.
            </p>
            <Button asChild size="sm">
              <Link href="/settings/billing">Voir les plans</Link>
            </Button>
          </CardContent>
        </Card>
      ) : (
        <>
          <Card>
            <CardHeader>
              <CardTitle>Serveur MCP</CardTitle>
              <CardDescription>
                Configure ton client MCP avec cette URL et une clé API en
                bearer.
              </CardDescription>
            </CardHeader>
            <CardContent className="flex flex-col gap-4">
              <div className="flex flex-col gap-2">
                <span className="font-medium text-sm">URL du serveur</span>
                <div className="flex items-center gap-2">
                  <code className="flex-1 truncate rounded-md bg-muted px-3 py-2 font-mono text-sm">
                    {mcpUrl}
                  </code>
                  <CopyButton value={mcpUrl} />
                </div>
              </div>
              <div className="flex flex-col gap-2">
                <span className="font-medium text-sm">
                  Exemple de configuration client
                </span>
                <pre className="overflow-x-auto rounded-md bg-muted px-3 py-2 font-mono text-xs">
                  {clientConfig}
                </pre>
                <div>
                  <CopyButton value={clientConfig} label="Copier la config" />
                </div>
              </div>
              <div className="flex flex-col gap-2 border-t pt-4 text-muted-foreground text-xs">
                <p>
                  <span className="font-medium text-foreground">
                    Claude Desktop
                  </span>{" "}
                  n'accepte pas encore de header natif : passe par le pont{" "}
                  <code className="rounded bg-muted px-1 py-0.5 font-mono">
                    npx mcp-remote {mcpUrl} --header "Authorization: Bearer
                    eli_…"
                  </code>{" "}
                  dans sa configuration.
                </p>
                <p>
                  OAuth natif (connexion en un clic depuis claude.ai / ChatGPT)
                  est prévu dans une prochaine version.
                </p>
                <p>
                  Guide complet (clients, outils, quota) :{" "}
                  <span className="font-medium text-foreground">
                    docs/mcp-addon-guide.md
                  </span>
                  .
                </p>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader className="flex-row items-center justify-between gap-4">
              <div className="flex flex-col gap-1.5">
                <div className="flex items-center gap-2">
                  <CardTitle>Tes clés</CardTitle>
                  <Badge variant="secondary">
                    {activeCount}{" "}
                    {activeCount > 1 ? "clés actives" : "clé active"}
                  </Badge>
                </div>
                <CardDescription>
                  Tes clés personnelles. Clé de 256 bits, stockée hashée
                  (SHA-256), affichée une seule fois.
                </CardDescription>
              </div>
              <Button
                type="button"
                size="sm"
                onClick={() => {
                  setNewKey(null);
                  setName("");
                  setCreateOpen(true);
                }}
              >
                <KeyIcon data-icon="inline-start" />
                Créer une clé
              </Button>
            </CardHeader>
            <CardContent>
              {keys.length === 0 ? (
                <p className="py-2 text-muted-foreground text-sm">
                  Aucune clé pour le moment.
                </p>
              ) : (
                <ul className="flex flex-col divide-y divide-border">
                  {keys.map((k) => {
                    const revoked = k.revokedAt != null;
                    return (
                      <li
                        key={k.id}
                        className="flex items-center justify-between gap-4 py-3 first:pt-0 last:pb-0"
                      >
                        <div className="flex min-w-0 flex-col gap-1">
                          <div className="flex items-center gap-2">
                            <span
                              className={
                                revoked
                                  ? "truncate font-medium text-muted-foreground text-sm line-through"
                                  : "truncate font-medium text-sm"
                              }
                            >
                              {k.name}
                            </span>
                            <code className="font-mono text-muted-foreground text-xs">
                              {k.prefix}…
                            </code>
                            {revoked && (
                              <Badge variant="secondary">Révoquée</Badge>
                            )}
                          </div>
                          <span className="text-muted-foreground text-xs">
                            Créée le {fmtDate(k.createdAt)} · {k.requestCount}{" "}
                            requête
                            {k.requestCount > 1 ? "s" : ""} ·{" "}
                            {fmtLastUsed(k.lastUsedAt)}
                          </span>
                        </div>
                        {!revoked && (
                          <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            disabled={pending}
                            onClick={() => setRevokeTarget(k.id)}
                          >
                            Révoquer
                          </Button>
                        )}
                      </li>
                    );
                  })}
                </ul>
              )}
            </CardContent>
          </Card>
        </>
      )}

      <Dialog open={createOpen} onOpenChange={setCreateOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Créer une clé API</DialogTitle>
            <DialogDescription>
              Donne un nom à ta clé pour la reconnaître plus tard.
            </DialogDescription>
          </DialogHeader>

          {newKey ? (
            <div className="flex flex-col gap-3">
              <p className="font-medium text-amber-600 text-sm dark:text-amber-500">
                Copie-la maintenant, elle ne sera plus affichée.
              </p>
              <div className="flex min-w-0 items-center gap-2">
                <code className="min-w-0 flex-1 break-all rounded-md bg-muted px-3 py-2 font-mono text-sm">
                  {newKey}
                </code>
                <CopyButton value={newKey} />
              </div>
            </div>
          ) : (
            <div className="flex flex-col gap-2">
              <label htmlFor="key-name" className="font-medium text-sm">
                Nom de la clé
              </label>
              <Input
                id="key-name"
                value={name}
                placeholder="Agent de production"
                onChange={(e) => setName(e.target.value)}
                disabled={pending}
              />
            </div>
          )}

          <DialogFooter>
            {newKey ? (
              <Button type="button" onClick={() => setCreateOpen(false)}>
                Terminé
              </Button>
            ) : (
              <Button
                type="button"
                disabled={pending || name.trim().length === 0}
                onClick={createKey}
              >
                Créer
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <AlertDialog
        open={revokeTarget !== null}
        onOpenChange={(open) => {
          if (!open) setRevokeTarget(null);
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Révoquer cette clé ?</AlertDialogTitle>
            <AlertDialogDescription>
              Cette action est immédiate : les agents qui utilisent cette clé
              perdront l'accès.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Annuler</AlertDialogCancel>
            <AlertDialogAction variant="destructive" onClick={confirmRevoke}>
              Révoquer
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
