"use client";
import React from "react";
import * as PopoverPrimitive from "@radix-ui/react-popover";

import { paperMixin } from "../styles";
import { cls } from "../util";
import { useInjectStyles } from "../hooks";
import { usePortalContainer } from "../hooks/PortalContainerContext";

export type PopoverSide = "top" | "right" | "bottom" | "left";
export type PopoverAlign = "start" | "center" | "end";

export interface PopoverProps {
    trigger: React.ReactNode;
    children: React.ReactNode;
    open?: boolean;
    onOpenChange?: (open: boolean) => void;
    side?: PopoverSide;
    sideOffset?: number;
    align?: PopoverAlign;
    alignOffset?: number;
    arrowPadding?: number;
    sticky?: "partial" | "always";
    hideWhenDetached?: boolean;
    avoidCollisions?: boolean;
    enabled?: boolean;
    modal?: boolean;
    className?: string;
    portalContainer?: HTMLElement | null;
    onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
    onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
}

export function Popover({
                            trigger,
                            children,
                            open,
                            onOpenChange,
                            side,
                            sideOffset = 5,
                            align,
                            alignOffset,
                            arrowPadding,
                            sticky,
                            hideWhenDetached,
                            avoidCollisions,
                            enabled = true,
                            modal = false,
                            portalContainer,
                            className,
                            onMouseEnter,
                            onMouseLeave
                        }: PopoverProps) {

    useInjectStyles("Popover", popoverStyles);

    // Get the portal container from context
    const contextContainer = usePortalContainer();

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

    if (!enabled)
        return <>{trigger}</>;

    return <PopoverPrimitive.Root open={open}
                                  onOpenChange={onOpenChange}
                                  modal={modal}>

        <PopoverPrimitive.Trigger asChild>
            {trigger}
        </PopoverPrimitive.Trigger>

        <PopoverPrimitive.Portal container={finalContainer}>
            <PopoverPrimitive.Content
                // `z-50`, the floating layer — see the note in `Menu`. Below it
                // a popover opened from inside a dialog or a side panel is
                // painted under the thing that owns its trigger.
                className={cls(paperMixin,
                    "PopoverContent z-50", className)}
                side={side}
                sideOffset={sideOffset}
                align={align}
                alignOffset={alignOffset}
                arrowPadding={arrowPadding}
                sticky={sticky}
                hideWhenDetached={hideWhenDetached}
                avoidCollisions={avoidCollisions}
                onMouseEnter={onMouseEnter}
                onMouseLeave={onMouseLeave}>

                {children}
                <PopoverPrimitive.Arrow className="fill-white dark:fill-surface-900"/>
            </PopoverPrimitive.Content>
        </PopoverPrimitive.Portal>
    </PopoverPrimitive.Root>;
}

const popoverStyles = `
/* ... (styles remain unchanged) ... */
.PopoverContent {
  animation-duration: 400ms;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform, opacity;
}
.PopoverContent[data-state='open'][data-side='top'] {
  animation-name: slideDownAndFade;
}
.PopoverContent[data-state='open'][data-side='right'] {
  animation-name: slideLeftAndFade;
}
.PopoverContent[data-state='open'][data-side='bottom'] {
  animation-name: slideUpAndFade;
}
.PopoverContent[data-state='open'][data-side='left'] {
  animation-name: slideRightAndFade;
}

@keyframes slideUpAndFade {
  from {
    opacity: 0;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideRightAndFade {
  from {
    opacity: 0;
    transform: translateX(-2px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes slideDownAndFade {
  from {
    opacity: 0;
    transform: translateY(-2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideLeftAndFade {
  from {
    opacity: 0;
    transform: translateX(2px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
`;
