import React, { useState } from 'react';
import cx from 'classnames';
import { BsOverlayTrigger, BsPopover } from '../bootstrap';
import { usePageContext } from '../pageContext';
import type { ComponentBaseProps } from '../../types';
export const CLASSNAME = 'Popover';

type Placement = React.ComponentProps<typeof BsPopover>['placement'];
type Container = React.ComponentProps<typeof BsOverlayTrigger>['container'];

export interface PopoverProps extends ComponentBaseProps {
    /**
     * Unique identifier of the popover
     */
    id: string;

    /**
     * The class name of the popover content
     */
    contentClassName?: string;

    /**
     * The content of the popover
     */
    content: JSX.Element;

    /**
     * The container used to render the popover (only for rare custom implementation)
     */
    container?: Container;

    /**
     * The placement of the popover message in relation to the triggering child
     */
    placement?: Placement;

    /**
     * Set manually the visibility of the popover content
     */
    show?: boolean;

    /**
     * Determines the amount of padding of the popover.
     * @default 'standard'
     */
    variant?: 'standard' | 'list';

    /**
     * Controls whether the tooltip can automatically flip to the opposite placement (e.g., top to bottom) if there's not enough space.
     */
    flip?: boolean;

    /**
     * Content of the popover trigger
     */
    children?: React.ReactNode | React.FC<{ isOpen: boolean }>;
}

/**
 * Popovers are floating containers attached to a specific UI element and triggered on click. They are used to add secondary information or actions to the UI element they are attached to.
 *
 * @type organism
 * @status live
 * @tags overlays
 */
export const Popover: React.FC<PopoverProps> = ({
    id,
    className,
    contentClassName,
    content,
    container,
    placement = 'top',
    testId = CLASSNAME,
    children,
    show,
    variant = 'standard',
    flip,
}) => {
    const page = usePageContext();
    const [toggleState, setToggleState] = useState(show ?? false);
    const isOpen = show ?? toggleState;

    return (
        <BsOverlayTrigger
            show={show}
            container={container}
            trigger="click"
            placement={placement}
            rootClose={show === undefined}
            onToggle={setToggleState}
            flip={flip}
            overlay={
                <BsPopover
                    id={`${id}-Popover`}
                    data-testid={`${id}-PopoverOverlay`}
                    className={cx('PopoverOverlay', page.className)}
                >
                    <BsPopover.Content
                        className={cx(
                            'PopoverContent',
                            contentClassName,
                            `PopoverContent-${variant}`
                        )}
                    >
                        {content}
                    </BsPopover.Content>
                </BsPopover>
            }
        >
            {({ ref, ...triggerHandler }) => (
                <div
                    id={id}
                    data-testid={testId}
                    className={cx(CLASSNAME, className)}
                    ref={ref}
                    {...triggerHandler}
                >
                    {typeof children === 'function' ? children({ isOpen }) : children}
                </div>
            )}
        </BsOverlayTrigger>
    );
};
