import { Check, CaretDown } from "@phosphor-icons/react";
import { useEffect, useRef, useState } from "react";

export type BottomControlSelectOption<TValue extends string> = {
  value: TValue;
  label: string;
};

export type BottomControlSelectMenuProps<TValue extends string> = {
  value: TValue;
  options: readonly BottomControlSelectOption<TValue>[];
  "aria-label": string;
  onValueChange: (value: TValue) => void;
};

export function BottomControlSelectMenu<TValue extends string>({ value, options, onValueChange, ...props }: BottomControlSelectMenuProps<TValue>) {
  const rootRef = useRef<HTMLDivElement>(null);
  const [open, setOpen] = useState(false);
  const selectedOption = options.find((option) => option.value === value) ?? options[0];

  useEffect(() => {
    if (!open) return;

    const handlePointerDown = (event: PointerEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
    };

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };

    window.addEventListener("pointerdown", handlePointerDown);
    window.addEventListener("keydown", handleKeyDown);
    return () => {
      window.removeEventListener("pointerdown", handlePointerDown);
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [open]);

  return (
    <div ref={rootRef} className="relative">
      <button
        type="button"
        className="inline-flex h-10 min-w-32 items-center rounded-full text-base text-white/85 transition hover:bg-white/10 hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30"
        aria-label={props["aria-label"]}
        aria-haspopup="listbox"
        aria-expanded={open}
        onClick={() => setOpen((current) => !current)}
      >
        <span className="min-w-0 flex-1 px-4 text-left">{selectedOption?.label}</span>
        <span className="grid size-10 flex-none place-items-center text-white/60">
          <CaretDown size={18} weight="bold" />
        </span>
      </button>
      {open ? (
        <div className="absolute bottom-full left-0 z-30 mb-3 min-w-full rounded-[1.5rem] p-1 text-white backdrop-blur-xl" role="listbox" aria-label={props["aria-label"]}>
          {options.map((option) => {
            const selected = option.value === value;
            return (
              <button
                key={option.value}
                type="button"
                className={`flex h-10 w-full items-center gap-3 rounded-full px-3 text-left text-sm transition ${selected ? "bg-white text-black" : "text-white/80 hover:bg-white/10 hover:text-white"}`}
                role="option"
                aria-selected={selected}
                onClick={() => {
                  onValueChange(option.value);
                  setOpen(false);
                }}
              >
                <span className="grid size-5 place-items-center">{selected ? <Check size={16} weight="bold" /> : null}</span>
                <span className="min-w-0 flex-1 whitespace-nowrap">{option.label}</span>
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}
