/**
 * DACH VAT rates and country inference for receipt reconciliation.
 *
 * Never assume German 19% when the receipt is Austrian, Swiss, or other.
 * Missing rates are derived from amounts or left at 0 — not filled with 19.
 */

export type TaxCountry = "DE" | "AT" | "CH" | "DACH" | "OTHER";

/** Standard / reduced / special / zero rates per country. */
export const VAT_RATES: Record<TaxCountry, readonly number[]> = {
  DE: [19, 7, 0],
  AT: [20, 10, 13, 0],
  CH: [8.1, 2.6, 3.8, 0],
  /** EUR without a DE/AT signal — never prefer 19% over a closer 20%. */
  DACH: [19, 7, 20, 10, 13, 0],
  OTHER: [],
};

export function roundTax(value: number): number {
  return Math.round((value + Number.EPSILON) * 100) / 100;
}

function haystack(parts: Array<string | null | undefined>): string {
  return parts
    .filter((p): p is string => typeof p === "string" && p.length > 0)
    .join(" ")
    .toLowerCase();
}

/**
 * Infer the VAT jurisdiction from tax id, currency, and address.
 * Tax id wins, then currency (CHF), then address keywords. EUR alone is not DE.
 */
export function inferTaxCountry(input: {
  currency?: string | null;
  taxId?: string | null;
  address?: string | null;
}): TaxCountry {
  const taxId = (input.taxId || "").replace(/\s+/g, "").toUpperCase();
  if (/^DE[A-Z0-9]/.test(taxId) || /^DE\d{9,}$/.test(taxId)) return "DE";
  if (/^ATU\d/.test(taxId) || /^AT\d/.test(taxId)) return "AT";
  if (/^CHE/.test(taxId) || /^CH[-.]?\d/.test(taxId)) return "CH";

  const currency = (input.currency || "").trim().toUpperCase();
  if (currency === "CHF") return "CH";

  const text = haystack([input.address, input.taxId]);
  if (
    /österreich|oesterreich|\baustria\b|\bwien\b|\bgraz\b|\blinz\b|\bsalzburg\b|\binnsbruck\b/.test(
      text
    )
  ) {
    return "AT";
  }
  if (
    /schweiz|\bswitzerland\b|\bzürich\b|\bzurich\b|\bbern\b|\bgenf\b|\bgeneva\b|\bbasel\b|\blausanne\b/.test(
      text
    )
  ) {
    return "CH";
  }
  if (
    /deutschland|\bgermany\b|\bberlin\b|\bmünchen\b|\bmuenchen\b|\bhamburg\b|\bk[öo]ln\b|\bfrankfurt\b/.test(
      text
    )
  ) {
    return "DE";
  }

  if (currency === "EUR") return "DACH";
  return "OTHER";
}

function snapTolerance(rate: number): number {
  if (rate >= 15) return 2;
  if (rate >= 5) return 1.5;
  return 1;
}

/**
 * Snap an approximate rate onto the country's official VAT table.
 * Unknown jurisdictions keep the computed rate (no German 19% fallback).
 */
export function snapVatRate(approxRate: number, country: TaxCountry): number {
  const rounded = roundTax(approxRate);
  const rates = VAT_RATES[country];
  if (!rates.length) return rounded;

  let best = rounded;
  let bestDiff = Infinity;
  for (const rate of rates) {
    const diff = Math.abs(rounded - rate);
    if (diff <= snapTolerance(rate) && diff < bestDiff) {
      best = rate;
      bestDiff = diff;
    }
  }
  return best;
}

/**
 * Resolve a tax line's rate. Never default a missing value to 19%.
 * Prefer the printed rate (snapped), else tax/net, else 0.
 */
export function resolveTaxRatePercent(
  item: {
    ratePercent?: number | null;
    taxAmount?: number | null;
    netAmount?: number | null;
  },
  country: TaxCountry
): number {
  if (typeof item.ratePercent === "number" && Number.isFinite(item.ratePercent)) {
    return snapVatRate(item.ratePercent, country);
  }
  const net = item.netAmount;
  const tax = item.taxAmount;
  if (typeof net === "number" && net > 0 && typeof tax === "number" && tax > 0) {
    return snapVatRate((tax / net) * 100, country);
  }
  return 0;
}
