import { useEffect, useRef, type ReactNode } from "react";
import { createPortal } from "react-dom";
import { useTranslation } from "react-i18next";
import { X } from "lucide-react";
import { useBackToClose } from "../lib/history";
import { pushLayer, removeLayer, isTopmost } from "../lib/layerStack";
import { useFullscreenElement } from "../lib/fullscreen";

// Small centered modal shell: backdrop + ESC + scroll-lock close. Each open modal is a layer in the
// shared `layerStack` so ESC only closes the topmost one — e.g. an error dialog over the tag editor
// dismisses just the error and returns to the editor underneath, and a player below defers to it
// (R8 S3). Portals into `document.fullscreenElement ?? document.body`: a node under <body> is painted
// beneath whatever holds the fullscreen lock, so a Modal opened from a player in true fullscreen (the
// download dialog) would otherwise open invisibly.
export default function Modal({
  title,
  onClose,
  children,
  maxWidth = "max-w-lg",
}: {
  title: ReactNode;
  onClose: () => void;
  children: ReactNode;
  maxWidth?: string;
}) {
  const { t } = useTranslation();
  // Browser/mouse Back closes the topmost modal instead of navigating away.
  useBackToClose(onClose);
  const fsRoot = useFullscreenElement();

  // Backdrop-click close must only fire when the press STARTED on the backdrop too. Otherwise a
  // drag that begins inside the dialog (e.g. selecting text in an input) and is released out on
  // the backdrop wrongly dismisses — the click event bubbles to the common ancestor (the backdrop).
  const pressedOnBackdrop = useRef(false);

  // Keep a stable handler across renders so the stack id is assigned once per mount.
  const onCloseRef = useRef(onClose);
  onCloseRef.current = onClose;
  useEffect(() => {
    const id = pushLayer();
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape" && isTopmost(id)) {
        e.stopPropagation();
        onCloseRef.current();
      }
    };
    window.addEventListener("keydown", onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      removeLayer(id);
      document.body.style.overflow = prev;
    };
  }, []);

  return createPortal(
    <div
      className="fixed inset-0 z-overlay flex items-center justify-center p-4 sm:p-6 bg-black/70 backdrop-blur-sm"
      onMouseDown={(e) => {
        pressedOnBackdrop.current = e.target === e.currentTarget;
      }}
      onClick={(e) => {
        if (pressedOnBackdrop.current && e.target === e.currentTarget) onClose();
      }}
      role="dialog"
      aria-modal="true"
    >
      <div
        className={`glass relative w-full ${maxWidth} max-h-full overflow-y-auto rounded-2xl shadow-2xl`}
      >
        <div className="flex items-start justify-between gap-3 p-5 pb-3">
          <h2 className="text-lg font-semibold leading-snug">{title}</h2>
          <button
            onClick={onClose}
            title={t("common.close")}
            aria-label={t("common.close")}
            className="shrink-0 p-1.5 rounded-lg text-muted hover:text-fg hover:bg-surface transition"
          >
            <X className="w-4 h-4" />
          </button>
        </div>
        <div className="px-5 pb-5">{children}</div>
      </div>
    </div>,
    fsRoot ?? document.body,
  );
}
