"use client";

import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";

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

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-stone-950/45 backdrop-blur-[3px] data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out", className)} {...props} />
));
DialogOverlay.displayName = "DialogOverlay";

/**
 * Modal content. On mobile it becomes a bottom sheet that slides up (and
 * back down on close); on larger screens a centred dialog that scales in.
 */
const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & { size?: "sm" | "md" | "lg" | "xl" | "full"; hideClose?: boolean }
>(({ className, children, size = "md", hideClose, ...props }, ref) => (
  <DialogPortal>
    <DialogOverlay />
    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        "fixed z-50 flex flex-col bg-surface shadow-xl border border-border focus:outline-none",
        // mobile: bottom sheet
        "inset-x-0 bottom-0 max-h-[92dvh] rounded-t-2xl data-[state=open]:animate-sheet-in data-[state=closed]:animate-sheet-out",
        // desktop: centred
        "sm:inset-auto sm:left-1/2 sm:top-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-2xl sm:max-h-[88vh] sm:w-full sm:data-[state=open]:animate-scale-in sm:data-[state=closed]:animate-scale-out",
        size === "sm" && "sm:max-w-sm",
        size === "md" && "sm:max-w-lg",
        size === "lg" && "sm:max-w-2xl",
        size === "xl" && "sm:max-w-4xl",
        size === "full" && "sm:max-w-[min(96vw,1200px)]",
        className
      )}
      {...props}
    >
      <div className="mx-auto mt-2 h-1 w-10 rounded-full bg-border-strong sm:hidden" />
      {children}
      {!hideClose ? (
        <DialogPrimitive.Close className="absolute right-3 top-3 rounded-md p-1.5 text-fg-muted transition hover:bg-surface-2 hover:text-fg hover:rotate-90 duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring">
          <X className="size-4" />
          <span className="sr-only">Close</span>
        </DialogPrimitive.Close>
      ) : null}
    </DialogPrimitive.Content>
  </DialogPortal>
));
DialogContent.displayName = "DialogContent";

function DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("flex flex-col gap-1 px-5 pt-5 pb-3 pr-12", className)} {...props} />;
}
function DialogBody({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("flex-1 overflow-y-auto px-5 py-2 scrollbar-thin", className)} {...props} />;
}
function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("flex flex-col-reverse gap-2 border-t border-border px-5 py-4 sm:flex-row sm:justify-end safe-bottom", className)} {...props} />;
}
const DialogTitle = React.forwardRef<React.ElementRef<typeof DialogPrimitive.Title>, React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>>(({ className, ...props }, ref) => (
  <DialogPrimitive.Title ref={ref} className={cn("text-base font-semibold leading-tight text-fg", className)} {...props} />
));
DialogTitle.displayName = "DialogTitle";
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 text-fg-muted", className)} {...props} />
));
DialogDescription.displayName = "DialogDescription";

/** Side drawer (slides from the right or left on desktop, bottom sheet on mobile). */
const DrawerContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & { width?: "sm" | "md" | "lg" | "xl"; side?: "right" | "left"; phone?: "sheet" | "side" }
>(({ className, children, width = "md", side = "right", phone = "sheet", ...props }, ref) => (
  <DialogPortal>
    <DialogOverlay />
    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        "fixed z-50 flex flex-col bg-surface shadow-xl border-border focus:outline-none",
        phone === "sheet"
          ? "inset-x-0 bottom-0 max-h-[92dvh] rounded-t-2xl border-t data-[state=open]:animate-sheet-in data-[state=closed]:animate-sheet-out sm:inset-y-0 sm:bottom-auto sm:max-h-none sm:h-full sm:w-full sm:rounded-none sm:border-t-0"
          : "inset-y-0 h-full w-[86vw] max-w-sm rounded-none sm:w-full",
        side === "right"
          ? cn("sm:right-0 sm:left-auto sm:border-l", phone === "sheet" ? "sm:data-[state=open]:animate-drawer-in sm:data-[state=closed]:animate-drawer-out" : "right-0 left-auto border-l data-[state=open]:animate-drawer-in data-[state=closed]:animate-drawer-out")
          : cn("sm:left-0 sm:right-auto sm:border-r", phone === "sheet" ? "sm:data-[state=open]:animate-drawer-left-in sm:data-[state=closed]:animate-drawer-left-out" : "left-0 right-auto border-r data-[state=open]:animate-drawer-left-in data-[state=closed]:animate-drawer-left-out"),
        width === "sm" && "sm:max-w-sm",
        width === "md" && "sm:max-w-md",
        width === "lg" && "sm:max-w-xl",
        width === "xl" && "sm:max-w-3xl",
        className
      )}
      {...props}
    >
      {phone === "sheet" ? <div className="mx-auto mt-2 h-1 w-10 rounded-full bg-border-strong sm:hidden" /> : null}
      {children}
      <DialogPrimitive.Close className="absolute right-3 top-3 rounded-md p-1.5 text-fg-muted transition hover:bg-surface-2 hover:text-fg hover:rotate-90 duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring">
        <X className="size-4" />
        <span className="sr-only">Close</span>
      </DialogPrimitive.Close>
    </DialogPrimitive.Content>
  </DialogPortal>
));
DrawerContent.displayName = "DrawerContent";

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