/**
 * Dropdown - Dropdown menu component with positioning
 * G-011: Accessible dropdown menus and popovers
 */

import { useState, useRef, useEffect, ReactNode, createContext, useContext } from 'react';
import clsx from 'clsx';

// Context for dropdown state
interface DropdownContextValue {
  isOpen: boolean;
  close: () => void;
}

const DropdownContext = createContext<DropdownContextValue | null>(null);

function useDropdownContext() {
  const context = useContext(DropdownContext);
  if (!context) {
    throw new Error('Dropdown components must be used within a Dropdown');
  }
  return context;
}

// Types
type DropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';

interface DropdownProps {
  children: ReactNode;
  className?: string;
}

interface DropdownTriggerProps {
  children: ReactNode;
  asChild?: boolean;
  className?: string;
}

interface DropdownContentProps {
  children: ReactNode;
  placement?: DropdownPlacement;
  align?: 'start' | 'end';
  className?: string;
  minWidth?: number;
}

interface DropdownItemProps {
  children: ReactNode;
  onClick?: () => void;
  disabled?: boolean;
  danger?: boolean;
  icon?: ReactNode;
  className?: string;
}

/**
 * Dropdown container component
 */
export function Dropdown({ children, className }: DropdownProps) {
  const [isOpen, setIsOpen] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);

  const close = () => setIsOpen(false);
  const toggle = () => setIsOpen((prev) => !prev);

  // Close on click outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        close();
      }
    };

    if (isOpen) {
      document.addEventListener('mousedown', handleClickOutside);
    }

    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [isOpen]);

  // Close on escape key
  useEffect(() => {
    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        close();
      }
    };

    if (isOpen) {
      document.addEventListener('keydown', handleEscape);
    }

    return () => {
      document.removeEventListener('keydown', handleEscape);
    };
  }, [isOpen]);

  return (
    <DropdownContext.Provider value={{ isOpen, close }}>
      <div ref={dropdownRef} className={clsx('relative inline-block', className)}>
        {/* Inject toggle function to trigger */}
        {Array.isArray(children)
          ? children.map((child, index) => {
              if (index === 0 && typeof child === 'object' && child !== null) {
                return (
                  <div key={index} onClick={toggle}>
                    {child}
                  </div>
                );
              }
              return child;
            })
          : children}
      </div>
    </DropdownContext.Provider>
  );
}

/**
 * Dropdown trigger button
 */
export function DropdownTrigger({ children, className }: DropdownTriggerProps) {
  return (
    <div className={clsx('cursor-pointer', className)} role="button" tabIndex={0}>
      {children}
    </div>
  );
}

/**
 * Dropdown content container
 */
export function DropdownContent({
  children,
  placement = 'bottom-start',
  className,
  minWidth = 180,
}: DropdownContentProps) {
  const { isOpen } = useDropdownContext();

  if (!isOpen) return null;

  const placementClasses: Record<DropdownPlacement, string> = {
    'bottom-start': 'top-full left-0 mt-1',
    'bottom-end': 'top-full right-0 mt-1',
    'top-start': 'bottom-full left-0 mb-1',
    'top-end': 'bottom-full right-0 mb-1',
  };

  return (
    <div
      className={clsx(
        'absolute z-dropdown',
        placementClasses[placement],
        'bg-surface-popover dark:bg-surface-popover',
        'border border-border dark:border-border',
        'rounded-lg shadow-lg',
        'py-1',
        'animate-in fade-in-0 zoom-in-95 duration-150',
        className
      )}
      style={{ minWidth }}
      role="menu"
      aria-orientation="vertical"
    >
      {children}
    </div>
  );
}

/**
 * Dropdown menu item
 */
export function DropdownItem({
  children,
  onClick,
  disabled = false,
  danger = false,
  icon,
  className,
}: DropdownItemProps) {
  const { close } = useDropdownContext();

  const handleClick = () => {
    if (disabled) return;
    onClick?.();
    close();
  };

  return (
    <button
      type="button"
      onClick={handleClick}
      disabled={disabled}
      role="menuitem"
      className={clsx(
        'w-full flex items-center gap-2 px-3 py-2 text-sm text-left',
        'transition-colors duration-150',
        disabled
          ? 'text-foreground-subtle cursor-not-allowed opacity-50'
          : danger
          ? 'text-danger hover:bg-danger/10 dark:hover:bg-danger/20'
          : 'text-foreground dark:text-foreground hover:bg-background-muted dark:hover:bg-background-muted',
        className
      )}
    >
      {icon && <span className="w-4 h-4 flex-shrink-0">{icon}</span>}
      {children}
    </button>
  );
}

/**
 * Dropdown separator
 */
export function DropdownSeparator({ className }: { className?: string }) {
  return (
    <div
      className={clsx('my-1 border-t border-border dark:border-border', className)}
      role="separator"
    />
  );
}

/**
 * Dropdown label (non-interactive)
 */
export function DropdownLabel({
  children,
  className,
}: {
  children: ReactNode;
  className?: string;
}) {
  return (
    <div
      className={clsx(
        'px-3 py-1.5 text-xs font-semibold uppercase tracking-wider',
        'text-foreground-muted dark:text-foreground-muted',
        className
      )}
    >
      {children}
    </div>
  );
}

/**
 * Simple Menu component (pre-composed dropdown)
 */
interface MenuProps {
  trigger: ReactNode;
  items: Array<{
    label: string;
    onClick: () => void;
    icon?: ReactNode;
    disabled?: boolean;
    danger?: boolean;
    separator?: boolean;
  }>;
  placement?: DropdownPlacement;
  className?: string;
}

export function Menu({ trigger, items, placement = 'bottom-end', className }: MenuProps) {
  return (
    <Dropdown className={className}>
      <DropdownTrigger>{trigger}</DropdownTrigger>
      <DropdownContent placement={placement}>
        {items.map((item, index) => (
          <div key={index}>
            {item.separator && <DropdownSeparator />}
            {!item.separator && (
              <DropdownItem
                onClick={item.onClick}
                icon={item.icon}
                disabled={item.disabled}
                danger={item.danger}
              >
                {item.label}
              </DropdownItem>
            )}
          </div>
        ))}
      </DropdownContent>
    </Dropdown>
  );
}

export default Dropdown;
