"use client";

import { useEffect, useRef, type ReactNode } from "react";
import { createPortal } from "react-dom";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";

interface Props {
  open: boolean;
  onClose: () => void;
  title: string;
  children: ReactNode;
  footer?: ReactNode;
  size?: "sm" | "md" | "lg";
  describedById?: string;
  /** Render the body only, with the close button floating top-end; the body owns the heading. */
  hideHeader?: boolean;
}

const SIZES = {
  sm: "max-w-sm",
  md: "max-w-md",
  lg: "max-w-2xl",
} as const;

export function Modal({
  open,
  onClose,
  title,
  children,
  footer,
  size = "md",
  describedById,
  hideHeader = false,
}: Props) {
  const panelRef = useRef<HTMLDivElement>(null);
  const previousActive = useRef<HTMLElement | null>(null);
  const onCloseRef = useRef(onClose);

  useEffect(() => {
    onCloseRef.current = onClose;
  }, [onClose]);

  useEffect(() => {
    if (!open) return;
    previousActive.current = document.activeElement as HTMLElement | null;
    document.body.style.overflow = "hidden";

    const focusables = () =>
      panelRef.current?.querySelectorAll<HTMLElement>(
        'button, a[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',
      );

    requestAnimationFrame(() => {
      const first = focusables()?.[0];
      first?.focus();
    });

    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") onCloseRef.current();
      if (e.key === "Tab") {
        const items = focusables();
        if (!items || items.length === 0) return;
        const first = items[0];
        const last = items[items.length - 1];
        if (e.shiftKey && document.activeElement === first) {
          e.preventDefault();
          last.focus();
        } else if (!e.shiftKey && document.activeElement === last) {
          e.preventDefault();
          first.focus();
        }
      }
    }
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
      previousActive.current?.focus();
    };
  }, [open]);

  if (!open || typeof document === "undefined") return null;

  const closeButton = (
    <button
      type="button"
      onClick={onClose}
      aria-label="Close"
      className="inline-flex h-9 w-9 items-center justify-center rounded-full border border-slate-200 text-slate-500 transition hover:bg-slate-100 dark:border-slate-700 dark:text-slate-400 dark:hover:bg-slate-800"
    >
      <X className="h-4 w-4" />
    </button>
  );

  return createPortal(
    <div
      className="fixed inset-0 z-[60] flex items-center justify-center px-4 py-8"
      role="dialog"
      aria-modal="true"
      aria-label={title}
      aria-describedby={describedById}
    >
      <div
        className="absolute inset-0 bg-slate-900/60 backdrop-blur-md animate-fade-in"
        onClick={onClose}
      />
      <div
        ref={panelRef}
        className={cn(
          "relative z-10 w-full rounded-3xl border border-slate-200/70 bg-white p-6 shadow-elevated animate-scale-in dark:border-slate-800 dark:bg-slate-900",
          SIZES[size],
        )}
      >
        {hideHeader ? (
          <div className="absolute end-4 top-4">{closeButton}</div>
        ) : (
          <div className="mb-4 flex items-start justify-between gap-4">
            <h2 className="text-lg font-bold text-slate-900 dark:text-white">{title}</h2>
            {closeButton}
          </div>
        )}
        <div className="text-sm text-slate-700 dark:text-slate-200">{children}</div>
        {footer && <div className="mt-6 flex flex-wrap justify-end gap-2">{footer}</div>}
      </div>
    </div>,
    document.body,
  );
}
