"use client";

import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from "react";
import Select, { type SingleValue } from "react-select";
import { cn } from "@/lib/utils";
import { SEARCHABLE_SELECT_COMPONENTS } from "@/components/common/SearchableSelectParts";
import { useControlledSelectMenu } from "@/hooks/useControlledSelectMenu";
import type { ApiCountry } from "@/api/profile.api";

interface CountryOption {
  value: string;
  label: string;
}

interface Props {
  countries: ApiCountry[];
  value: string;
  onChange: (val: string) => void;
  placeholder?: string;
  disabled?: boolean;
  label?: string;
}

export interface CountrySelectHandle {
  /** Force the menu shut — for callers (e.g. a closing modal) that can't rely on blur/outside-click. */
  closeMenu: () => void;
}

export const CountrySelect = forwardRef<CountrySelectHandle, Props>(function CountrySelect(
  { countries, value, onChange, placeholder, disabled, label },
  ref,
) {
  const [search, setSearch] = useState("");
  const countryRef = useRef<HTMLDivElement>(null);
  const countryMenu = useControlledSelectMenu(countryRef, "select-menu-portal");

  useImperativeHandle(ref, () => ({
    closeMenu: () => countryMenu.onMenuClose(),
  }), [countryMenu]);

  const options: CountryOption[] = useMemo(
    () => countries.map((c) => ({ value: c.name, label: c.name })),
    [countries],
  );

  const selected = useMemo(() => options.find((o) => o.value === value) ?? null, [options, value]);

  return (
    <div className="space-y-1.5">
      {label && (
        <span className="block text-[length:var(--text-sm-fixed)] font-medium capitalize text-slate-500 dark:text-slate-400">
          {label}
        </span>
      )}
      <div className="rs-wrapper" ref={countryRef}>
        <Select<CountryOption>
          unstyled
          isSearchable
          isDisabled={disabled}
          menuIsOpen={countryMenu.menuIsOpen}
          onMenuOpen={countryMenu.onMenuOpen}
          inputValue={search}
          onInputChange={(val, { action }) => { if (action === "input-change") setSearch(val); }}
          onMenuClose={() => { countryMenu.onMenuClose(); setSearch(""); }}
          components={SEARCHABLE_SELECT_COMPONENTS}
          options={options}
          value={selected}
          onChange={(opt: SingleValue<CountryOption>) => onChange(opt?.value ?? "")}
          placeholder={placeholder ?? ""}
          menuPortalTarget={typeof document !== "undefined" ? document.body : undefined}
          menuPosition="fixed"
          styles={{ menuPortal: (base) => ({ ...base, zIndex: 9999 }) }}
          classNames={{
            control: ({ menuIsOpen }) =>
              cn(
                "h-11 w-full cursor-pointer border bg-white px-3 text-sm text-slate-900 transition-[border-radius] duration-150 dark:bg-slate-900 dark:text-white",
                menuIsOpen ? "rounded-t-2xl rounded-b-none" : "rounded-2xl",
                "border-slate-200 dark:border-slate-700",
                disabled && "cursor-not-allowed opacity-50",
              ),
            menu: () =>
              "select-menu-portal overflow-hidden rounded-b-2xl border border-t-0 border-slate-200 bg-white shadow-card dark:border-slate-700 dark:bg-slate-900",
            menuList: () => "max-h-60 overflow-y-auto overflow-x-hidden py-1",
            // Plain string, not cn()/twMerge — this runs once per rendered option, so on a
            // ~200-country list it's the hot path on every keystroke while filtering.
            option: ({ isFocused, isSelected }) =>
              `cursor-pointer px-4 py-2.5 text-sm transition ${
                isSelected
                  ? "bg-brand-500 text-white"
                  : isFocused
                    ? "bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-white"
                    : "text-slate-700 dark:text-slate-300"
              }`,
            singleValue: () => "text-sm text-slate-900 dark:text-white",
            placeholder: () => "text-sm text-slate-400",
            indicatorsContainer: () => "shrink-0 gap-1",
            dropdownIndicator: () =>
              "cursor-pointer px-1 text-slate-400 hover:text-slate-600 dark:hover:text-slate-300",
            noOptionsMessage: () => "px-4 py-3 text-sm text-slate-500 dark:text-slate-400",
            valueContainer: () => "flex-1 overflow-hidden",
          }}
        />
      </div>
    </div>
  );
});
