import { type ReactElement } from "react";
import * as React from "react";
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import { Select as SelectPrimitive } from "@base-ui/react/select";
import { cn } from "@/lib/utils";
import { useThemeVars } from "@/lib/theme-provider";

/**
 * Provides a DOM container for Select portals so they render inside the
 * DrawerContent element (which has pointer-events:auto from Radix
 * DismissableLayer) rather than at document.body (which Radix sets to
 * pointer-events:none when a modal dialog is open).
 *
 * Usage inside a Vaul Drawer:
 *   const [portalEl, setPortalEl] = useState<HTMLElement | undefined>();
 *   <SelectPortalProvider container={portalEl}>…</SelectPortalProvider>
 *   <div ref={el => el && setPortalEl(el)} />   ← place inside DrawerContent
 */
const SelectPortalContext = React.createContext<HTMLElement | undefined>(
  undefined,
);

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

function SelectPortalProvider({
  container,
  children,
}: SelectPortalProviderProps): ReactElement {
  return (
    <SelectPortalContext.Provider value={container}>
      {children}
    </SelectPortalContext.Provider>
  );
}

export type SelectProps<
  Value = string,
  Multiple extends boolean | undefined = false,
> = SelectPrimitive.Root.Props<Value, Multiple>;

function Select<Value = string, Multiple extends boolean | undefined = false>({
  ...props
}: SelectProps<Value, Multiple>): ReactElement {
  return <SelectPrimitive.Root data-slot="select" {...props} />;
}

export type SelectGroupProps = React.ComponentProps<
  typeof SelectPrimitive.Group
>;

function SelectGroup({ ...props }: SelectGroupProps): ReactElement {
  return <SelectPrimitive.Group data-slot="select-group" {...props} />;
}

export type SelectValueProps = React.ComponentProps<
  typeof SelectPrimitive.Value
>;

function SelectValue({ ...props }: SelectValueProps): ReactElement {
  return <SelectPrimitive.Value data-slot="select-value" {...props} />;
}

export type SelectTriggerProps = React.ComponentProps<
  typeof SelectPrimitive.Trigger
> & {
  size?: "sm" | "default";
};

function SelectTrigger({
  className,
  size = "default",
  children,
  ...props
}: SelectTriggerProps): ReactElement {
  return (
    <SelectPrimitive.Trigger
      className={cn(
        "flex w-fit items-center justify-between gap-2 border border-input bg-transparent px-3 py-2 text-body-medium whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/20 data-popup-open:border-primary data-popup-open:ring-[3px] data-popup-open:ring-primary/20 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-placeholder:font-normal data-placeholder:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
        className,
      )}
      data-size={size}
      data-slot="select-trigger"
      {...props}
    >
      {children}
      <SelectPrimitive.Icon className="transition-transform duration-200 data-popup-open:rotate-180">
        <ChevronDownIcon className="size-4 opacity-50" />
      </SelectPrimitive.Icon>
    </SelectPrimitive.Trigger>
  );
}

export type SelectContentProps = React.ComponentProps<
  typeof SelectPrimitive.Popup
>;

function SelectContent({
  className,
  children,
  style,
  ...props
}: SelectContentProps): ReactElement {
  const themeVars = useThemeVars();
  const portalContainer = React.useContext(SelectPortalContext);
  return (
    <SelectPrimitive.Portal container={portalContainer}>
      <SelectPrimitive.Positioner
        className="z-[200]"
        align="start"
        alignItemWithTrigger={false}
        sideOffset={4}
      >
        <SelectPrimitive.Popup
          className={cn(
            "relative max-h-[var(--available-height)] min-w-[var(--anchor-width,8rem)] overflow-x-hidden overflow-y-auto border bg-popover p-1 text-popover-foreground shadow-md 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="select-content"
          style={{ ...themeVars, ...style } as React.CSSProperties}
          {...props}
        >
          <SelectScrollUpButton />
          {children}
          <SelectScrollDownButton />
        </SelectPrimitive.Popup>
      </SelectPrimitive.Positioner>
    </SelectPrimitive.Portal>
  );
}

export type SelectLabelProps = React.ComponentProps<
  typeof SelectPrimitive.GroupLabel
>;

function SelectLabel({ className, ...props }: SelectLabelProps): ReactElement {
  return (
    <SelectPrimitive.GroupLabel
      className={cn(
        "px-2 py-1.5 text-label-small text-muted-foreground",
        className,
      )}
      data-slot="select-label"
      {...props}
    />
  );
}

export type SelectItemProps = React.ComponentProps<typeof SelectPrimitive.Item>;

function SelectItem({
  className,
  children,
  ...props
}: SelectItemProps): ReactElement {
  return (
    <SelectPrimitive.Item
      className={cn(
        "relative flex w-full cursor-default items-center gap-2 py-1.5 pr-8 pl-2 text-body-small outline-hidden select-none data-highlighted:bg-primary/5 data-highlighted:text-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
        className,
      )}
      data-slot="select-item"
      {...props}
    >
      <span
        className="absolute right-2 flex size-3.5 items-center justify-center"
        data-slot="select-item-indicator"
      >
        <SelectPrimitive.ItemIndicator>
          <CheckIcon className="size-4" />
        </SelectPrimitive.ItemIndicator>
      </span>
      <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
    </SelectPrimitive.Item>
  );
}

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

function SelectSeparator({
  className,
  ...props
}: SelectSeparatorProps): ReactElement {
  return (
    <div
      className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
      data-slot="select-separator"
      role="separator"
      {...props}
    />
  );
}

export type SelectScrollUpButtonProps = React.ComponentProps<
  typeof SelectPrimitive.ScrollUpArrow
>;

function SelectScrollUpButton({
  className,
  ...props
}: SelectScrollUpButtonProps): ReactElement {
  return (
    <SelectPrimitive.ScrollUpArrow
      className={cn(
        "flex cursor-default items-center justify-center py-1",
        className,
      )}
      data-slot="select-scroll-up-button"
      {...props}
    >
      <ChevronUpIcon className="size-4" />
    </SelectPrimitive.ScrollUpArrow>
  );
}

export type SelectScrollDownButtonProps = React.ComponentProps<
  typeof SelectPrimitive.ScrollDownArrow
>;

function SelectScrollDownButton({
  className,
  ...props
}: SelectScrollDownButtonProps): ReactElement {
  return (
    <SelectPrimitive.ScrollDownArrow
      className={cn(
        "flex cursor-default items-center justify-center py-1",
        className,
      )}
      data-slot="select-scroll-down-button"
      {...props}
    >
      <ChevronDownIcon className="size-4" />
    </SelectPrimitive.ScrollDownArrow>
  );
}

export {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectPortalProvider,
  SelectScrollDownButton,
  SelectScrollUpButton,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
};
