function roundToTwo(value: number): number {
  return Math.round((Number(value || 0) + Number.EPSILON) * 100) / 100;
}

function clampToPercent(value: number): number {
  return Math.max(0, Math.min(100, Number(value || 0)));
}

export type CoverageSplitInput = {
  totalAmount: number;
  secondaryCoveragePercent?: number;
  secondaryCoverageAmount?: number;
  hasSecondaryCustomer: boolean;
};

export type CoverageSplitResult = {
  hasSecondaryCoverage: boolean;
  secondaryRatio: number;
  primaryAmount: number;
  secondaryAmount: number;
};

export function resolveCoverageSplit(input: CoverageSplitInput): CoverageSplitResult {
  const totalAmount = roundToTwo(Math.max(0, Number(input.totalAmount || 0)));
  const secondaryCoveragePercent = clampToPercent(Number(input.secondaryCoveragePercent || 0));
  const hasSecondaryCoverage = Boolean(input.hasSecondaryCustomer) && secondaryCoveragePercent > 0;

  if (!hasSecondaryCoverage || totalAmount <= 0) {
    return {
      hasSecondaryCoverage,
      secondaryRatio: 0,
      primaryAmount: totalAmount,
      secondaryAmount: 0,
    };
  }

  const storedSecondaryAmount = roundToTwo(Math.max(0, Number(input.secondaryCoverageAmount || 0)));
  const secondaryRatio = storedSecondaryAmount > 0
    ? Math.max(0, Math.min(1, storedSecondaryAmount / totalAmount))
    : Math.max(0, Math.min(1, secondaryCoveragePercent / 100));

  const secondaryAmount = roundToTwo(totalAmount * secondaryRatio);
  const primaryAmount = roundToTwo(Math.max(0, totalAmount - secondaryAmount));

  return {
    hasSecondaryCoverage,
    secondaryRatio,
    primaryAmount,
    secondaryAmount,
  };
}

export function resolveInvoiceAmountForParty(params: {
  totalAmount: number;
  primaryMatched: boolean;
  secondaryMatched: boolean;
  split: CoverageSplitResult;
}): number {
  const safeTotal = roundToTwo(Math.max(0, Number(params.totalAmount || 0)));
  if (safeTotal <= 0) return 0;

  if (!params.split.hasSecondaryCoverage) {
    return params.primaryMatched ? safeTotal : 0;
  }

  let allocated = 0;
  if (params.primaryMatched) allocated += params.split.primaryAmount;
  if (params.secondaryMatched) allocated += params.split.secondaryAmount;
  if (allocated <= 0) return 0;
  return roundToTwo(Math.min(safeTotal, allocated));
}
