'use client';

import * as DialogPrimitive from '@radix-ui/react-dialog';
import { X } from 'lucide-react';
import * as React from 'react';

import { cn } from '@/lib/utils';

const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = DialogPrimitive.Portal;
const DialogClose = DialogPrimitive.Close;

const DialogOverlay = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Overlay
    ref={ref}
    className={cn(
      'fixed inset-0 z-50 bg-foreground/25 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0',
      className,
    )}
    {...props}
  />
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;

/*
 * Dos comportamientos según el ancho:
 *
 * - En celular es una hoja anclada abajo, a todo el ancho. El pulgar llega a
 *   los botones sin estirar la mano, que es como se usa el sistema en el taller.
 * - De `sm` hacia arriba es el diálogo centrado de siempre.
 *
 * En ambos casos la altura está topada con `dvh` y el contenido scrollea por
 * dentro. Antes no había tope de altura: en una laptop de 768px de alto o en un
 * celular acostado, el botón de guardar quedaba fuera de la pantalla y no había
 * forma de alcanzarlo. `dvh` y no `vh` porque en móvil la barra del navegador
 * aparece y desaparece, y `vh` no se entera.
 */
const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
  <DialogPortal>
    <DialogOverlay />
    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        'fixed z-50 flex flex-col overflow-hidden bg-surface text-foreground shadow-2xl',
        // Celular: hoja desde abajo
        'inset-x-0 bottom-0 max-h-[92dvh] rounded-t-3xl border-t border-border',
        'data-[state=open]:animate-sheet-up',
        // Tablet y computadora: diálogo centrado
        'sm:inset-x-auto sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:max-h-[88dvh] sm:w-full sm:max-w-lg sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-2xl sm:border',
        'sm:data-[state=open]:animate-fade-in',
        className,
      )}
      {...props}
    >
      {/* Agarradera visible sólo en la hoja móvil */}
      <div
        aria-hidden
        className="mx-auto mt-2 h-1 w-10 shrink-0 rounded-full bg-border-strong sm:hidden"
      />
      {children}
      <DialogPrimitive.Close className="absolute right-3 top-3 z-10 flex h-9 w-9 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none">
        <X className="h-5 w-5" />
        <span className="sr-only">Cerrar</span>
      </DialogPrimitive.Close>
    </DialogPrimitive.Content>
  </DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;

const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div
    className={cn(
      'shrink-0 space-y-1 border-b border-border px-5 py-4 pr-14 text-left sm:px-6',
      className,
    )}
    {...props}
  />
);
DialogHeader.displayName = 'DialogHeader';

/*
 * Región scrolleable del diálogo. Usala para el cuerpo del formulario, así el
 * encabezado y el pie quedan siempre visibles mientras se scrollea.
 */
const DialogBody = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div
    className={cn('min-h-0 flex-1 overflow-y-auto overscroll-contain px-5 py-5 sm:px-6', className)}
    {...props}
  />
);
DialogBody.displayName = 'DialogBody';

/*
 * El pie queda fijo abajo y nunca se va de la pantalla. En celular los botones
 * se apilan a todo el ancho con la acción principal ABAJO, que es donde cae el
 * pulgar: con el orden invertido el botón más fácil de apretar terminaba siendo
 * "Cancelar". En pantalla grande van en fila a la derecha, como se espera.
 * El orden del DOM no cambia en ninguno de los dos casos.
 */
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div
    className={cn(
      'safe-bottom flex shrink-0 flex-col gap-2 border-t border-border bg-surface px-5 py-4 sm:flex-row sm:justify-end sm:px-6 [&>*]:w-full sm:[&>*]:w-auto',
      className,
    )}
    {...props}
  />
);
DialogFooter.displayName = 'DialogFooter';

const DialogTitle = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Title
    ref={ref}
    className={cn('text-lg font-semibold tracking-tight text-foreground', className)}
    {...props}
  />
));
DialogTitle.displayName = DialogPrimitive.Title.displayName;

const DialogDescription = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Description
    ref={ref}
    className={cn('text-sm leading-relaxed text-muted-foreground', className)}
    {...props}
  />
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;

export {
  Dialog,
  DialogPortal,
  DialogOverlay,
  DialogClose,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogBody,
  DialogFooter,
  DialogTitle,
  DialogDescription,
};
