"use client";

import { useState, type FormEvent } from "react";
import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import { Card, CardBody, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { useToast } from "@/components/ui/toast";
import {
  IconAlertTriangle,
  IconArrowRight,
  IconCheckCircle,
} from "@/components/icons";

type Mode =
  | "menu"
  | "setup_pending" // setup appelé, attente du code de confirmation
  | "disable_pending"; // demande du code pour désactiver

export function TotpManager() {
  const router = useRouter();
  const { toast } = useToast();
  const [mode, setMode] = useState<Mode>("menu");
  const [secret, setSecret] = useState<string | null>(null);
  const [otpauthUri, setOtpauthUri] = useState<string | null>(null);
  const [code, setCode] = useState("");
  const [pending, setPending] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function startSetup() {
    setError(null);
    setPending(true);
    try {
      const res = await fetch("/api/auth/totp/setup", { method: "POST" });
      const body = (await res.json().catch(() => ({}))) as {
        success?: boolean;
        secret_base32?: string;
        otpauth_uri?: string;
        error?: string;
      };
      if (!res.ok || !body.success || !body.secret_base32) {
        setError(body.error ?? "Impossible de démarrer l'enrollment");
        setPending(false);
        return;
      }
      setSecret(body.secret_base32);
      setOtpauthUri(body.otpauth_uri ?? null);
      setMode("setup_pending");
      setCode("");
      setPending(false);
    } catch {
      setError("Erreur réseau");
      setPending(false);
    }
  }

  async function confirmSetup(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError(null);
    setPending(true);
    try {
      const res = await fetch("/api/auth/totp/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ code }),
      });
      const body = (await res.json().catch(() => ({}))) as {
        success?: boolean;
        error?: string;
      };
      if (!res.ok || !body.success) {
        setError(body.error ?? "Code invalide");
        setPending(false);
        return;
      }
      toast({
        title: "2FA activé",
        description: "Tu devras saisir un code à chaque connexion.",
        tone: "success",
        duration: 3500,
      });
      setSecret(null);
      setOtpauthUri(null);
      setCode("");
      setMode("menu");
      setPending(false);
      router.refresh();
    } catch {
      setError("Erreur réseau");
      setPending(false);
    }
  }

  async function confirmDisable(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError(null);
    setPending(true);
    try {
      const res = await fetch("/api/auth/totp/disable", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ code }),
      });
      const body = (await res.json().catch(() => ({}))) as {
        success?: boolean;
        error?: string;
      };
      if (!res.ok || !body.success) {
        setError(body.error ?? "Code invalide");
        setPending(false);
        return;
      }
      toast({
        title: "2FA désactivé",
        tone: "warning",
        duration: 3500,
      });
      setCode("");
      setMode("menu");
      setPending(false);
      router.refresh();
    } catch {
      setError("Erreur réseau");
      setPending(false);
    }
  }

  function cancel() {
    setMode("menu");
    setSecret(null);
    setOtpauthUri(null);
    setCode("");
    setError(null);
  }

  // ─── Mode setup en cours : afficher la clé + champ premier code ─────
  if (mode === "setup_pending" && secret) {
    return (
      <Card>
        <CardHeader>
          <CardTitle>Activer le 2FA</CardTitle>
          <CardDescription>
            Étape 1 : ajoute le compte dans ton application d&apos;authentification
            (Google Authenticator, Authy, 2FAS, etc.). Étape 2 : saisis le code à
            6 chiffres généré pour confirmer.
          </CardDescription>
        </CardHeader>
        <CardBody className="space-y-5">
          <div>
            <p className="mb-2 text-xs font-medium uppercase tracking-wider text-muted-foreground">
              Clé secrète
            </p>
            <div className="rounded-md border border-border bg-surface-2 p-3 font-mono text-sm tabular-nums break-all select-all">
              {formatBase32(secret)}
            </div>
            <p className="mt-1.5 text-[11px] text-muted-foreground">
              Saisis cette clé manuellement dans ton authenticator. Sensible à
              la casse n&apos;est pas requise.
            </p>
          </div>

          {otpauthUri && (
            <details className="rounded-md border border-border bg-surface-2 p-3 text-xs">
              <summary className="cursor-pointer text-muted-foreground hover:text-foreground">
                Détails techniques (URI otpauth://)
              </summary>
              <p className="mt-2 break-all font-mono text-[11px] text-foreground">
                {otpauthUri}
              </p>
            </details>
          )}

          <form onSubmit={confirmSetup} className="space-y-3">
            <div>
              <label
                htmlFor="setup-code"
                className="mb-1.5 block text-xs font-medium text-foreground"
              >
                Code à 6 chiffres
              </label>
              <input
                id="setup-code"
                type="text"
                inputMode="numeric"
                pattern="\d{6}"
                maxLength={6}
                required
                autoFocus
                autoComplete="one-time-code"
                value={code}
                onChange={(e) => setCode(e.target.value.replace(/\D/g, ""))}
                placeholder="123456"
                className="w-full rounded-md border border-border bg-surface px-3 py-2 text-center text-xl tracking-[0.4em] tabular-nums shadow-sm focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent-ring/40"
              />
            </div>
            {error && <ErrorAlert message={error} />}
            <div className="flex gap-2">
              <Button
                type="button"
                variant="ghost"
                onClick={cancel}
                disabled={pending}
              >
                Annuler
              </Button>
              <Button
                type="submit"
                loading={pending}
                disabled={code.length !== 6}
                className="flex-1"
                iconRight={!pending ? <IconCheckCircle size={14} /> : undefined}
              >
                Confirmer et activer
              </Button>
            </div>
          </form>
        </CardBody>
      </Card>
    );
  }

  // ─── Mode disable : demande du code ─────────────────────────────────
  if (mode === "disable_pending") {
    return (
      <Card>
        <CardHeader>
          <CardTitle>Désactiver le 2FA</CardTitle>
          <CardDescription>
            Saisis ton code TOTP actuel pour confirmer la désactivation. C&apos;est
            une protection anti-vol de session.
          </CardDescription>
        </CardHeader>
        <CardBody>
          <form onSubmit={confirmDisable} className="space-y-3">
            <input
              id="disable-code"
              type="text"
              inputMode="numeric"
              pattern="\d{6}"
              maxLength={6}
              required
              autoFocus
              autoComplete="one-time-code"
              value={code}
              onChange={(e) => setCode(e.target.value.replace(/\D/g, ""))}
              placeholder="123456"
              className="w-full rounded-md border border-border bg-surface px-3 py-2 text-center text-xl tracking-[0.4em] tabular-nums shadow-sm focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent-ring/40"
            />
            {error && <ErrorAlert message={error} />}
            <div className="flex gap-2">
              <Button
                type="button"
                variant="ghost"
                onClick={cancel}
                disabled={pending}
              >
                Annuler
              </Button>
              <Button
                type="submit"
                loading={pending}
                disabled={code.length !== 6}
                className="flex-1"
                variant="danger"
              >
                Désactiver le 2FA
              </Button>
            </div>
          </form>
        </CardBody>
      </Card>
    );
  }

  // ─── Menu principal : Activer / Désactiver ─────────────────────────
  return (
    <Card>
      <CardHeader>
        <CardTitle>Authentification à deux facteurs (2FA)</CardTitle>
        <CardDescription>
          Ajoute une étape supplémentaire à la connexion via une application
          d&apos;authentification (TOTP RFC 6238). Recommandé pour les comptes
          super-administrateurs.
        </CardDescription>
      </CardHeader>
      <CardBody className="space-y-4">
        <div className="grid gap-3 sm:grid-cols-2">
          <Button
            type="button"
            onClick={startSetup}
            loading={pending && mode === "menu"}
            iconRight={<IconArrowRight size={14} />}
          >
            Activer le 2FA
          </Button>
          <Button
            type="button"
            variant="ghost"
            onClick={() => {
              setMode("disable_pending");
              setError(null);
            }}
          >
            Désactiver le 2FA
          </Button>
        </div>
        {error && <ErrorAlert message={error} />}
        <p className="text-[11px] text-muted-foreground">
          Si tu as activé le 2FA et que tu perds l&apos;accès à ton application,
          un autre super-administrateur peut désactiver ton 2FA en base
          directement. Pas de backup codes en V1.
        </p>
      </CardBody>
    </Card>
  );
}

// Formate une clé base32 en groupes de 4 caractères pour faciliter la lecture
// et la saisie manuelle dans l'authenticator. Ex: "ABCDEFGH..." → "ABCD EFGH …".
function formatBase32(secret: string): string {
  return secret.match(/.{1,4}/g)?.join(" ") ?? secret;
}

function ErrorAlert({ message }: { message: string }) {
  return (
    <div
      role="alert"
      className="flex items-start gap-2 rounded-md border border-red-200 bg-danger-subtle px-3 py-2 text-sm text-danger"
    >
      <IconAlertTriangle size={14} className="mt-0.5 shrink-0" />
      <span>{message}</span>
    </div>
  );
}
