"use client";
import React from "react";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { focusedDisabled, paperMixin } from "../styles";
import { cls } from "../util";
import { usePortalContainer } from "../hooks/PortalContainerContext";

export type MenuProps = {
    children: React.ReactNode;
    trigger: React.ReactNode;

    open?: boolean;
    defaultOpen?: boolean;
    onOpenChange?(open: boolean): void;

    portalContainer?: HTMLElement | null;
    side?: "top" | "right" | "bottom" | "left";
    align?: "start" | "center" | "end";

    sideOffset?: number;
    className?: string;
}

const Menu = React.forwardRef<
    React.ElementRef<typeof DropdownMenu.Trigger>,
    MenuProps
>(({
       children,
       trigger,
       open,
       defaultOpen,
       side,
       align,
       onOpenChange,
       portalContainer,
       sideOffset = 4,
       className
   }, ref) => {
    // Get the portal container from context
    const contextContainer = usePortalContainer();

    // Prioritize manual prop, fallback to context container
    const finalContainer = (portalContainer ?? contextContainer ?? undefined) as HTMLElement | undefined;

    return (
        <DropdownMenu.Root
            open={open}
            defaultOpen={defaultOpen}
            onOpenChange={onOpenChange}>
            <DropdownMenu.Trigger
                ref={ref}
                asChild>
                {trigger}
            </DropdownMenu.Trigger>
            <DropdownMenu.Portal container={finalContainer}>
                <DropdownMenu.Content
                    side={side}
                    sideOffset={sideOffset}
                    align={align}
                    // `z-50` is the floating layer — the tier `Dialog`, `Sheet`,
                    // `Select` and `Tooltip` all sit on. Radix copies this value
                    // onto the popper wrapper it portals next to them, so at any
                    // lower value the menu opens *behind* the dialog or sheet it
                    // was opened from: visible in the DOM, painted under the
                    // overlay, and unclickable. Peers on this tier stack by mount
                    // order, which is what puts a menu above the dialog holding
                    // its trigger, and a dialog that menu opens above them both.
                    className={cls(paperMixin, focusedDisabled, "py-2 z-50", className)}>
                    {children}
                </DropdownMenu.Content>
            </DropdownMenu.Portal>
        </DropdownMenu.Root>
    );
})
Menu.displayName = "Menu"

export { Menu }

export type MenuItemProps = {
    children: React.ReactNode;
    dense?: boolean;
    disabled?: boolean;
    onClick?: (event: React.MouseEvent) => void;
    className?: string;
};

export const MenuItem = React.memo(({
                                        children,
                                        dense = false, // Default value is false if not provided
                                        disabled = false,
                                        onClick,
                                        className
                                    }: MenuItemProps) => {
    // Dynamically adjusting the class based on the "dense" prop
    const classNames = cls(
        onClick && !disabled && "cursor-pointer",
        disabled && "opacity-50 cursor-not-allowed",
        "rounded-md text-sm font-medium text-surface-accent-700 dark:text-surface-accent-300 flex items-center gap-4 transition-colors duration-150",
        !disabled && "hover:bg-surface-accent-100 dark:hover:bg-surface-accent-900",
        dense ? "px-4 py-1.5" : "px-4 py-2",
        className
    );

    return (
        <DropdownMenu.Item
            className={classNames}
            disabled={disabled}
            onClick={disabled ? undefined : onClick}>
            {children}
        </DropdownMenu.Item>
    );
});

MenuItem.displayName = "MenuItem";
