import { BadRequestException } from '@nestjs/common';
import type { PartyPax } from './row-pax';

/**
 * Movement Dashboard activity add-ons (client rule 2026-10-15): pax
 * above the activity line's own booked count are add-ons — billed as a
 * separate customer charge, never complimentary. Reducing add-ons
 * refunds the billed amount pro-rata.
 */
export interface AddonChange {
  addon: PartyPax;
  /** + charge / − refund to post as a settlement row (selling currency). */
  billedDelta: number;
  added: number;
  removed: number;
}

export function computeAddonChange(input: {
  /** Pax booked on the line (adults+seniors, children) — excl. add-ons. */
  base: PartyPax;
  /** Pax now on the line as set from the dashboard. */
  effective: PartyPax;
  oldAddon: PartyPax;
  oldBilled: number;
  /** Confirmed charge for newly added pax. */
  charge?: number;
}): AddonChange | null {
  const { base, effective, oldAddon, oldBilled, charge } = input;
  const addon: PartyPax = {
    adults: Math.max(0, effective.adults - base.adults),
    children: Math.max(0, effective.children - base.children),
  };
  if (addon.adults === oldAddon.adults && addon.children === oldAddon.children) return null;

  const added =
    Math.max(0, addon.adults - oldAddon.adults) + Math.max(0, addon.children - oldAddon.children);
  const removed =
    Math.max(0, oldAddon.adults - addon.adults) + Math.max(0, oldAddon.children - addon.children);
  if (added > 0 && !(Number(charge) > 0)) {
    throw new BadRequestException(
      `Add-on of ${added} pax needs a charge — add-ons are always billed.`,
    );
  }
  const oldTotal = oldAddon.adults + oldAddon.children;
  const refund =
    removed > 0 && oldTotal > 0 ? Math.round(((oldBilled * removed) / oldTotal) * 100) / 100 : 0;
  const billedDelta = Math.round(((added > 0 ? Number(charge) : 0) - refund) * 100) / 100;
  return { addon, billedDelta, added, removed };
}

/**
 * Supplier line cost after a dashboard pax change, priced by age
 * (client rule 2026-10-15): each added / removed pax moves the cost by
 * that age group's per-pax cost (`unit_price` on the line's age row).
 * An age with no rate falls back to the line's average per-pax cost.
 */
export function addonSupplierCost(input: {
  lineCost: number;
  oldPax: PartyPax;
  newPax: PartyPax;
  rates: { adult?: number; child?: number };
}): number {
  const { lineCost, oldPax, newPax, rates } = input;
  const oldTotal = oldPax.adults + oldPax.children;
  const avg = oldTotal > 0 ? lineCost / oldTotal : 0;
  const adultRate = Number(rates.adult) > 0 ? Number(rates.adult) : avg;
  const childRate = Number(rates.child) > 0 ? Number(rates.child) : avg;
  const next =
    lineCost +
    (newPax.adults - oldPax.adults) * adultRate +
    (newPax.children - oldPax.children) * childRate;
  return Math.max(0, Math.round(next * 100) / 100);
}
