/**
 * Content Currency Resolution
 *
 * Decides which currency AI-generated content (product descriptions, ICP
 * revenue ranges, persona budgets, pricing comparisons, …) must be written in.
 *
 * Resolution order:
 *   1. The currency the user explicitly picked in the form
 *   2. The currency implied by the Business Profile's country
 *   3. INR — the platform default when neither is known
 *
 * Two sets exist because modules store currency differently:
 *   - `resolveContentCurrency` returns one of the five codes the Product model's
 *     enum accepts (INR, USD, EUR, GBP, AED), so the result is always storable.
 *   - `resolveExtendedCurrency` returns any supported code, for modules such as
 *     ICP/Persona whose currency field is free-form and whose picker offers a
 *     wider list (CAD, AUD, JPY, …).
 */

/** Codes the Product model's `currency` enum accepts. */
export type ContentCurrencyCode = 'INR' | 'USD' | 'EUR' | 'GBP' | 'AED';

/** Every code the platform can express, for free-form currency fields. */
export type ExtendedCurrencyCode =
  | ContentCurrencyCode
  | 'CAD' | 'AUD' | 'SGD' | 'JPY' | 'CNY' | 'CHF' | 'BRL' | 'ZAR' | 'SEK' | 'MXN';

/** Used when neither an explicit currency nor a Business Profile country exists. */
export const DEFAULT_CONTENT_CURRENCY: ContentCurrencyCode = 'INR';

/** Used when a country IS known but maps to no supported currency. */
const INTERNATIONAL_FALLBACK_CURRENCY: ContentCurrencyCode = 'USD';

export interface ContentCurrencyMeta {
  code: ExtendedCurrencyCode;
  symbol: string;
  name: string;
  /** A formatted sample the prompt can show the model. */
  example: string;
}

export const CONTENT_CURRENCY_META: Record<ExtendedCurrencyCode, ContentCurrencyMeta> = {
  INR: { code: 'INR', symbol: '₹', name: 'Indian Rupee', example: '₹2,999' },
  USD: { code: 'USD', symbol: '$', name: 'US Dollar', example: '$49' },
  EUR: { code: 'EUR', symbol: '€', name: 'Euro', example: '€49' },
  GBP: { code: 'GBP', symbol: '£', name: 'British Pound', example: '£39' },
  AED: { code: 'AED', symbol: 'د.إ', name: 'UAE Dirham', example: 'AED 199' },
  CAD: { code: 'CAD', symbol: 'C$', name: 'Canadian Dollar', example: 'C$69' },
  AUD: { code: 'AUD', symbol: 'A$', name: 'Australian Dollar', example: 'A$79' },
  SGD: { code: 'SGD', symbol: 'S$', name: 'Singapore Dollar', example: 'S$69' },
  JPY: { code: 'JPY', symbol: '¥', name: 'Japanese Yen', example: '¥7,000' },
  CNY: { code: 'CNY', symbol: '¥', name: 'Chinese Yuan', example: '¥350' },
  CHF: { code: 'CHF', symbol: 'Fr', name: 'Swiss Franc', example: 'Fr 45' },
  BRL: { code: 'BRL', symbol: 'R$', name: 'Brazilian Real', example: 'R$250' },
  ZAR: { code: 'ZAR', symbol: 'R', name: 'South African Rand', example: 'R900' },
  SEK: { code: 'SEK', symbol: 'kr', name: 'Swedish Krona', example: 'kr 500' },
  MXN: { code: 'MXN', symbol: 'Mex$', name: 'Mexican Peso', example: 'Mex$900' },
};

const PRODUCT_CURRENCY_CODES: ContentCurrencyCode[] = ['INR', 'USD', 'EUR', 'GBP', 'AED'];
const ALL_CURRENCY_CODES = Object.keys(CONTENT_CURRENCY_META) as ExtendedCurrencyCode[];

/**
 * Country → currency lookup.
 *
 * Keyed by lowercased country name as well as ISO-3166 alpha-2/alpha-3 codes,
 * because `BusinessProfile.country` stores a full country name while other
 * callers (geo headers, imports) may pass a code.
 */
const COUNTRY_CURRENCY: Record<string, ExtendedCurrencyCode> = {
  // ── India ────────────────────────────────────────────────────────────────
  'india': 'INR',
  'bharat': 'INR',
  'in': 'INR',
  'ind': 'INR',

  // ── United Arab Emirates ─────────────────────────────────────────────────
  'united arab emirates': 'AED',
  'uae': 'AED',
  'u.a.e.': 'AED',
  'ae': 'AED',
  'are': 'AED',

  // ── United Kingdom ───────────────────────────────────────────────────────
  'united kingdom': 'GBP',
  'united kingdom of great britain and northern ireland': 'GBP',
  'great britain': 'GBP',
  'england': 'GBP',
  'scotland': 'GBP',
  'wales': 'GBP',
  'northern ireland': 'GBP',
  'uk': 'GBP',
  'u.k.': 'GBP',
  'gb': 'GBP',
  'gbr': 'GBP',

  // ── United States ────────────────────────────────────────────────────────
  'united states': 'USD',
  'united states of america': 'USD',
  'usa': 'USD',
  'u.s.': 'USD',
  'u.s.a.': 'USD',
  'us': 'USD',
  'america': 'USD',

  // ── Eurozone ─────────────────────────────────────────────────────────────
  'austria': 'EUR', 'at': 'EUR', 'aut': 'EUR',
  'belgium': 'EUR', 'be': 'EUR', 'bel': 'EUR',
  'croatia': 'EUR', 'hr': 'EUR', 'hrv': 'EUR',
  'cyprus': 'EUR', 'cy': 'EUR', 'cyp': 'EUR',
  'estonia': 'EUR', 'ee': 'EUR', 'est': 'EUR',
  'finland': 'EUR', 'fi': 'EUR', 'fin': 'EUR',
  'france': 'EUR', 'fr': 'EUR', 'fra': 'EUR',
  'germany': 'EUR', 'de': 'EUR', 'deu': 'EUR',
  'greece': 'EUR', 'gr': 'EUR', 'grc': 'EUR',
  'ireland': 'EUR', 'ie': 'EUR', 'irl': 'EUR',
  'italy': 'EUR', 'it': 'EUR', 'ita': 'EUR',
  'latvia': 'EUR', 'lv': 'EUR', 'lva': 'EUR',
  'lithuania': 'EUR', 'lt': 'EUR', 'ltu': 'EUR',
  'luxembourg': 'EUR', 'lu': 'EUR', 'lux': 'EUR',
  'malta': 'EUR', 'mt': 'EUR', 'mlt': 'EUR',
  'netherlands': 'EUR', 'the netherlands': 'EUR', 'holland': 'EUR', 'nl': 'EUR', 'nld': 'EUR',
  'portugal': 'EUR', 'pt': 'EUR', 'prt': 'EUR',
  'slovakia': 'EUR', 'sk': 'EUR', 'svk': 'EUR',
  'slovenia': 'EUR', 'si': 'EUR', 'svn': 'EUR',
  'spain': 'EUR', 'es': 'EUR', 'esp': 'EUR',
  'monaco': 'EUR', 'mc': 'EUR', 'mco': 'EUR',
  'andorra': 'EUR', 'ad': 'EUR', 'and': 'EUR',
  'san marino': 'EUR', 'sm': 'EUR', 'smr': 'EUR',
  'vatican city': 'EUR', 'va': 'EUR', 'vat': 'EUR',

  // ── Other supported currencies ───────────────────────────────────────────
  // These are only reachable through the extended (free-form) resolver; the
  // product-safe resolver falls back to USD for them.
  'canada': 'CAD', 'ca': 'CAD', 'can': 'CAD',
  'australia': 'AUD', 'au': 'AUD', 'aus': 'AUD',
  'singapore': 'SGD', 'sg': 'SGD', 'sgp': 'SGD',
  'japan': 'JPY', 'jp': 'JPY', 'jpn': 'JPY',
  'china': 'CNY', 'cn': 'CNY', 'chn': 'CNY', "people's republic of china": 'CNY',
  'switzerland': 'CHF', 'ch': 'CHF', 'che': 'CHF',
  'brazil': 'BRL', 'br': 'BRL', 'bra': 'BRL',
  'south africa': 'ZAR', 'za': 'ZAR', 'zaf': 'ZAR',
  'sweden': 'SEK', 'se': 'SEK', 'swe': 'SEK',
  'mexico': 'MXN', 'mx': 'MXN', 'mex': 'MXN',
};

function normaliseKey(value: string): string {
  return value.trim().toLowerCase().replace(/\s+/g, ' ');
}

function coerceCode(input: string | null | undefined, allowed: ExtendedCurrencyCode[]): ExtendedCurrencyCode | null {
  if (!input || typeof input !== 'string') return null;
  const trimmed = input.trim();
  if (!trimmed) return null;

  const upper = trimmed.toUpperCase();
  if ((allowed as string[]).includes(upper)) return upper as ExtendedCurrencyCode;

  const bySymbol = allowed.find(code => CONTENT_CURRENCY_META[code].symbol === trimmed);
  return bySymbol || null;
}

/**
 * Coerce an arbitrary currency input to a product-storable code (INR, USD, EUR,
 * GBP, AED), or null when it is empty / unrecognised. Accepts codes and symbols.
 */
export function normaliseCurrencyCode(input?: string | null): ContentCurrencyCode | null {
  return coerceCode(input, PRODUCT_CURRENCY_CODES) as ContentCurrencyCode | null;
}

/** As above, but accepting any supported currency. */
export function normaliseExtendedCurrencyCode(input?: string | null): ExtendedCurrencyCode | null {
  return coerceCode(input, ALL_CURRENCY_CODES);
}

function currencyForCountry(country: string | null | undefined, allowed: ExtendedCurrencyCode[]): ExtendedCurrencyCode | null {
  if (!country || typeof country !== 'string' || !country.trim()) return null;
  const mapped = COUNTRY_CURRENCY[normaliseKey(country)];
  // A country we know about but whose currency this caller can't store falls
  // back to USD, the conventional international default — as does a country
  // that isn't in the table at all.
  if (!mapped || !allowed.includes(mapped)) return INTERNATIONAL_FALLBACK_CURRENCY;
  return mapped;
}

/**
 * Map a Business Profile country (name or ISO code) to a product-storable
 * currency. Returns null when no country is set.
 */
export function resolveCurrencyForCountry(country?: string | null): ContentCurrencyCode | null {
  return currencyForCountry(country, PRODUCT_CURRENCY_CODES) as ContentCurrencyCode | null;
}

/**
 * Full resolution for product-storable currency:
 * explicit selection → Business Profile country → INR.
 */
export function resolveContentCurrency(
  explicitCurrency?: string | null,
  businessProfileCountry?: string | null,
): ContentCurrencyCode {
  return (
    normaliseCurrencyCode(explicitCurrency) ||
    resolveCurrencyForCountry(businessProfileCountry) ||
    DEFAULT_CONTENT_CURRENCY
  );
}

/**
 * Full resolution across every supported currency, for free-form currency
 * fields (ICP `primaryCurrency`, persona budgets):
 * explicit selection → Business Profile country → INR.
 */
export function resolveExtendedCurrency(
  explicitCurrency?: string | null,
  businessProfileCountry?: string | null,
): ExtendedCurrencyCode {
  return (
    normaliseExtendedCurrencyCode(explicitCurrency) ||
    currencyForCountry(businessProfileCountry, ALL_CURRENCY_CODES) ||
    DEFAULT_CONTENT_CURRENCY
  );
}

export function getCurrencyMeta(code?: string | null): ContentCurrencyMeta {
  return CONTENT_CURRENCY_META[normaliseExtendedCurrencyCode(code) || DEFAULT_CONTENT_CURRENCY];
}
