import { computeInSitu } from './t1-insitu.js';

function clone(obj) { return { ...obj }; }
function pctDelta(value, base) {
  if (value == null || base == null || base === 0) return null;
  return Math.round(((value - base) / base) * 10000) / 100;
}
function point(label, input, baseValue) {
  const result = computeInSitu(input);
  return { label, value_usd: result.in_situ_value_usd, delta_pct: pctDelta(result.in_situ_value_usd, baseValue), assumptions: input };
}

export function t1Sensitivity(baseInput = {}, options = {}) {
  const baseResult = computeInSitu(baseInput);
  const baseValue = baseResult.in_situ_value_usd;
  const gradeStdAu = Number(options.grade_std_au_gpt ?? baseInput.grade_std_au_gpt ?? 0) || 0;
  const gradeStdCu = Number(options.grade_std_cu_pct ?? baseInput.grade_std_cu_pct ?? 0) || 0;
  const gradeStdAg = Number(options.grade_std_ag_gpt ?? baseInput.grade_std_ag_gpt ?? 0) || 0;

  const priceSteps = [
    ['-20%', 0.8], ['-10%', 0.9], ['base', 1.0], ['+10%', 1.1], ['+20%', 1.2],
  ].map(([label, f]) => point(label, {
    ...clone(baseInput),
    price_au_usd_oz: baseInput.price_au_usd_oz == null ? baseInput.price_au_usd_oz : baseInput.price_au_usd_oz * f,
    price_ag_usd_oz: baseInput.price_ag_usd_oz == null ? baseInput.price_ag_usd_oz : baseInput.price_ag_usd_oz * f,
    price_cu_usd_lb: baseInput.price_cu_usd_lb == null ? baseInput.price_cu_usd_lb : baseInput.price_cu_usd_lb * f,
  }, baseValue));

  const gradeSteps = [
    ['-2σ', -2], ['-1σ', -1], ['base', 0], ['+1σ', 1], ['+2σ', 2],
  ].map(([label, z]) => point(label, {
    ...clone(baseInput),
    grade_au_gpt: baseInput.grade_au_gpt == null ? baseInput.grade_au_gpt : Math.max(0, baseInput.grade_au_gpt + z * gradeStdAu),
    grade_ag_gpt: baseInput.grade_ag_gpt == null ? baseInput.grade_ag_gpt : Math.max(0, baseInput.grade_ag_gpt + z * gradeStdAg),
    grade_cu_pct: baseInput.grade_cu_pct == null ? baseInput.grade_cu_pct : Math.max(0, baseInput.grade_cu_pct + z * gradeStdCu),
  }, baseValue));

  const recoverySteps = [
    ['-20%', 0.8], ['-10%', 0.9], ['base', 1.0], ['+10%', 1.1], ['+20%', 1.2],
  ].map(([label, f]) => point(label, {
    ...clone(baseInput),
    recovery_au: baseInput.recovery_au == null ? baseInput.recovery_au : Math.min(1, Math.max(0, baseInput.recovery_au * f)),
    recovery_ag: baseInput.recovery_ag == null ? baseInput.recovery_ag : Math.min(1, Math.max(0, baseInput.recovery_ag * f)),
    recovery_cu: baseInput.recovery_cu == null ? baseInput.recovery_cu : Math.min(1, Math.max(0, baseInput.recovery_cu * f)),
  }, baseValue));

  const factorSteps = [
    ['-20%', 0.8], ['-10%', 0.9], ['base', 1.0], ['+10%', 1.1], ['+20%', 1.2],
  ].map(([label, f]) => point(label, { ...clone(baseInput), in_situ_factor: baseInput.in_situ_factor == null ? baseInput.in_situ_factor : baseInput.in_situ_factor * f }, baseValue));

  return {
    base_value_usd: baseValue,
    base_result: baseResult,
    drivers: {
      commodity_price: priceSteps,
      grade: gradeSteps,
      recovery: recoverySteps,
      in_situ_factor: factorSteps,
    },
  };
}
