'use client';

import { useEffect, useState } from 'react';

import { cn } from '@/lib/utils';
import { getCountryName } from '@/lib/i18n/countries';

interface CountryFlagProps {
  /** ISO-3166-1 alpha-2 code (case-insensitive). Renders nothing when null/empty
   *  so callers can `<CountryFlag code={client.nationalityIso} />` without guards. */
  code: string | null | undefined;
  /** Tailwind size classes (default `h-3 w-4`). The 3x2 SVG ratio renders crisp
   *  at any width - pick `h-4 w-5` for chips, `h-3 w-4` for inline rail rows,
   *  `h-5 w-7` for detail headers. */
  className?: string;
  /** Override the aria-label/title (defaults to the localized country name). */
  title?: string;
  /** Hide from assistive tech when the flag is purely decorative (e.g. shown next
   *  to a visible country name that already conveys the same info). */
  decorative?: boolean;
}

// Single lazy import of the whole 3×2 string-SVG index. Per-code dynamic
// imports with template strings don't enumerate cleanly through the
// package's `exports` field in Next.js's webpack build, so we fall back
// to one chunk that holds every flag and pluck by key. The chunk is
// only fetched the first time any flag renders in the session and is
// cached on the module's promise - every subsequent CountryFlag instance
// resolves instantly.
let flagsPromise: Promise<Record<string, string>> | null = null;
let flagsCache: Record<string, string> | null = null;

function loadAllFlags(): Promise<Record<string, string>> {
  if (flagsCache) return Promise.resolve(flagsCache);
  if (!flagsPromise) {
    flagsPromise = import('country-flag-icons/string/3x2')
      .then((mod) => {
        flagsCache = mod as unknown as Record<string, string>;
        return flagsCache;
      })
      .catch((err: unknown) => {
        flagsPromise = null;
        throw err;
      });
  }
  return flagsPromise;
}

/**
 * Lazy-loaded SVG country flag. Uses the `country-flag-icons` 3×2 string
 * variant via dynamic import, so only the flags actually rendered in a
 * session are downloaded (one ~1–2 KB chunk per country, cached). Falls
 * back to a muted placeholder for unknown codes or during the initial
 * load tick - accepted, since the surrounding text label conveys the
 * same info.
 *
 * Use everywhere we previously rendered an ISO code chip or a regional-
 * indicator emoji glyph; the SVG path renders identically on every
 * platform (notably Windows, where the emoji form falls back to the
 * letter pair).
 */
export function CountryFlag({ code, className, title, decorative }: CountryFlagProps) {
  const normalized = code ? code.toUpperCase() : '';
  const [svg, setSvg] = useState<string | null>(() =>
    normalized && flagsCache ? (flagsCache[normalized] ?? null) : null,
  );

  useEffect(() => {
    if (!normalized) {
      // eslint-disable-next-line react-hooks/set-state-in-effect -- clear cached SVG when caller drops the code
      setSvg(null);
      return;
    }
    if (flagsCache) {
      setSvg(flagsCache[normalized] ?? null);
      return;
    }
    let cancelled = false;
    loadAllFlags()
      .then((flags) => {
        if (!cancelled) setSvg(flags[normalized] ?? null);
      })
      .catch(() => {
        if (!cancelled) setSvg(null);
      });
    return () => {
      cancelled = true;
    };
  }, [normalized]);

  if (!normalized) return null;

  const label = title ?? getCountryName(normalized, 'en') ?? normalized;
  const baseClass = 'inline-block shrink-0 overflow-hidden rounded-[2px]';
  const sizeClass = className ?? 'h-3 w-4';

  if (!svg) {
    return (
      <span
        className={cn(baseClass, sizeClass, 'bg-muted')}
        aria-hidden={decorative ? true : undefined}
        aria-label={decorative ? undefined : label}
        title={decorative ? undefined : label}
      />
    );
  }
  return (
    <span
      className={cn(baseClass, sizeClass, '[&>svg]:h-full [&>svg]:w-full')}
      role={decorative ? undefined : 'img'}
      aria-hidden={decorative ? true : undefined}
      aria-label={decorative ? undefined : label}
      title={decorative ? undefined : label}
      dangerouslySetInnerHTML={{ __html: svg }}
    />
  );
}
