'use client';

import { Button } from '@/components/actions/Button';
import { useEscapeKey, useOutsideClick } from '@/components/foundation/client-hooks';
import { classNames } from '@/lib/components/classNames';
import { useRef, useState, type KeyboardEvent } from 'react';
import styles from './DropdownMenu.module.css';

export interface MenuItem {
  id: string;
  label: string;
  onSelect: () => void;
  disabled?: boolean;
  destructive?: boolean;
}

interface DropdownMenuProps {
  label: string;
  items: MenuItem[];
  className?: string;
}

export function DropdownMenu({ label, items, className }: DropdownMenuProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);
  const itemRefs = useRef<Array<HTMLButtonElement | null>>([]);
  useOutsideClick(rootRef, () => setOpen(false), open);
  useEscapeKey(() => setOpen(false), open);

  const focusItem = (index: number) => {
    const enabled = items
      .map((item, itemIndex) => ({ item, itemIndex }))
      .filter(({ item }) => !item.disabled);
    const target = enabled[(index + enabled.length) % enabled.length];
    if (target) itemRefs.current[target.itemIndex]?.focus();
  };

  const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
    const currentIndex = itemRefs.current.findIndex((node) => node === document.activeElement);
    if (event.key === 'ArrowDown') {
      event.preventDefault();
      focusItem(currentIndex + 1);
    } else if (event.key === 'ArrowUp') {
      event.preventDefault();
      focusItem(currentIndex - 1);
    } else if (event.key === 'Home') {
      event.preventDefault();
      focusItem(0);
    } else if (event.key === 'End') {
      event.preventDefault();
      focusItem(items.length - 1);
    }
  };

  return (
    <div ref={rootRef} className={classNames(styles.root, className)} onKeyDown={handleKeyDown}>
      <Button
        intent="tertiary"
        trailingIcon="chevron-down"
        aria-haspopup="menu"
        aria-expanded={open}
        onClick={() => setOpen((value) => !value)}
      >
        {label}
      </Button>
      {open ? (
        <div className={styles.menu} role="menu">
          {items.map((item, index) => (
            <button
              key={item.id}
              ref={(node) => {
                itemRefs.current[index] = node;
              }}
              type="button"
              role="menuitem"
              disabled={item.disabled}
              className={classNames(styles.item, item.destructive && styles.destructive)}
              onClick={() => {
                item.onSelect();
                setOpen(false);
              }}
            >
              {item.label}
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}
