import { useTheme } from '@wise/components-theming';
import { clsx } from 'clsx';
import { useRef, useState, cloneElement, useEffect, isValidElement, useId } from 'react';

import { Position, Typography } from '../common';
import ResponsivePanel from '../common/responsivePanel';
import Title from '../title';
import { logActionRequired } from '../utilities';

/** @deprecated Use `"top" | "bottom"` instead. */
type PopoverPreferredPlacementDeprecated =
  | `${Position.LEFT_TOP}`
  | `${Position.RIGHT_TOP}`
  | `${Position.BOTTOM_RIGHT}`
  | `${Position.BOTTOM_LEFT}`;

export type PopoverPreferredPlacement =
  | `${Position.TOP}`
  | `${Position.RIGHT}`
  | `${Position.BOTTOM}`
  | `${Position.LEFT}`
  | PopoverPreferredPlacementDeprecated;

export interface PopoverProps {
  children?: React.ReactNode;
  title?: React.ReactNode;
  /** Screen-reader-friendly title. Must be provided if `title` prop is not set. */
  'aria-label'?: string;
  /** @default 'right' */
  preferredPlacement?: PopoverPreferredPlacement;
  content: React.ReactNode;
  onClose?: () => void;
  className?: string;
}

function resolvePlacement(preferredPlacement: PopoverPreferredPlacement) {
  switch (preferredPlacement) {
    case 'left-top':
    case 'right-top':
      return 'top';
    case 'bottom-left':
    case 'bottom-right':
      return 'bottom';
    default:
      return preferredPlacement;
  }
}

export default function Popover({
  children,
  className,
  content,
  preferredPlacement = Position.RIGHT,
  title,
  onClose,
  'aria-label': ariaLabel,
}: PopoverProps) {
  const titleId = useId();

  const resolvedPlacement = resolvePlacement(preferredPlacement);
  useEffect(() => {
    if (resolvedPlacement !== preferredPlacement) {
      logActionRequired(
        `Popover has deprecated ${preferredPlacement} value for the 'preferredPlacement' prop. Please use ${resolvedPlacement} instead.`,
      );
    }
  }, [preferredPlacement, resolvedPlacement]);

  const anchorReference = useRef(null);
  const [open, setOpen] = useState(false);

  const handleOnClose = () => {
    setOpen(false);
    onClose?.();
  };

  return (
    <span className={clsx('np-popover', className)}>
      <span ref={anchorReference} className="d-inline-block">
        {isValidElement<{ onClick?: () => void }>(children)
          ? cloneElement(children, {
              onClick: () => {
                children.props.onClick?.();
                setOpen((prevOpen) => !prevOpen);
              },
            })
          : children}
      </span>
      <ResponsivePanel
        aria-label={ariaLabel}
        aria-labelledby={title && !ariaLabel ? titleId : undefined}
        open={open}
        anchorRef={anchorReference}
        position={resolvedPlacement}
        arrow
        className="np-popover__container"
        onClose={handleOnClose}
      >
        <div className="np-popover__content np-text-default-body">
          {title && (
            <Title type={Typography.TITLE_BODY} id={titleId} className="m-b-1">
              {title}
            </Title>
          )}
          {content}
        </div>
      </ResponsivePanel>
    </span>
  );
}
