import * as React from 'react'
import { type ReactNode, useEffect, useRef } from 'react'
import ReactDOM from 'react-dom'

import { Button } from '@components/ui/button/button'

/**
 * An entry in the context menu.
 */
export type ContextMenuAction = {
  link?: ReactNode

  /**
   * If true, the action will be disabled and not clickable.
   */
  disabled?: boolean
}

export type ContextMenuConfig = {
  /**
   * Array of actions to be displayed in the context menu.
   */
  actions: ContextMenuAction[]

  /**
   * Position of the context menu on the screen.
   * If null, the menu will not be displayed.
   * The position should be an object with absolute x and y coordinates.
   */
  position: { x: number; y: number } | null
}

type ContextMenuProps = ContextMenuConfig & {
  /**
   * Callback function to be called when the context menu is closed.
   */
  onClose: () => void
}

/**
 * ContextMenu Component
 *
 * A floating menu that displays a list of actions at a specified position on the screen.
 * The menu closes when clicking outside of it or pressing the Escape key.
 *
 * Props:
 * - actions: An array of Links, optional disabled state, and optional icon.
 * - position: An object with x and y coordinates specifying the position of the menu, or null to hide the menu.
 * - onClose: A callback function triggered when the menu is closed.
 *
 * Example usage:
 *
 * const actions = [
 *   { label: 'Edit', onClick: () => console.log('Edit clicked') },
 *   { label: 'Delete', onClick: () => console.log('Delete clicked'), disabled: true },
 * ]
 *
 * const [menuPosition, setMenuPosition] = useState<{ x: number; y: number } | null>(null);
 *
 * return (
 *   <div
 *     onContextMenu={(e) => {
 *       e.preventDefault();
 *       setMenuPosition({ x: e.clientX, y: e.clientY });
 *     }}
 *   >
 *     <p>Right-click to open the context menu.</p>
 *     <ContextMenu
 *       actions={actions}
 *       position={menuPosition}
 *       onClose={() => setMenuPosition(null)}
 *     />
 *   </div>
 * );
 */

export const ContextMenuSimple = ({ actions, position, onClose }: ContextMenuProps) => {
  const menuRef = useRef<HTMLDivElement | null>(null)

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
        event.preventDefault()
        event.stopPropagation()
        onClose()
      }
    }

    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        onClose()
      }
    }

    document.addEventListener('mousedown', handleClickOutside, true)
    document.addEventListener('keydown', handleEscape)

    return () => {
      document.removeEventListener('mousedown', handleClickOutside, true)
      document.removeEventListener('keydown', handleEscape)
    }
  }, [onClose])

  if (!position) {
    return null
  }

  return ReactDOM.createPortal(
    <div
      ref={menuRef}
      style={
        {
          '--wrapper-x': `${position.x}px`,
          '--wrapper-y': `${position.y}px`,
        } as React.CSSProperties
      }
      className={`top-(--wrapper-y) left-(--wrapper-x) fixed bg-background border border-(--discreet-border) shadow-md min-w-[150px] z-50`}
    >
      <div className="flex flex-col gap-1">
        {actions.map((action, index) => (
          <Button
            asChild
            key={`btn-${index}_${action.disabled}`}
            onClick={() => {
              if (!action.disabled) {
                onClose()
              }
            }}
            disabled={action.disabled}
            __e2e_test_id__={`context-menu-item-${index}`}
            variant="ghost"
            className={`w-full justify-start`}
          >
            {action.link}
          </Button>
        ))}
      </div>
    </div>,
    document.body,
  )
}
