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

/**
 * Dialog primitive — thin styled wrapper over @radix-ui/react-dialog.
 * Radix handles focus trap, scroll lock, Escape, focus restoration, and ARIA.
 *
 * The exported API mirrors the previous custom implementation so consumers
 * (Drawer, CommandPalette, ShortcutsOverlay) didn't need restructuring:
 *
 *   <Dialog open onOpenChange>
 *     <DialogPanel ariaLabel="…">
 *       <DialogHeader onClose>...</DialogHeader>
 *       <DialogBody>...</DialogBody>
 *       <DialogFooter>...</DialogFooter>
 *     </DialogPanel>
 *   </Dialog>
 */

interface DialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  children: React.ReactNode;
  /** Compatibility shim — ariaLabel is now supplied on DialogPanel directly. */
  ariaLabel?: string;
  /** Block close from overlay click */
  closeOnOverlayClick?: boolean;
  /** Block close from Escape */
  closeOnEscape?: boolean;
}

const DialogCtx = React.createContext<{
  ariaLabel?: string;
  closeOnOverlayClick: boolean;
  closeOnEscape: boolean;
}>({ closeOnOverlayClick: true, closeOnEscape: true });

export function Dialog({
  open,
  onOpenChange,
  children,
  ariaLabel,
  closeOnOverlayClick = true,
  closeOnEscape = true,
}: DialogProps) {
  return (
    <DialogCtx.Provider
      value={{ ariaLabel, closeOnOverlayClick, closeOnEscape }}
    >
      <RadixDialog.Root open={open} onOpenChange={onOpenChange}>
        {children}
      </RadixDialog.Root>
    </DialogCtx.Provider>
  );
}

export const DialogTrigger = RadixDialog.Trigger;
export const DialogClose = RadixDialog.Close;

interface DialogPanelProps extends React.HTMLAttributes<HTMLDivElement> {
  /** Accessible label when the panel has no DialogTitle */
  ariaLabel?: string;
  /** Accessible description id reference */
  ariaDescribedBy?: string;
}

export const DialogPanel = React.forwardRef<HTMLDivElement, DialogPanelProps>(
  ({ className, children, ariaLabel, ariaDescribedBy, ...props }, ref) => {
    const ctx = React.useContext(DialogCtx);
    const label = ariaLabel ?? ctx.ariaLabel;
    return (
      <RadixDialog.Portal>
        <RadixDialog.Overlay
          className={cn(
            "fixed inset-0 z-50 bg-black/40 backdrop-blur-sm",
            "data-[state=open]:animate-fade-in",
          )}
        />
        <RadixDialog.Content
          ref={ref}
          aria-label={label}
          aria-describedby={ariaDescribedBy}
          onInteractOutside={(e) => {
            if (!ctx.closeOnOverlayClick) e.preventDefault();
          }}
          onEscapeKeyDown={(e) => {
            if (!ctx.closeOnEscape) e.preventDefault();
          }}
          className={cn(
            "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
            "flex max-h-[90vh] w-full max-w-lg flex-col overflow-hidden",
            "rounded-xl border border-border bg-surface-raised shadow-xl outline-none",
            "data-[state=open]:animate-fade-in-up",
            className,
          )}
          {...props}
        >
          {/* Radix warns if no Title is present. If consumer didn't provide one,
              expose ariaLabel via VisuallyHidden Title as a fallback. */}
          {label && !hasDialogTitle(children) && (
            <RadixDialog.Title className="sr-only">{label}</RadixDialog.Title>
          )}
          {children}
        </RadixDialog.Content>
      </RadixDialog.Portal>
    );
  },
);
DialogPanel.displayName = "DialogPanel";

/** Best-effort detection: does the children tree include a <DialogTitle>? */
function hasDialogTitle(node: React.ReactNode): boolean {
  let found = false;
  React.Children.forEach(node, (child) => {
    if (found) return;
    if (!React.isValidElement(child)) return;
    if (child.type === DialogTitle) {
      found = true;
      return;
    }
    const subtree = (child.props as { children?: React.ReactNode } | undefined)
      ?.children;
    if (subtree && hasDialogTitle(subtree)) found = true;
  });
  return found;
}

export function DialogHeader({
  className,
  children,
  onClose,
  ...props
}: React.HTMLAttributes<HTMLDivElement> & { onClose?: () => void }) {
  return (
    <div
      className={cn(
        "flex items-start justify-between gap-4 border-b border-border px-5 py-4",
        className,
      )}
      {...props}
    >
      <div className="min-w-0 flex-1">{children}</div>
      {onClose && (
        <RadixDialog.Close asChild>
          <button
            type="button"
            onClick={onClose}
            className="-mr-2 -mt-1 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
            aria-label="Close"
          >
            <X className="h-4 w-4" />
          </button>
        </RadixDialog.Close>
      )}
    </div>
  );
}

export const DialogTitle = React.forwardRef<
  HTMLHeadingElement,
  React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
  <RadixDialog.Title asChild>
    <h2
      ref={ref}
      className={cn("text-base font-semibold text-foreground", className)}
      {...props}
    />
  </RadixDialog.Title>
));
DialogTitle.displayName = "DialogTitle";

export const DialogDescription = React.forwardRef<
  HTMLParagraphElement,
  React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
  <RadixDialog.Description asChild>
    <p
      ref={ref}
      className={cn("mt-1 text-sm text-muted-foreground", className)}
      {...props}
    />
  </RadixDialog.Description>
));
DialogDescription.displayName = "DialogDescription";

export function DialogBody({
  className,
  ...props
}: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      className={cn("flex-1 overflow-y-auto px-5 py-4", className)}
      {...props}
    />
  );
}

export function DialogFooter({
  className,
  ...props
}: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      className={cn(
        "flex flex-row-reverse items-center gap-2 border-t border-border px-5 py-3",
        className,
      )}
      {...props}
    />
  );
}
