import { type ReactElement } from "react";
import * as React from "react";
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
import { cn } from "@/lib/utils";
import { asChildProps } from "@/lib/as-child";
import { useThemeVars } from "@/lib/theme-provider";

/**
 * Provides a DOM container for Popover portals rendered inside a Drawer/Dialog.
 * Without this, Base UI's FloatingPortal renders to document.body, which sits
 * outside Radix's DismissableLayer — causing outside-click detection to fire
 * and close the Drawer when the user clicks inside the popover.
 *
 * Usage: wrap DrawerContent body with <PopoverPortalProvider container={ref}>
 * and place a <div ref={...} /> inside DrawerContent as the portal target.
 */
const PopoverPortalContext = React.createContext<
  HTMLElement | null | undefined
>(undefined);

export type PopoverPortalProviderProps = {
  container: HTMLElement | null | undefined;
  children: React.ReactNode;
};

function PopoverPortalProvider({
  container,
  children,
}: PopoverPortalProviderProps): ReactElement {
  return (
    <PopoverPortalContext.Provider value={container}>
      {children}
    </PopoverPortalContext.Provider>
  );
}

export type PopoverProps = React.ComponentProps<typeof PopoverPrimitive.Root>;

function Popover({ ...props }: PopoverProps): ReactElement {
  return <PopoverPrimitive.Root data-slot="popover" {...props} />;
}

export type PopoverTriggerProps = React.ComponentProps<
  typeof PopoverPrimitive.Trigger
> & {
  /** shadcn-compatible alias for Base UI's `render`: replaces the trigger with its single child. */
  asChild?: boolean;
};

function PopoverTrigger({
  asChild,
  children,
  ...props
}: PopoverTriggerProps): ReactElement {
  return (
    <PopoverPrimitive.Trigger
      data-slot="popover-trigger"
      {...props}
      {...asChildProps(asChild, children)}
    />
  );
}

export type PopoverContentProps = React.ComponentProps<
  typeof PopoverPrimitive.Popup
> & {
  align?: "start" | "center" | "end";
  sideOffset?: number;
};

function PopoverContent({
  className,
  align = "center",
  sideOffset = 4,
  style,
  ...props
}: PopoverContentProps): ReactElement {
  const themeVars = useThemeVars();
  const portalContainer = React.useContext(PopoverPortalContext);
  return (
    <PopoverPrimitive.Portal container={portalContainer ?? undefined}>
      <PopoverPrimitive.Positioner
        className="z-[200]"
        align={align}
        sideOffset={sideOffset}
        positionMethod="fixed"
      >
        <PopoverPrimitive.Popup
          className={cn(
            "z-50 w-72 border border-border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-ending-style:animate-out data-ending-style:fade-out-0 data-ending-style:zoom-out-95 data-ending-style:fill-mode-forwards data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95",
            className
          )}
          data-slot="popover-content"
          style={{ ...themeVars, ...style } as React.CSSProperties}
          {...props}
        />
      </PopoverPrimitive.Positioner>
    </PopoverPrimitive.Portal>
  );
}

export type PopoverAnchorProps = React.ComponentProps<"div">;

function PopoverAnchor({ ...props }: PopoverAnchorProps): ReactElement {
  return <div data-slot="popover-anchor" {...props} />;
}

export type PopoverHeaderProps = React.ComponentProps<"div">;

function PopoverHeader({
  className,
  ...props
}: PopoverHeaderProps): ReactElement {
  return (
    <div
      className={cn("flex flex-col gap-1 text-body-small", className)}
      data-slot="popover-header"
      {...props}
    />
  );
}

export type PopoverTitleProps = React.ComponentProps<"h2">;

function PopoverTitle({
  className,
  ...props
}: PopoverTitleProps): ReactElement {
  return (
    // eslint-disable-next-line jsx-a11y/heading-has-content -- children passed via props spread
    <h2
      className={cn("font-medium", className)}
      data-slot="popover-title"
      {...props}
    />
  );
}

export type PopoverDescriptionProps = React.ComponentProps<"p">;

function PopoverDescription({
  className,
  ...props
}: PopoverDescriptionProps): ReactElement {
  return (
    <p
      className={cn("text-muted-foreground", className)}
      data-slot="popover-description"
      {...props}
    />
  );
}

export {
  Popover,
  PopoverTrigger,
  PopoverContent,
  PopoverAnchor,
  PopoverHeader,
  PopoverTitle,
  PopoverDescription,
  PopoverPortalProvider,
};
