export type CountryCode = "NG" | "US" | "GB";

export type CountryConfig = {
  code: CountryCode;
  name: string;
  currency: string;
  symbol: string;
  locale: string;
  phonePrefix: string;
  phonePlaceholder: string;
  vatRate: number;
  vatLabel: string;
  /** Address field labels, ordered as they are written locally. */
  regionLabel: string;
  localityLabel: string;
  postcodeLabel: string;
};

export const COUNTRIES: Record<CountryCode, CountryConfig> = {
  NG: {
    code: "NG",
    name: "Nigeria",
    currency: "NGN",
    symbol: "₦",
    locale: "en-NG",
    phonePrefix: "+234",
    phonePlaceholder: "+234 803 000 0000",
    vatRate: 7.5,
    vatLabel: "VAT (7.5%)",
    regionLabel: "State",
    localityLabel: "LGA / City",
    postcodeLabel: "Postal code",
  },
  US: {
    code: "US",
    name: "United States",
    currency: "USD",
    symbol: "$",
    locale: "en-US",
    phonePrefix: "+1",
    phonePlaceholder: "+1 202 555 0134",
    vatRate: 0,
    vatLabel: "Sales tax",
    regionLabel: "State",
    localityLabel: "City",
    postcodeLabel: "ZIP code",
  },
  GB: {
    code: "GB",
    name: "United Kingdom",
    currency: "GBP",
    symbol: "£",
    locale: "en-GB",
    phonePrefix: "+44",
    phonePlaceholder: "+44 20 7946 0000",
    vatRate: 20,
    vatLabel: "VAT (20%)",
    regionLabel: "County",
    localityLabel: "Town / City",
    postcodeLabel: "Postcode",
  },
};

export const DEFAULT_COUNTRY: CountryCode = "NG";
export const COUNTRY_LIST = Object.values(COUNTRIES);

export function country(code?: string | null): CountryConfig {
  return COUNTRIES[(code as CountryCode) ?? DEFAULT_COUNTRY] ?? COUNTRIES[DEFAULT_COUNTRY];
}

/** Money formatted for the given country, e.g. ₦150,000.00 / $1,200.00 / £980.00 */
export function formatMoney(amount: number, code?: string | null) {
  const c = country(code);
  try {
    return new Intl.NumberFormat(c.locale, {
      style: "currency",
      currency: c.currency,
      maximumFractionDigits: 2,
    }).format(amount);
  } catch {
    return `${c.symbol}${amount.toLocaleString(c.locale)}`;
  }
}

export function formatDate(value: string | number | Date, code?: string | null) {
  const c = country(code);
  return new Date(value).toLocaleDateString(c.locale, { day: "2-digit", month: "short", year: "numeric" });
}

/** Normalise a local number into an international one for the selected country. */
export function formatPhone(input: string, code?: string | null) {
  const c = country(code);
  const digits = input.replace(/[^\d+]/g, "");
  if (!digits) return "";
  if (digits.startsWith("+")) return digits;
  const trimmed = digits.replace(/^0+/, "");
  return `${c.phonePrefix} ${trimmed}`;
}

/** Address written the way it is addressed locally. */
export function formatAddress(
  parts: { street?: string | null; locality?: string | null; region?: string | null; postcode?: string | null },
  code?: string | null,
) {
  const c = country(code);
  const { street, locality, region, postcode } = parts;
  const lines =
    c.code === "US"
      ? [street, [locality, region, postcode].filter(Boolean).join(", ")]
      : c.code === "GB"
        ? [street, locality, region, postcode]
        : [street, locality, region, postcode];
  return [...lines.filter(Boolean), c.name].join(", ");
}

export type Totals = { subtotal: number; discount: number; vatRate: number; vatAmount: number; total: number };

/** Subtotal → discount → tax → total, using the country's default tax rate unless overridden. */
export function computeTotals(
  items: { quantity: number; unit_price: number }[],
  discount = 0,
  code?: string | null,
  vatRateOverride?: number | null,
): Totals {
  const c = country(code);
  const subtotal = items.reduce((sum, i) => sum + Number(i.quantity || 0) * Number(i.unit_price || 0), 0);
  const net = Math.max(0, subtotal - Number(discount || 0));
  const vatRate = vatRateOverride ?? c.vatRate;
  const vatAmount = Math.round(net * (vatRate / 100) * 100) / 100;
  return {
    subtotal: Math.round(subtotal * 100) / 100,
    discount: Math.round(Number(discount || 0) * 100) / 100,
    vatRate,
    vatAmount,
    total: Math.round((net + vatAmount) * 100) / 100,
  };
}