/**
 * Country → ISO 3166-2 subdivision (state/province/region) catalog.
 *
 * Backed by the `iso-3166-2` npm package which ships the full ISO
 * 3166-2 dataset (~5000 entries across every country). We expose a
 * thin wrapper so the combobox doesn't have to know the library
 * shape, and so we can normalize the records into a uniform
 * `{ code, name }` pair.
 *
 * Subdivisions are an OPTIONAL field per the v1 spec. Countries
 * without recognized subdivisions return an empty array; the
 * combobox renders an empty state in that case.
 */

import isoCountries from 'iso-3166-2';

import type { CountryCode } from './countries';

export interface Subdivision {
  /** ISO 3166-2 code, e.g. 'PL-MZ', 'US-CA', 'GB-SCT'. */
  code: string;
  /** Display name (English baseline from the iso-3166-2 dataset). */
  name: string;
  /** Subdivision type - 'State', 'Province', 'Region', etc. */
  type?: string;
}

interface IsoCountryRecord {
  name: string;
  sub: Record<string, { type: string; name: string }>;
}

const cache = new Map<string, readonly Subdivision[]>();

function loadFor(country: CountryCode): readonly Subdivision[] {
  const hit = cache.get(country);
  if (hit) return hit;
  // The `iso-3166-2` package exposes a `country` lookup. Defensive
  // because some country codes (e.g. obscure territories) lack subs.
  const lookup = (isoCountries as unknown as { country: (c: string) => IsoCountryRecord | null })
    .country;
  const record = lookup ? lookup(country) : null;
  if (!record?.sub) {
    cache.set(country, []);
    return [];
  }
  const list: Subdivision[] = Object.entries(record.sub)
    .map(([code, { name, type }]) => ({ code, name, type }))
    .sort((a, b) => a.name.localeCompare(b.name));
  cache.set(country, list);
  return list;
}

/**
 * Returns the subdivision list for a country. Empty array when none
 * are recognized - caller can use this to hide the field.
 */
export function subdivisionsForCountry(country: CountryCode): readonly Subdivision[] {
  return loadFor(country);
}

export function hasSubdivisions(country: CountryCode): boolean {
  return loadFor(country).length > 0;
}

export function isValidSubdivisionCode(code: string): boolean {
  // ISO 3166-2 codes follow `XX-YYY` - derive the country from the prefix.
  const country = code.split('-')[0];
  if (!country || country.length !== 2) return false;
  const list = loadFor(country as CountryCode);
  return list.some((s) => s.code === code);
}

export function getSubdivisionName(code: string): string {
  const country = code.split('-')[0];
  if (!country) return code;
  const list = loadFor(country as CountryCode);
  return list.find((s) => s.code === code)?.name ?? code;
}
