'use client';

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { cn } from '@/lib/utils';
import { AlertTriangle, HelpCircle, Trash2 } from 'lucide-react';
import { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';

/*
 * Reemplazo de `window.confirm`.
 *
 * El confirm del navegador no se puede estilar, se ve distinto en cada
 * dispositivo, en la app instalada aparece con el nombre del sitio ("localhost
 * dice:") y en iOS bloquea el hilo. Para alguien que no es de tecnología ese
 * salto visual se lee como que el sistema falló.
 *
 * La API es una promesa a propósito, para que el código en cada pantalla no
 * cambie de forma:
 *
 *   if (!window.confirm('¿Inactivar?')) return;   // antes
 *   if (!(await confirm({ title: '¿Inactivar?' }))) return;   // ahora
 */

export type ConfirmTone = 'default' | 'destructive';

export type ConfirmOptions = {
  title: string;
  /** Qué va a pasar exactamente. Escribilo en palabras, no en jerga. */
  description?: string;
  /** Texto del botón que confirma. Que diga la acción: "Inactivar", no "Aceptar". */
  confirmLabel?: string;
  cancelLabel?: string;
  tone?: ConfirmTone;
};

type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;

const ConfirmContext = createContext<ConfirmFn | null>(null);

export function useConfirm(): ConfirmFn {
  const context = useContext(ConfirmContext);
  if (!context) {
    throw new Error('useConfirm debe usarse dentro de ConfirmProvider');
  }
  return context;
}

type PendingState = {
  options: ConfirmOptions;
  open: boolean;
};

export function ConfirmProvider({ children }: { children: React.ReactNode }) {
  const [pending, setPending] = useState<PendingState | null>(null);
  const resolverRef = useRef<((value: boolean) => void) | null>(null);

  const confirm = useCallback<ConfirmFn>((options) => {
    return new Promise<boolean>((resolve) => {
      // Si ya había una confirmación abierta, la anterior se resuelve en falso
      // para no dejar una promesa colgada para siempre.
      resolverRef.current?.(false);
      resolverRef.current = resolve;
      setPending({ options, open: true });
    });
  }, []);

  const settle = useCallback((value: boolean) => {
    resolverRef.current?.(value);
    resolverRef.current = null;
    setPending((current) => (current ? { ...current, open: false } : null));
  }, []);

  const value = useMemo(() => confirm, [confirm]);
  const options = pending?.options;
  const destructive = options?.tone === 'destructive';
  const Icon = destructive ? Trash2 : options?.tone === 'default' ? HelpCircle : AlertTriangle;

  return (
    <ConfirmContext.Provider value={value}>
      {children}

      <AlertDialog
        open={pending?.open ?? false}
        onOpenChange={(open) => {
          // Cubre el Escape y el clic afuera: ambos cuentan como cancelar.
          if (!open) settle(false);
        }}
      >
        {options ? (
          <AlertDialogContent>
            <AlertDialogHeader>
              <div
                className={cn(
                  'mb-1 flex h-11 w-11 items-center justify-center rounded-full',
                  destructive ? 'bg-destructive-soft text-destructive' : 'bg-warning-soft text-warning',
                )}
              >
                <Icon className="h-5 w-5" />
              </div>
              <AlertDialogTitle>{options.title}</AlertDialogTitle>
              {options.description ? (
                <AlertDialogDescription>{options.description}</AlertDialogDescription>
              ) : null}
            </AlertDialogHeader>

            <AlertDialogFooter>
              <AlertDialogCancel onClick={() => settle(false)}>
                {options.cancelLabel || 'Cancelar'}
              </AlertDialogCancel>
              <AlertDialogAction
                onClick={() => settle(true)}
                className={cn(
                  destructive && 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
                )}
              >
                {options.confirmLabel || 'Continuar'}
              </AlertDialogAction>
            </AlertDialogFooter>
          </AlertDialogContent>
        ) : null}
      </AlertDialog>
    </ConfirmContext.Provider>
  );
}
