// Copyright 2026 Aurum Authors
// Licensed under Apache-2.0

///|
// Fixed synthetic inputs for notes/use-cases.md; no real user or market data.
fn require(condition : Bool, message : String) -> Unit {
  if !condition {
    abort(message)
  }
}

///|
fn main {
  println("设计场景 / 待验证:固定输入计算演示")
  println("【1 金额解析、权重分摊与对账】")
  let amount = match @money.Money::parse("100.00", "CNY") {
    Some(value) => value
    None => abort("fixed amount must parse")
  }
  let shares = match amount.allocate_by_weights([1, 2, 3]) {
    Some(value) => value
    None => abort("fixed weights must allocate")
  }
  for share in shares {
    println("  份额 CNY = " + share.to_decimal_string())
  }
  let total = match @money.Money::sum(shares, "CNY") {
    Some(value) => value
    None => abort("same-currency shares must sum")
  }
  if total != amount {
    abort("allocation must conserve amount")
  }
  println("  合计 CNY = " + total.to_decimal_string())
  let rejects_precision = @money.Money::parse("100.001", "CNY") == None
  require(rejects_precision, "excess precision must be rejected")
  println("  超精度解析被拒绝 = " + rejects_precision.to_string())
  let rejects_weights = amount.allocate_by_weights([0, 0, 0]) == None
  require(rejects_weights, "zero weights must be rejected")
  println("  全零权重被拒绝 = " + rejects_weights.to_string())

  println("【2 等间隔现金流审阅】")
  let cashflows = [-1000.0, 300.0, 400.0, 500.0]
  let breakdown = match
    @capital.discounted_cash_flow_schedule(0.10, cashflows) {
    Some(value) => value
    None => abort("fixed cashflows must discount")
  }
  for row in breakdown {
    println(
      "  t=" +
      row.period.to_string() +
      " 现金流=" +
      row.cashflow.to_string() +
      " 现值=" +
      row.present_value.to_string(),
    )
  }
  match @capital.net_present_value(0.10, cashflows) {
    Some(value) => {
      require((value - -21.0368145).abs() < 1.0e-6, "fixed NPV mismatch")
      println("  NPV = " + value.to_string())
    }
    None => abort("fixed cashflows must have NPV")
  }
  match @capital.internal_rate_of_return(cashflows) {
    Some(value) => println("  IRR = " + value.to_string())
    None => abort("fixed single-sign-change cashflows must have IRR")
  }
  match @capital.net_present_value(0.0, [1.0e16, 1.0, -1.0e16]) {
    Some(value) => {
      require(value == 1.0, "cancellation NPV must preserve the small term")
      println("  数值压力样例 NPV = " + value.to_string())
    }
    None => abort("fixed cancellation sample must have NPV")
  }
  let rejects_irr = @capital.internal_rate_of_return([-100.0, 230.0, -132.0]) ==
    None
  require(rejects_irr, "multiple-sign-change IRR must be rejected")
  println("  多次变号唯一 IRR 被拒绝 = " + rejects_irr.to_string())

  println("【3 按分还款计划与额外还本】")
  let principal = match @money.Money::parse("10000.00", "CNY") {
    Some(value) => value
    None => abort("fixed principal must parse")
  }
  let rows = match
    @amortize.equal_installment_money_schedule(
      principal,
      0.01,
      12,
      @money.round_half_up(),
    ) {
    Some(value) => value
    None => abort("fixed loan must produce a plan")
  }
  for row in rows {
    println(
      "  期=" +
      row.period.to_string() +
      " 还款=" +
      row.payment.to_decimal_string() +
      " 本金=" +
      row.principal.to_decimal_string() +
      " 利息=" +
      row.interest.to_decimal_string() +
      " 余额=" +
      row.balance.to_decimal_string(),
    )
  }
  let baseline = match @amortize.summarize_money_schedule(rows) {
    Some(value) => value
    None => abort("baseline plan must reconcile")
  }
  require(baseline.principal == principal, "baseline principal mismatch")
  require(
    baseline.ending_balance == @money.Money::zero("CNY"),
    "baseline loan must settle",
  )
  println(
    "  基准汇总本金 CNY = " + baseline.principal.to_decimal_string(),
  )
  println("  基准总利息 CNY = " + baseline.interest.to_decimal_string())
  println(
    "  基准期末余额 CNY = " + baseline.ending_balance.to_decimal_string(),
  )
  let extra_rows = match
    @amortize.equal_installment_money_schedule_with_extra_principal(
      principal,
      0.01,
      12,
      [@money.Money::of(10000, "CNY")],
      @money.round_half_up(),
    ) {
    Some(value) => value
    None => abort("fixed extra principal must produce a plan")
  }
  let extra = match @amortize.summarize_money_schedule(extra_rows) {
    Some(value) => value
    None => abort("extra-principal plan must reconcile")
  }
  require(extra.principal == principal, "extra-principal total mismatch")
  require(
    extra.ending_balance == @money.Money::zero("CNY"),
    "extra-principal loan must settle",
  )
  println(
    "  额外还本首期还款 CNY = " +
    extra_rows[0].payment.to_decimal_string(),
  )
  println(
    "  额外还本首期本金 CNY = " +
    extra_rows[0].principal.to_decimal_string(),
  )
  println(
    "  额外还本汇总本金 CNY = " + extra.principal.to_decimal_string(),
  )
  println("  额外还本总利息 CNY = " + extra.interest.to_decimal_string())
  println(
    "  额外还本期末余额 CNY = " +
    extra.ending_balance.to_decimal_string(),
  )
  let difference = match baseline.interest.try_sub(extra.interest) {
    Some(value) => value
    None => abort("fixed interest difference must fit Money")
  }
  require(difference.minor() == 1157, "fixed interest difference mismatch")
  println("  固定模型利息差 CNY = " + difference.to_decimal_string())
  let rejects_periods = @amortize.equal_installment_money_schedule(
      principal,
      0.01,
      0,
      @money.round_half_up(),
    ) ==
    None
  require(rejects_periods, "zero loan periods must be rejected")
  println("  零期数被拒绝 = " + rejects_periods.to_string())
}