"use client";

import clsx from "clsx";
import { useEffect, useId, useRef, useState, type ReactNode } from "react";

/** Small accessible dropdown menu: a trigger button plus a list of actions. */
export function Menu({ trigger, items, align = "right" }: { trigger: (props: { onClick: () => void; "aria-expanded": boolean; "aria-haspopup": "menu"; "aria-controls": string }) => ReactNode; items: { label: string; hint?: string; icon?: ReactNode; onSelect: () => void }[]; align?: "left" | "right" }) {
  const [open, setOpen] = useState(false);
  const id = useId();
  const box = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (!open) return;
    const onDown = (e: MouseEvent) => box.current && !box.current.contains(e.target as Node) && setOpen(false);
    const onKey = (e: KeyboardEvent) => e.key === "Escape" && setOpen(false);
    document.addEventListener("mousedown", onDown);
    document.addEventListener("keydown", onKey);
    box.current?.querySelector<HTMLElement>("[role=menuitem]")?.focus();
    return () => {
      document.removeEventListener("mousedown", onDown);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);
  return (
    <div className="relative" ref={box}>
      {trigger({ onClick: () => setOpen((o) => !o), "aria-expanded": open, "aria-haspopup": "menu", "aria-controls": id })}
      {open && (
        <div
          id={id}
          role="menu"
          className={clsx("absolute z-40 mt-2 w-72 rounded-lg border border-line bg-white p-1 shadow-lg", align === "right" ? "right-0" : "left-0")}
          onKeyDown={(e) => {
            const items = [...(e.currentTarget.querySelectorAll<HTMLElement>("[role=menuitem]") ?? [])];
            const i = items.indexOf(document.activeElement as HTMLElement);
            if (e.key === "ArrowDown") items[(i + 1) % items.length]?.focus();
            if (e.key === "ArrowUp") items[(i - 1 + items.length) % items.length]?.focus();
          }}
        >
          {items.map((it) => (
            <button
              key={it.label}
              role="menuitem"
              type="button"
              onClick={() => {
                setOpen(false);
                it.onSelect();
              }}
              className="flex w-full items-start gap-3 rounded-md px-3 py-2 text-left hover:bg-paper focus:bg-paper focus:outline-none"
            >
              {it.icon && <span className="mt-0.5 text-teal [&_svg]:size-4">{it.icon}</span>}
              <span>
                <span className="block text-sm font-medium">{it.label}</span>
                {it.hint && <span className="block text-xs text-muted">{it.hint}</span>}
              </span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}
