import React, { useState, useRef, useEffect, useCallback } from "react";
import DownloadButton from "./DownloadButton";

export default function DownloadDropdown({ options, title, author }) {
  const [isOpen, setIsOpen] = useState(false);
  const containerRef = useRef(null);
  const triggerRef = useRef(null);
  const menuRef = useRef(null);

  const close = useCallback((returnFocus) => {
    setIsOpen(false);
    if (returnFocus) triggerRef.current?.focus();
  }, []);

  // Close when a click or focus lands outside the dropdown, so the menu cannot
  // be left hanging open after tabbing or clicking away.
  useEffect(() => {
    if (!isOpen) return;

    const closeIfOutside = (event) => {
      if (!containerRef.current?.contains(event.target)) setIsOpen(false);
    };

    document.addEventListener("pointerdown", closeIfOutside);
    document.addEventListener("focusin", closeIfOutside);
    return () => {
      document.removeEventListener("pointerdown", closeIfOutside);
      document.removeEventListener("focusin", closeIfOutside);
    };
  }, [isOpen]);

  const menuItems = () =>
    Array.from(menuRef.current?.querySelectorAll('[role="menuitem"]') || []);

  const focusItem = (index) => {
    const items = menuItems();
    if (!items.length) return;
    items[(index + items.length) % items.length].focus();
  };

  const handleTriggerKeyDown = (event) => {
    if (event.key === "ArrowUp" || event.key === "ArrowDown") {
      event.preventDefault();
      setIsOpen(true);
      // The menu opens upward, so ArrowUp enters it at the item nearest the button.
      const target = event.key === "ArrowUp" ? -1 : 0;
      requestAnimationFrame(() => focusItem(target));
    } else if (event.key === "Escape" && isOpen) {
      event.preventDefault();
      close(false);
    }
  };

  const handleMenuKeyDown = (event) => {
    const items = menuItems();
    const current = items.indexOf(document.activeElement);

    switch (event.key) {
      case "ArrowDown":
        event.preventDefault();
        focusItem(current + 1);
        break;
      case "ArrowUp":
        event.preventDefault();
        focusItem(current - 1);
        break;
      case "Home":
        event.preventDefault();
        focusItem(0);
        break;
      case "End":
        event.preventDefault();
        focusItem(-1);
        break;
      case "Escape":
        event.preventDefault();
        close(true);
        break;
      case "Tab":
        // Let focus move on naturally, but do not leave the menu open behind it.
        setIsOpen(false);
        break;
      default:
        break;
    }
  };

  return (
    <div
      ref={containerRef}
      className="relative"
      onMouseEnter={() => setIsOpen(true)}
      onMouseLeave={() => setIsOpen(false)}
    >
      <button
        ref={triggerRef}
        type="button"
        className="flex items-center justify-center h-9 px-3 rounded-md bg-gray-100 text-gray-700 border-0 cursor-pointer hover:bg-gray-200 transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-600"
        aria-haspopup="menu"
        aria-expanded={isOpen}
        aria-label="Download size options"
        onClick={() => setIsOpen(!isOpen)}
        onKeyDown={handleTriggerKeyDown}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width={16}
          height={16}
          fill="none"
          viewBox="0 0 24 24"
          aria-hidden="true"
          className={`transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
        >
          <path
            stroke="currentColor"
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2.5}
            d="m19 9-7 7-7-7"
          />
        </svg>
      </button>

      {isOpen && (
        /*
         * The gap above the trigger is padding on this wrapper, not a margin on
         * the panel, so it stays inside the hover area. With a margin the cursor
         * crossed dead space on its way to the menu, which fired mouseleave and
         * closed it before it could be reached.
         */
        <div
          className="absolute right-0 bottom-full pb-2 z-[100]"
          onMouseEnter={() => setIsOpen(true)}
          onMouseLeave={() => setIsOpen(false)}
        >
          <div
            ref={menuRef}
            role="menu"
            aria-label="Download size options"
            onKeyDown={handleMenuKeyDown}
            className="relative bg-white min-w-[180px] rounded-xl shadow-xl border border-gray-200 py-2"
            style={{ animation: 'fadeInUp 0.2s ease-out' }}
          >
            {/* Arrow pointing down */}
            <div className="absolute -bottom-1.5 right-4 w-3 h-3 bg-white border-r border-b border-gray-200 transform rotate-45"></div>

            {options.map((opt) => (
              <DownloadButton
                key={opt.label}
                label={opt.label}
                type={opt.type}
                url={opt.url}
                title={title}
                author={author}
                role="menuitem"
                onActivate={() => close(true)}
              />
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
