export type BlendSource = { tons: number; ppm: number };

export type BlendResult2 = {
  source1_tons: number;
  source2_tons: number;
  result_ppm: number;
};

/** Two-source blend to hit target PPM for fixed total tons. */
export function calculateBlendTwo(
  source1: BlendSource,
  source2: BlendSource,
  targetTons: number,
  targetPpm: number
): BlendResult2 {
  if (targetTons <= 0) {
    throw new Error('calculateBlendTwo: targetTons must be positive');
  }
  const denom = source1.ppm - source2.ppm;
  if (Math.abs(denom) < 1e-9) {
    throw new Error('calculateBlendTwo: sources must have different PPM');
  }
  const tons1 = (targetTons * (targetPpm - source2.ppm)) / denom;
  const tons2 = targetTons - tons1;
  if (tons1 < -1e-6 || tons2 < -1e-6) {
    throw new Error('calculateBlendTwo: infeasible blend (negative tons)');
  }
  const result_ppm = (tons1 * source1.ppm + tons2 * source2.ppm) / targetTons;
  return { source1_tons: tons1, source2_tons: tons2, result_ppm };
}

export type BlendResult3 = {
  source1_tons: number;
  source2_tons: number;
  source3_tons: number;
  result_ppm: number;
};

/**
 * Three-source: fix tons3, solve for tons1+tons2 to hit targetPpm with two sources.
 * If source3 omitted, degrades to two-source.
 */
export function calculateBlendThree(
  s1: BlendSource,
  s2: BlendSource,
  s3: BlendSource | null,
  targetTons: number,
  targetPpm: number,
  tons3 = 0
): BlendResult3 {
  if (!s3 || tons3 <= 0) {
    const r = calculateBlendTwo(s1, s2, targetTons, targetPpm);
    return { ...r, source3_tons: 0 };
  }
  const remTons = targetTons - tons3;
  if (remTons <= 0) {
    throw new Error('calculateBlendThree: tons3 must be less than targetTons');
  }
  const remPpmMass = targetPpm * targetTons - tons3 * s3.ppm;
  const targetPpm12 = remPpmMass / remTons;
  const r = calculateBlendTwo(s1, s2, remTons, targetPpm12);
  const result_ppm =
    (r.source1_tons * s1.ppm + r.source2_tons * s2.ppm + tons3 * s3.ppm) / targetTons;
  return {
    source1_tons: r.source1_tons,
    source2_tons: r.source2_tons,
    source3_tons: tons3,
    result_ppm,
  };
}
