"use client";

import * as React from "react";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import * as DialogPrimitive from "@radix-ui/react-dialog";

import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button";
import { useModalPortal } from "@/lib/modalPortalRef";
import { useTabId } from "@/contexts/TabIdContext";
import { useTabStore } from "@/stores/tabStore";

/**
 * 탭 시스템 스코프 여부를 하위 컴포넌트에 전달하는 내부 Context.
 * scoped=true 이면 AlertDialogPrimitive 대신 DialogPrimitive 사용.
 */
const ScopedAlertCtx = React.createContext(false);

const AlertDialog: React.FC<React.ComponentProps<typeof AlertDialogPrimitive.Root>> = ({
  open,
  children,
  onOpenChange,
  ...props
}) => {
  const autoContainer = useModalPortal();
  const scoped = !!autoContainer;
  const tabId = useTabId();
  const activeTabId = useTabStore((s) => s[s.mode].activeTabId);
  const isTabActive = !tabId || tabId === activeTabId;

  const isTabActiveRef = React.useRef(isTabActive);
  isTabActiveRef.current = isTabActive;

  const effectiveOpen = open != null ? open : undefined;

  const guardedOnOpenChange = React.useCallback(
    (newOpen: boolean) => {
      if (scoped && !newOpen && !isTabActiveRef.current) return;
      onOpenChange?.(newOpen);
    },
    [scoped, onOpenChange],
  );

  if (scoped) {
    return (
      <ScopedAlertCtx.Provider value={true}>
        <DialogPrimitive.Root open={effectiveOpen} onOpenChange={guardedOnOpenChange} modal={false}>
          {children}
        </DialogPrimitive.Root>
      </ScopedAlertCtx.Provider>
    );
  }

  return (
    <ScopedAlertCtx.Provider value={false}>
      <AlertDialogPrimitive.Root {...props} open={effectiveOpen} onOpenChange={guardedOnOpenChange}>
        {children}
      </AlertDialogPrimitive.Root>
    </ScopedAlertCtx.Provider>
  );
};
AlertDialog.displayName = "AlertDialog";

const AlertDialogTrigger = AlertDialogPrimitive.Trigger;

const AlertDialogPortal = AlertDialogPrimitive.Portal;

const AlertDialogOverlay = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <AlertDialogPrimitive.Overlay
    className={cn(
      "fixed inset-0 z-1050 bg-black/80",
      className,
    )}
    {...props}
    ref={ref}
  />
));
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;

interface ScopedAlertDialogContentProps
  extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> {
  container?: HTMLElement | null;
  hidden?: boolean;
}

const AlertDialogContent = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Content>,
  ScopedAlertDialogContentProps
>(({ className, container: explicitContainer, hidden: hiddenProp, style, ...props }, ref) => {
  const autoContainer = useModalPortal();
  const container = explicitContainer !== undefined ? explicitContainer : autoContainer;
  const scoped = React.useContext(ScopedAlertCtx);

  // 탭 비활성 시 content를 언마운트하지 않고 CSS로 숨김 (자식 컴포넌트 상태 보존)
  const tabId = useTabId();
  const activeTabId = useTabStore((s) => s[s.mode].activeTabId);
  const isTabActive = !tabId || tabId === activeTabId;

  const adjustedStyle = scoped && style
    ? { ...style, maxHeight: undefined, maxWidth: undefined }
    : style;

  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;
        }
      }
      e.preventDefault();
    },
    [scoped, container],
  );

  if (scoped) {
    return (
      <DialogPrimitive.Portal container={container ?? undefined}>
        <div
          className="absolute inset-0 z-[10100] flex items-center justify-center overflow-hidden p-4"
          style={(hiddenProp || !isTabActive) ? { display: "none" } : undefined}
        >
          <div className="absolute inset-0 bg-black/80" />
          <DialogPrimitive.Content
            ref={ref}
            onInteractOutside={handleInteractOutside}
            onFocusOutside={(e: any) => e.preventDefault()}
            onEscapeKeyDown={(e) => e.preventDefault()}
            className={cn(
              "bg-background relative z-1 grid w-full max-w-lg max-h-full gap-4 border p-6 shadow-lg sm:rounded-lg",
              className,
            )}
            style={adjustedStyle}
            {...props}
          />
        </div>
      </DialogPrimitive.Portal>
    );
  }

  return (
    <AlertDialogPortal container={container ?? undefined}>
      <div
        style={hiddenProp ? { display: "none" } : undefined}
      >
        <AlertDialogPrimitive.Overlay className="fixed inset-0 z-[10100] bg-black/80" />
        <AlertDialogPrimitive.Content
          ref={ref}
          className={cn(
            "bg-background fixed top-[50%] left-[50%] z-[10101] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg sm:rounded-lg",
            className,
          )}
          style={adjustedStyle}
          {...props}
        />
      </div>
    </AlertDialogPortal>
  );
});
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;

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

const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} />
);
AlertDialogFooter.displayName = "AlertDialogFooter";

const AlertDialogTitle = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
>(({ className, ...props }, ref) => {
  const scoped = React.useContext(ScopedAlertCtx);
  const Comp = scoped ? DialogPrimitive.Title : AlertDialogPrimitive.Title;
  return <Comp ref={ref} className={cn("text-lg font-semibold", className)} {...props} />;
});
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;

const AlertDialogDescription = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
>(({ className, ...props }, ref) => {
  const scoped = React.useContext(ScopedAlertCtx);
  const Comp = scoped ? DialogPrimitive.Description : AlertDialogPrimitive.Description;
  return <Comp ref={ref} className={cn("text-muted-foreground text-sm", className)} {...props} />;
});
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;

const AlertDialogAction = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Action>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
>(({ className, ...props }, ref) => {
  const scoped = React.useContext(ScopedAlertCtx);
  const Comp = scoped ? DialogPrimitive.Close : AlertDialogPrimitive.Action;
  return <Comp ref={ref} className={cn(buttonVariants(), className)} {...props} />;
});
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;

const AlertDialogCancel = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
>(({ className, ...props }, ref) => {
  const scoped = React.useContext(ScopedAlertCtx);
  const Comp = scoped ? DialogPrimitive.Close : AlertDialogPrimitive.Cancel;
  return (
    <Comp
      ref={ref}
      className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)}
      {...props}
    />
  );
});
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;

export {
  AlertDialog,
  AlertDialogPortal,
  AlertDialogOverlay,
  AlertDialogTrigger,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogFooter,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogAction,
  AlertDialogCancel,
};
