"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";
import { useModalPortal } from "@/lib/modalPortalRef";
import { useTabId } from "@/contexts/TabIdContext";
import { useTabStore } from "@/stores/tabStore";
import { useDialogAutoValidation } from "@/lib/hooks/useDialogAutoValidation";

// Dialog: 탭 시스템 내에서 자동으로 modal={false} + 비활성 탭이면 open={false} 처리
const Dialog: React.FC<React.ComponentProps<typeof DialogPrimitive.Root>> = ({
  modal,
  open,
  onOpenChange,
  ...props
}) => {
  const autoContainer = useModalPortal();
  const scoped = !!autoContainer;
  const tabId = useTabId();
  const activeTabId = useTabStore((s) => s[s.mode].activeTabId);
  const isTabActive = !tabId || tabId === activeTabId;

  // ref로 최신 isTabActive를 동기적으로 추적 (useEffect보다 빠르게 업데이트)
  const isTabActiveRef = React.useRef(isTabActive);
  isTabActiveRef.current = isTabActive;

  const effectiveModal = modal !== undefined ? modal : !scoped ? undefined : false;
  const effectiveOpen = open != null ? open && isTabActive : undefined;

  // 비활성 탭에서 발생하는 onOpenChange(false) 차단
  // (탭 전환 시 content unmount → focus 이동 → Radix가 onOpenChange(false)를 호출하는 것을 방지)
  const guardedOnOpenChange = React.useCallback(
    (newOpen: boolean) => {
      if (scoped && !newOpen && !isTabActiveRef.current) {
        return;
      }
      onOpenChange?.(newOpen);
    },
    [scoped, onOpenChange, tabId],
  );

  return <DialogPrimitive.Root {...props} open={effectiveOpen} onOpenChange={guardedOnOpenChange} modal={effectiveModal} />;
};
Dialog.displayName = "Dialog";

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-999 bg-black/60",
      className,
    )}
    {...props}
  />
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;

interface ScopedDialogContentProps
  extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
  /** 포탈 대상 컨테이너. 명시적으로 전달하면 해당 값 사용, 미전달 시 탭 시스템 자동 감지 */
  container?: HTMLElement | null;
  /** 탭 비활성 시 포탈 내용 숨김 */
  hidden?: boolean;
}

const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  ScopedDialogContentProps
>(({ className, children, container: explicitContainer, hidden: hiddenProp, onInteractOutside, onFocusOutside, style, ...props }, ref) => {
  const autoContainer = useModalPortal();
  const container = explicitContainer !== undefined ? explicitContainer : autoContainer;
  const scoped = !!container;

  // state 기반 ref: DialogPrimitive.Content 마운트/언마운트 시 useEffect 재실행 보장
  const [contentNode, setContentNode] = React.useState<HTMLDivElement | null>(null);
  const mergedRef = React.useCallback(
    (node: HTMLDivElement | null) => {
      setContentNode(node);
      if (typeof ref === "function") ref(node);
      else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;
    },
    [ref],
  );
  useDialogAutoValidation(contentNode);

  const handleInteractOutside = React.useCallback(
    (e: any) => {
      if (scoped && container) {
        const target = (e.detail?.originalEvent?.target ?? e.target) as HTMLElement | null;
        if (target && !container.contains(target)) {
          e.preventDefault();
          return;
        }
      }
      onInteractOutside?.(e);
    },
    [scoped, container, onInteractOutside],
  );

  // scoped 모드: content unmount 시 포커스 이동으로 인한 onOpenChange(false) 방지
  const handleFocusOutside = React.useCallback(
    (e: any) => {
      if (scoped) {
        e.preventDefault();
        return;
      }
      onFocusOutside?.(e);
    },
    [scoped, onFocusOutside],
  );

  // scoped 모드: 뷰포트 기반 maxHeight/maxWidth 제거 → className의 max-h-full이 컨테이너 기준으로 적용됨
  const adjustedStyle = scoped && style
    ? { ...style, maxHeight: undefined, maxWidth: undefined }
    : style;

  return (
    <DialogPortal container={container ?? undefined}>
      <div
        className={scoped ? "absolute inset-0 z-999 flex items-center justify-center overflow-hidden p-4" : undefined}
        style={hiddenProp ? { display: "none" } : undefined}
      >
        {scoped ? (
          <div className="absolute inset-0 bg-black/60" />
        ) : (
          <DialogPrimitive.Overlay className="fixed inset-0 z-999 bg-black/60" />
        )}
        <DialogPrimitive.Content
          ref={mergedRef}
          onInteractOutside={handleInteractOutside}
          onFocusOutside={handleFocusOutside}
          className={cn(
            scoped
              ? "bg-background relative z-1 flex w-full max-w-lg max-h-full flex-col gap-4 border p-6 shadow-lg sm:rounded-lg"
              : "bg-background fixed top-[50%] left-[50%] z-1000 flex w-full max-w-lg translate-x-[-50%] translate-y-[-50%] flex-col gap-4 border p-6 shadow-lg sm:rounded-lg",
            className,
            scoped && "max-h-full",
          )}
          style={adjustedStyle}
          {...props}
        >
          {children}
          <DialogPrimitive.Close data-dialog-close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none">
            <X className="h-4 w-4" />
            <span className="sr-only">Close</span>
          </DialogPrimitive.Close>
        </DialogPrimitive.Content>
      </div>
    </DialogPortal>
  );
});
DialogContent.displayName = DialogPrimitive.Content.displayName;

const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left shrink-0", className)} {...props} />
);
DialogHeader.displayName = "DialogHeader";

const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div data-slot="dialog-footer" className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 shrink-0", 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 leading-none font-semibold tracking-tight", 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-muted-foreground text-sm", className)} {...props} />
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;

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