/**
 * Markup-tax model (client policy 2026-05-13, billing fix 2026-10-14).
 *
 *   Cost lines (hotel / transport / activity / special) are entered
 *   tax-inclusive — supplier tax is already inside them. The DMC's own
 *   taxable supply is its MARKUP (service charge), so the selected slab
 *   (`tax_slab_id`) applies to the markup only.
 *
 *   `selling_total` is the FINAL customer price:
 *       selling_total = cost_in_selling + markup + markup_tax
 *   and it is what settlements, invoices and accounting bill.
 *
 *   Rounding is applied to that final price (clean customer price), so
 *   markup + markup_tax are back-solved from it here. Mirrors
 *   `splitFinalPrice` in the frontend `itinerary-helpers.ts` — keep both
 *   in lockstep.
 */

const round2 = (n: number) => Math.round(n * 100) / 100;

export interface FinalPriceSplit {
  /** Markup (service charge) in selling currency, excl. tax. Negative = discount. */
  markup: number;
  /** Tax on the markup in selling currency. 0 when no slab / no positive markup. */
  markupTax: number;
  /** final − markupTax — cost + markup. */
  preTax: number;
}

export function splitFinalPrice(
  finalTotal: number,
  costInSelling: number,
  taxRatePct: number,
): FinalPriceSplit {
  const final = Number(finalTotal) || 0;
  const cost = Number(costInSelling) || 0;
  const rate = Number(taxRatePct) || 0;
  const gross = final - cost;
  if (gross <= 0 || rate <= 0) {
    return { markup: round2(gross), markupTax: 0, preTax: round2(final) };
  }
  const markup = round2(gross / (1 + rate / 100));
  const markupTax = round2(gross - markup);
  return { markup, markupTax, preTax: round2(final - markupTax) };
}

export interface MarkupConfigLike {
  pricing_strategy?: string | null;
  markup_type?: string | null;
  markup_amount?: number | string | null;
  hotel_markup?: number | string | null;
  transport_markup?: number | string | null;
  activity_markup?: number | string | null;
  special_markup?: number | string | null;
}

export interface ComponentCosts {
  hotel: number;
  transport: number;
  activity: number;
  special: number;
}

type Component = keyof ComponentCosts;
const COMPONENTS: Component[] = ['hotel', 'transport', 'activity', 'special'];

/**
 * Split the pre-tax selling amount (cost + markup, selling currency)
 * across the four components. Weights follow the pricing strategy —
 * per-component markups weight each component by its own marked-up
 * cost; overall / per-person strategies spread the markup pro-rata to
 * cost. The last non-zero component absorbs rounding drift so the four
 * always sum exactly to `preTax`.
 */
export function distributeSellingComponents(
  costs: ComponentCosts,
  cfg: MarkupConfigLike,
  preTax: number,
): Record<Component, number> {
  const isPerComponent = (cfg.pricing_strategy || '').includes('component');
  const pct = cfg.markup_type === 'percentage';
  const markupOf: Record<Component, number> = {
    hotel: Number(cfg.hotel_markup) || 0,
    transport: Number(cfg.transport_markup) || 0,
    activity: Number(cfg.activity_markup) || 0,
    special: Number(cfg.special_markup) || 0,
  };
  const weights = COMPONENTS.map((c) => {
    const cost = Number(costs[c]) || 0;
    if (!isPerComponent || cost === 0) return cost;
    return pct ? cost * (1 + markupOf[c] / 100) : cost + markupOf[c];
  });
  const totalWeight = weights.reduce((s, w) => s + w, 0);
  const out: Record<Component, number> = { hotel: 0, transport: 0, activity: 0, special: 0 };
  if (totalWeight <= 0) return out;

  let lastIdx = -1;
  weights.forEach((w, i) => {
    if (w !== 0) lastIdx = i;
  });
  let allocated = 0;
  COMPONENTS.forEach((c, i) => {
    if (i === lastIdx) return;
    out[c] = round2((preTax * weights[i]) / totalWeight);
    allocated += out[c];
  });
  if (lastIdx >= 0) out[COMPONENTS[lastIdx]] = round2(preTax - allocated);
  return out;
}
