/**
 * ISO-3166-1 alpha-2 country list.
 *
 * Source: full ISO 3166-1 list as of 2026-04 (250 codes incl. UN
 * member states + recognized territories). Country *names* are
 * resolved at render time via `Intl.DisplayNames` so we don't ship
 * a localized name table - the browser already has it.
 *
 * Validation uses the `ISO_COUNTRIES` Set; render uses
 * `getCountryName(iso, locale)`.
 */

export const ALL_COUNTRY_CODES = [
  'AD',
  'AE',
  'AF',
  'AG',
  'AI',
  'AL',
  'AM',
  'AO',
  'AQ',
  'AR',
  'AS',
  'AT',
  'AU',
  'AW',
  'AX',
  'AZ',
  'BA',
  'BB',
  'BD',
  'BE',
  'BF',
  'BG',
  'BH',
  'BI',
  'BJ',
  'BL',
  'BM',
  'BN',
  'BO',
  'BQ',
  'BR',
  'BS',
  'BT',
  'BV',
  'BW',
  'BY',
  'BZ',
  'CA',
  'CC',
  'CD',
  'CF',
  'CG',
  'CH',
  'CI',
  'CK',
  'CL',
  'CM',
  'CN',
  'CO',
  'CR',
  'CU',
  'CV',
  'CW',
  'CX',
  'CY',
  'CZ',
  'DE',
  'DJ',
  'DK',
  'DM',
  'DO',
  'DZ',
  'EC',
  'EE',
  'EG',
  'EH',
  'ER',
  'ES',
  'ET',
  'FI',
  'FJ',
  'FK',
  'FM',
  'FO',
  'FR',
  'GA',
  'GB',
  'GD',
  'GE',
  'GF',
  'GG',
  'GH',
  'GI',
  'GL',
  'GM',
  'GN',
  'GP',
  'GQ',
  'GR',
  'GS',
  'GT',
  'GU',
  'GW',
  'GY',
  'HK',
  'HM',
  'HN',
  'HR',
  'HT',
  'HU',
  'ID',
  'IE',
  'IL',
  'IM',
  'IN',
  'IO',
  'IQ',
  'IR',
  'IS',
  'IT',
  'JE',
  'JM',
  'JO',
  'JP',
  'KE',
  'KG',
  'KH',
  'KI',
  'KM',
  'KN',
  'KP',
  'KR',
  'KW',
  'KY',
  'KZ',
  'LA',
  'LB',
  'LC',
  'LI',
  'LK',
  'LR',
  'LS',
  'LT',
  'LU',
  'LV',
  'LY',
  'MA',
  'MC',
  'MD',
  'ME',
  'MF',
  'MG',
  'MH',
  'MK',
  'ML',
  'MM',
  'MN',
  'MO',
  'MP',
  'MQ',
  'MR',
  'MS',
  'MT',
  'MU',
  'MV',
  'MW',
  'MX',
  'MY',
  'MZ',
  'NA',
  'NC',
  'NE',
  'NF',
  'NG',
  'NI',
  'NL',
  'NO',
  'NP',
  'NR',
  'NU',
  'NZ',
  'OM',
  'PA',
  'PE',
  'PF',
  'PG',
  'PH',
  'PK',
  'PL',
  'PM',
  'PN',
  'PR',
  'PS',
  'PT',
  'PW',
  'PY',
  'QA',
  'RE',
  'RO',
  'RS',
  'RU',
  'RW',
  'SA',
  'SB',
  'SC',
  'SD',
  'SE',
  'SG',
  'SH',
  'SI',
  'SJ',
  'SK',
  'SL',
  'SM',
  'SN',
  'SO',
  'SR',
  'SS',
  'ST',
  'SV',
  'SX',
  'SY',
  'SZ',
  'TC',
  'TD',
  'TF',
  'TG',
  'TH',
  'TJ',
  'TK',
  'TL',
  'TM',
  'TN',
  'TO',
  'TR',
  'TT',
  'TV',
  'TW',
  'TZ',
  'UA',
  'UG',
  'UM',
  'US',
  'UY',
  'UZ',
  'VA',
  'VC',
  'VE',
  'VG',
  'VI',
  'VN',
  'VU',
  'WF',
  'WS',
  'YE',
  'YT',
  'ZA',
  'ZM',
  'ZW',
] as const;

export type CountryCode = (typeof ALL_COUNTRY_CODES)[number];

export const ISO_COUNTRIES: ReadonlySet<string> = new Set(ALL_COUNTRY_CODES);

export function isValidCountryCode(code: string): code is CountryCode {
  return ISO_COUNTRIES.has(code);
}

/**
 * Browser-localized display name for a country code.
 * Caches `Intl.DisplayNames` instances by locale to avoid repeated allocation.
 */
const displayNameCache = new Map<string, Intl.DisplayNames>();

function getDisplay(locale: string): Intl.DisplayNames {
  let dn = displayNameCache.get(locale);
  if (!dn) {
    dn = new Intl.DisplayNames([locale], { type: 'region' });
    displayNameCache.set(locale, dn);
  }
  return dn;
}

export function getCountryName(code: string, locale = 'en'): string {
  if (!isValidCountryCode(code)) return code;
  try {
    return getDisplay(locale).of(code) ?? code;
  } catch {
    return code;
  }
}

/**
 * Detect a sensible default country from the runtime context.
 * Browser path: navigator.language (`'en-GB'` → `'GB'`).
 * Server / unknown path: falls back to the provided default (`'US'` per spec).
 */
export function detectDefaultCountry(fallback: CountryCode = 'US'): CountryCode {
  if (typeof navigator === 'undefined') return fallback;
  const lang = navigator.language;
  if (!lang) return fallback;
  // Locale tags look like 'en', 'en-US', 'pl-PL'. Take the region part.
  const parts = lang.split('-');
  const region = parts.length > 1 ? parts[parts.length - 1]?.toUpperCase() : '';
  if (region && isValidCountryCode(region)) return region;
  return fallback;
}
