import {
  normalizeSupportedLocale,
  resolveLocaleFromAcceptLanguage,
} from "@/lib/i18n-config";

const COUNTRY_HEADERS = [
  "cf-ipcountry",
  "x-vercel-ip-country",
  "cloudfront-viewer-country",
  "x-country-code",
] as const;

export type MailBillingProvider = "polar" | "toss-pay";

export type PolarLocalizedPrice = {
  amount: number;
  currency: string;
  countryCode: string | null;
};

const EURO_COUNTRIES = new Set([
  "AT", "BE", "CY", "DE", "EE", "ES", "FI", "FR", "GR", "HR",
  "IE", "IT", "LT", "LU", "LV", "MT", "NL", "PT", "SI", "SK",
]);

// Polar amounts use each currency's smallest unit. These are fixed catalog
// prices anchored to the USD 5.99 plan, not live exchange-rate conversions.
const POLAR_PRICE_BY_COUNTRY: Readonly<Record<string, Omit<PolarLocalizedPrice, "countryCode">>> = {
  AU: { amount: 949, currency: "aud" },
  CA: { amount: 849, currency: "cad" },
  CH: { amount: 529, currency: "chf" },
  CN: { amount: 4300, currency: "cny" },
  GB: { amount: 479, currency: "gbp" },
  HK: { amount: 4700, currency: "hkd" },
  IN: { amount: 52500, currency: "inr" },
  JP: { amount: 899, currency: "jpy" },
  KG: { amount: 52500, currency: "kgs" },
  KZ: { amount: 330000, currency: "kzt" },
  MO: { amount: 4800, currency: "mop" },
  NZ: { amount: 1049, currency: "nzd" },
  SG: { amount: 799, currency: "sgd" },
  TW: { amount: 19500, currency: "twd" },
  US: { amount: 599, currency: "usd" },
  VN: { amount: 159000, currency: "vnd" },
};

const POLAR_PRICE_BY_LOCALE: Readonly<Record<string, Omit<PolarLocalizedPrice, "countryCode">>> = {
  en: { amount: 599, currency: "usd" },
  ja: { amount: 899, currency: "jpy" },
  vi: { amount: 159000, currency: "vnd" },
  zh: { amount: 4300, currency: "cny" },
};

const DEFAULT_POLAR_PRICE = { amount: 599, currency: "usd" } as const;

export function getRequestCountryCode(requestHeaders: Pick<Headers, "get">) {
  for (const headerName of COUNTRY_HEADERS) {
    const countryCode = requestHeaders.get(headerName)?.trim().toUpperCase();

    if (countryCode && /^[A-Z]{2}$/.test(countryCode)) {
      return countryCode;
    }
  }

  return null;
}

export function isKoreanCommerceRequest(
  requestHeaders: Pick<Headers, "get">,
  preferredLocale?: string | null,
  resolvedCountryCode?: string | null,
) {
  const countryCode = resolvedCountryCode === undefined
    ? getRequestCountryCode(requestHeaders)
    : resolvedCountryCode;

  if (countryCode) {
    return countryCode === "KR";
  }

  // Some direct-origin deployments do not inject a GeoIP header. Keep the
  // existing Korean checkout available there while hiding it for other locales.
  const locale =
    normalizeSupportedLocale(preferredLocale) ??
    resolveLocaleFromAcceptLanguage(requestHeaders.get("accept-language"));

  return locale === "ko";
}

export function resolveMailBillingProvider(
  requestHeaders: Pick<Headers, "get">,
  preferredLocale?: string | null,
  resolvedCountryCode?: string | null,
): MailBillingProvider {
  return isKoreanCommerceRequest(
    requestHeaders,
    preferredLocale,
    resolvedCountryCode,
  ) ? "toss-pay" : "polar";
}

export function resolvePolarLocalizedPrice(
  requestHeaders: Pick<Headers, "get">,
  preferredLocale?: string | null,
  resolvedCountryCode?: string | null,
): PolarLocalizedPrice {
  const countryCode = resolvedCountryCode === undefined
    ? getRequestCountryCode(requestHeaders)
    : resolvedCountryCode;

  if (countryCode) {
    const countryPrice = EURO_COUNTRIES.has(countryCode)
      ? { amount: 549, currency: "eur" }
      : POLAR_PRICE_BY_COUNTRY[countryCode];

    return {
      ...(countryPrice ?? DEFAULT_POLAR_PRICE),
      countryCode,
    };
  }

  const locale =
    normalizeSupportedLocale(preferredLocale) ??
    resolveLocaleFromAcceptLanguage(requestHeaders.get("accept-language"));

  return {
    ...(POLAR_PRICE_BY_LOCALE[locale] ?? DEFAULT_POLAR_PRICE),
    countryCode: null,
  };
}

export function getCurrencyFractionDigits(currency: string) {
  try {
    return new Intl.NumberFormat("en", {
      currency: currency.toUpperCase(),
      style: "currency",
    }).resolvedOptions().maximumFractionDigits;
  } catch {
    return 2;
  }
}

export function formatPolarPrice(amount: number, currency: string, locale = "en") {
  const fractionDigits = getCurrencyFractionDigits(currency) ?? 2;

  return new Intl.NumberFormat(locale, {
    currency: currency.toUpperCase(),
    style: "currency",
  }).format(amount / 10 ** fractionDigits);
}
