'use client';

import { useMemo, useState } from 'react';
import { Check, ChevronsUpDown } from 'lucide-react';

import { Button } from '@/components/ui/button';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@/components/ui/command';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { cn } from '@/lib/utils';
import { ALL_COUNTRY_CODES, getCountryName, type CountryCode } from '@/lib/i18n/countries';

interface CountryComboboxProps {
  value: string | null | undefined;
  onChange: (iso: CountryCode | null) => void;
  /** Display locale; defaults to navigator.language so country names follow the user. */
  locale?: string;
  /** When true, renders just the flag/code (compact 24×24 trigger). */
  compact?: boolean;
  placeholder?: string;
  disabled?: boolean;
  className?: string;
  /** Allow clearing the selection. */
  clearable?: boolean;
  id?: string;
  'data-testid'?: string;
}

/**
 * Returns the regional-indicator emoji flag for an ISO alpha-2 code.
 * E.g. 'GB' → 🇬🇧. Avoids shipping a flag-image asset and respects the
 * platform's emoji rendering (iOS/macOS render real flags; Windows
 * shows the country code on a flag rectangle).
 */
function flagEmoji(code: string): string {
  if (code.length !== 2) return '';
  const A = 0x1f1e6;
  const a = 'A'.charCodeAt(0);
  const cp1 = A + code.charCodeAt(0) - a;
  const cp2 = A + code.charCodeAt(1) - a;
  return String.fromCodePoint(cp1, cp2);
}

export function CountryCombobox({
  value,
  onChange,
  locale,
  compact = false,
  placeholder = 'Select country…',
  disabled,
  className,
  clearable = true,
  id,
  'data-testid': testId,
}: CountryComboboxProps) {
  const [open, setOpen] = useState(false);
  const effectiveLocale = locale ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');

  // Pre-build the options list once per locale change so the cmdk filter
  // can search by both code + localized name without re-allocating.
  const options = useMemo(() => {
    return ALL_COUNTRY_CODES.map((code) => ({
      code,
      name: getCountryName(code, effectiveLocale),
      flag: flagEmoji(code),
    })).sort((a, b) => a.name.localeCompare(b.name, effectiveLocale));
  }, [effectiveLocale]);

  const selected = value ? options.find((o) => o.code === value) : undefined;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          id={id}
          variant="outline"
          role="combobox"
          aria-expanded={open}
          disabled={disabled}
          className={cn(
            'justify-between',
            compact ? 'w-20 px-2' : 'w-full',
            !selected && 'text-muted-foreground',
            className,
          )}
          data-testid={testId}
        >
          {selected ? (
            <span className="flex min-w-0 items-center gap-2">
              <span className="text-base leading-none">{selected.flag}</span>
              {!compact ? (
                <span className="truncate text-sm">{selected.name}</span>
              ) : (
                <span className="text-xs font-medium">{selected.code}</span>
              )}
            </span>
          ) : (
            <span className="truncate">{placeholder}</span>
          )}
          <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-[280px] p-0" align="start">
        <Command>
          <CommandInput placeholder="Search country or code…" />
          <CommandList>
            <CommandEmpty>No country found.</CommandEmpty>
            {clearable && value ? (
              <CommandGroup>
                <CommandItem
                  value="__clear__"
                  onSelect={() => {
                    onChange(null);
                    setOpen(false);
                  }}
                  className="text-muted-foreground"
                >
                  Clear selection
                </CommandItem>
              </CommandGroup>
            ) : null}
            <CommandGroup>
              {options.map((opt) => (
                <CommandItem
                  key={opt.code}
                  // cmdk filters by `value` — include both code + name.
                  value={`${opt.name} ${opt.code}`}
                  onSelect={() => {
                    onChange(opt.code);
                    setOpen(false);
                  }}
                >
                  <Check
                    className={cn('mr-2 h-4 w-4', value === opt.code ? 'opacity-100' : 'opacity-0')}
                  />
                  <span className="mr-2 text-base leading-none">{opt.flag}</span>
                  <span className="flex-1 truncate text-sm">{opt.name}</span>
                  <span className="text-xs text-muted-foreground">{opt.code}</span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}
