/**
 * rMortgage Amortization Engine
 *
 * Pure math functions — no React dependencies.
 * Handles amortization, tranche splitting, overpayment distribution,
 * and comparison with traditional mortgages.
 */

import type {
  MortgageTranche,
  MortgageState,
  MortgageSimulatorConfig,
  AmortizationEntry,
  Lender,
  LendingTier,
} from './mortgage-types'
import { DEFAULT_CONFIG } from './mortgage-types'

// ─── Core Amortization Math ──────────────────────────────

/** Monthly payment for a fixed-rate fully-amortizing loan */
export function monthlyPayment(principal: number, annualRate: number, termMonths: number): number {
  if (annualRate === 0) return principal / termMonths
  const r = annualRate / 12
  return principal * (r * Math.pow(1 + r, termMonths)) / (Math.pow(1 + r, termMonths) - 1)
}

/** Interest portion of a payment given current balance */
export function interestPortion(balance: number, annualRate: number): number {
  return balance * (annualRate / 12)
}

/** Generate full amortization schedule for a single loan */
export function amortizationSchedule(
  principal: number,
  annualRate: number,
  termMonths: number,
  monthlyOverpayment: number = 0,
): AmortizationEntry[] {
  const schedule: AmortizationEntry[] = []
  let balance = principal
  const basePayment = monthlyPayment(principal, annualRate, termMonths)
  let cumulativeInterest = 0
  let cumulativePrincipal = 0

  for (let month = 1; month <= termMonths && balance > 0.01; month++) {
    const interest = interestPortion(balance, annualRate)
    const totalPayment = Math.min(balance + interest, basePayment + monthlyOverpayment)
    const principalPaid = totalPayment - interest
    balance = Math.max(0, balance - principalPaid)
    cumulativeInterest += interest
    cumulativePrincipal += principalPaid

    schedule.push({
      month,
      payment: totalPayment,
      principal: principalPaid,
      interest,
      balance,
      cumulativeInterest,
      cumulativePrincipal,
    })
  }

  return schedule
}

// ─── Lender Name Generator ───────────────────────────────

const FIRST_NAMES = [
  'Alice', 'Bob', 'Carmen', 'David', 'Elena', 'Frank', 'Grace', 'Hassan',
  'Iris', 'James', 'Kira', 'Leo', 'Maya', 'Noah', 'Olga', 'Pat',
  'Quinn', 'Rosa', 'Sam', 'Tara', 'Uma', 'Victor', 'Wren', 'Xavier',
  'Yara', 'Zane', 'Amara', 'Basil', 'Clara', 'Diego', 'Ella', 'Felix',
  'Gia', 'Hugo', 'Ivy', 'Jules', 'Kaia', 'Liam', 'Mira', 'Nico',
  'Opal', 'Priya', 'Ravi', 'Sage', 'Teo', 'Una', 'Val', 'Willow',
  'Xena', 'Yuri', 'Zara', 'Arlo', 'Bea', 'Cruz', 'Dahlia', 'Elio',
  'Flora', 'Gael', 'Hana', 'Idris', 'June', 'Kai', 'Luz', 'Marcel',
  'Noor', 'Owen', 'Pearl', 'Rio', 'Soren', 'Thea', 'Umar', 'Vera',
]

function generateLender(index: number): Lender {
  const name = FIRST_NAMES[index % FIRST_NAMES.length]
  const suffix = index >= FIRST_NAMES.length ? ` ${Math.floor(index / FIRST_NAMES.length) + 1}` : ''
  return {
    id: `lender-${index}`,
    name: `${name}${suffix}`,
    walletAddress: `0x${index.toString(16).padStart(40, '0')}`,
  }
}

// ─── Initialize Mortgage State ───────────────────────────

export function initializeMortgage(config: MortgageSimulatorConfig = DEFAULT_CONFIG): MortgageState {
  const totalPrincipal = config.propertyValue * (1 - config.downPaymentPercent / 100)
  const numTranches = Math.ceil(totalPrincipal / config.trancheSize)
  const defaultTermMonths = config.termYears * 12

  // Create tranches with optional rate variation
  const tranches: MortgageTranche[] = []
  let remainingPrincipal = totalPrincipal

  // Determine which tranches are funded vs open
  const fundedCount = Math.round(numTranches * (config.fundingPercent / 100))

  // Determine which lenders are reinvestors (among funded tranches only)
  const reinvestorCount = Math.round(fundedCount * (config.reinvestorPercent / 100))
  const reinvestRates = config.reinvestmentRates.length > 0 ? config.reinvestmentRates : [0.05]

  // Build tier assignments: distribute tranches across tiers by allocation
  const tiers = config.useVariableTerms ? config.lendingTiers : []
  const tierAssignments: (LendingTier | null)[] = []
  if (tiers.length > 0) {
    // Normalize allocations
    const totalAlloc = tiers.reduce((s, t) => s + t.allocation, 0)
    let assigned = 0
    for (const tier of tiers) {
      const count = Math.round((tier.allocation / totalAlloc) * numTranches)
      for (let j = 0; j < count && assigned < numTranches; j++) {
        tierAssignments.push(tier)
        assigned++
      }
    }
    // Fill any remainder with the last tier
    while (tierAssignments.length < numTranches) {
      tierAssignments.push(tiers[tiers.length - 1])
    }
  }

  for (let i = 0; i < numTranches; i++) {
    const principal = Math.min(config.trancheSize, remainingPrincipal)
    remainingPrincipal -= principal

    // Determine rate and term from tier or base config
    const tier = tierAssignments[i] ?? null
    const termMonths = tier ? tier.termYears * 12 : defaultTermMonths
    const tierLabel = tier ? tier.label : `${config.termYears}yr`

    // Apply rate variation: spread linearly across tranches
    const baseRate = tier ? tier.rate : config.interestRate
    const variationOffset = config.rateVariation > 0
      ? config.rateVariation * (2 * (i / Math.max(numTranches - 1, 1)) - 1)
      : 0
    const rate = Math.max(0.01, baseRate + variationOffset)

    const isFunded = i < fundedCount
    const mp = monthlyPayment(principal, rate, termMonths)

    // Assign reinvestment strategy: spread reinvestors evenly among funded
    const isReinvestor = isFunded && i < reinvestorCount
    const reinvestmentRate = isReinvestor
      ? reinvestRates[i % reinvestRates.length]
      : undefined

    tranches.push({
      id: `tranche-${i}`,
      lender: generateLender(i),
      principal,
      principalRemaining: principal,
      interestRate: rate,
      termMonths,
      monthsElapsed: 0,
      monthlyPayment: isFunded ? mp : 0,
      monthlyPrincipal: isFunded ? mp - interestPortion(principal, rate) : 0,
      monthlyInterest: isFunded ? interestPortion(principal, rate) : 0,
      totalInterestPaid: 0,
      totalPrincipalPaid: 0,
      transferable: true,
      listedForSale: false,
      transferHistory: [],
      status: 'active',
      funded: isFunded,
      tierLabel,
      reinvestmentRate,
      isReinvested: false,
      reinvestmentPool: 0,
    })
  }

  const totalMonthly = tranches.reduce((s, t) => s + t.monthlyPayment, 0)
  const tradMonthly = monthlyPayment(totalPrincipal, config.interestRate, defaultTermMonths)
  const tradSchedule = amortizationSchedule(totalPrincipal, config.interestRate, defaultTermMonths)
  const tradTotalInterest = tradSchedule.length > 0
    ? tradSchedule[tradSchedule.length - 1].cumulativeInterest
    : 0

  return {
    propertyValue: config.propertyValue,
    downPayment: config.propertyValue * (config.downPaymentPercent / 100),
    totalPrincipal,
    trancheSize: config.trancheSize,
    baseInterestRate: config.interestRate,
    termMonths: defaultTermMonths,
    borrower: {
      id: 'borrower-0',
      name: 'Borrower',
      walletAddress: '0x' + 'b'.repeat(40),
    },
    tranches,
    currentMonth: 0,
    monthlyPayment: totalMonthly,
    overpayment: config.overpayment,
    overpaymentTarget: config.overpaymentTarget,
    totalInterestPaid: 0,
    totalPrincipalPaid: 0,
    totalPrincipalRemaining: totalPrincipal,
    tranchesRepaid: 0,
    communityFundBalance: 0,
    traditionalTotalInterest: tradTotalInterest,
    traditionalMonthlyPayment: tradMonthly,
  }
}

// ─── Advance Simulation by One Month ─────────────────────

export function advanceMonth(state: MortgageState): MortgageState {
  const next = { ...state, tranches: state.tranches.map(t => ({ ...t, transferHistory: [...t.transferHistory] })) }
  next.currentMonth += 1

  const activeTranches = next.tranches.filter(t => t.status === 'active' && t.funded)
  if (activeTranches.length === 0) return next

  // Distribute overpayment
  let overpaymentPool = next.overpayment
  let communityContribution = 0

  if (overpaymentPool > 0) {
    switch (next.overpaymentTarget) {
      case 'community_fund':
        communityContribution = overpaymentPool
        overpaymentPool = 0
        break
      case 'split':
        communityContribution = overpaymentPool / 2
        overpaymentPool = overpaymentPool / 2
        break
      case 'extra_principal':
        // all goes to extra principal
        break
    }
  }

  // Extra principal distributed evenly across active tranches
  const extraPrincipalPerTranche = activeTranches.length > 0
    ? overpaymentPool / activeTranches.length
    : 0

  let totalInterestThisMonth = 0
  let totalPrincipalThisMonth = 0

  // Track newly repaid reinvestors for reinvestment
  const newlyRepaidReinvestors: MortgageTranche[] = []

  for (const tranche of next.tranches) {
    if (tranche.status === 'repaid' || !tranche.funded) continue

    const interest = interestPortion(tranche.principalRemaining, tranche.interestRate)
    const basePrincipal = tranche.monthlyPayment - interest
    const extraPrincipal = extraPrincipalPerTranche
    const principalPaid = Math.min(tranche.principalRemaining, basePrincipal + extraPrincipal)

    tranche.principalRemaining = Math.max(0, tranche.principalRemaining - principalPaid)
    tranche.monthsElapsed += 1
    tranche.monthlyInterest = interest
    tranche.monthlyPrincipal = principalPaid
    tranche.totalInterestPaid += interest
    tranche.totalPrincipalPaid += principalPaid

    totalInterestThisMonth += interest
    totalPrincipalThisMonth += principalPaid

    // Reinvestors accumulate their received payments
    if (tranche.reinvestmentRate != null) {
      tranche.reinvestmentPool += principalPaid + interest
    }

    if (tranche.principalRemaining < 0.01) {
      tranche.principalRemaining = 0
      tranche.status = 'repaid'
      if (tranche.reinvestmentRate != null) {
        newlyRepaidReinvestors.push(tranche)
      }
    }
  }

  // Create reinvestment tranches from repaid reinvestors
  for (const repaid of newlyRepaidReinvestors) {
    const reinvestAmount = repaid.reinvestmentPool
    if (reinvestAmount < 100) continue // minimum reinvestment threshold

    const rate = repaid.reinvestmentRate!
    const remainingTermMonths = Math.max(12, next.termMonths - next.currentMonth)
    const mp = monthlyPayment(reinvestAmount, rate, remainingTermMonths)

    const newTranche: MortgageTranche = {
      id: `reinvest-${repaid.id}-m${next.currentMonth}`,
      lender: repaid.lender, // same lender reinvests
      principal: reinvestAmount,
      principalRemaining: reinvestAmount,
      interestRate: rate,
      termMonths: remainingTermMonths,
      monthsElapsed: 0,
      monthlyPayment: mp,
      monthlyPrincipal: mp - interestPortion(reinvestAmount, rate),
      monthlyInterest: interestPortion(reinvestAmount, rate),
      totalInterestPaid: 0,
      totalPrincipalPaid: 0,
      transferable: true,
      listedForSale: false,
      transferHistory: [],
      status: 'active',
      funded: true,
      tierLabel: `reinvest@${(rate * 100).toFixed(0)}%`,
      reinvestmentRate: rate, // continues reinvesting
      isReinvested: true,
      parentTrancheId: repaid.id,
      reinvestmentPool: 0,
    }

    next.tranches.push(newTranche)
    repaid.reinvestmentPool = 0
  }

  // Also create reinvestment tranches periodically for active reinvestors
  // who've accumulated enough in their pool (annual reinvestment cycle)
  if (next.currentMonth % 12 === 0) {
    for (const tranche of next.tranches) {
      if (tranche.status !== 'active' || tranche.reinvestmentRate == null) continue
      if (tranche.reinvestmentPool < 500) continue // need at least $500 to reinvest

      const reinvestAmount = tranche.reinvestmentPool
      const rate = tranche.reinvestmentRate
      const remainingTermMonths = Math.max(12, next.termMonths - next.currentMonth)
      const mp = monthlyPayment(reinvestAmount, rate, remainingTermMonths)

      const newTranche: MortgageTranche = {
        id: `reinvest-${tranche.id}-m${next.currentMonth}`,
        lender: tranche.lender,
        principal: reinvestAmount,
        principalRemaining: reinvestAmount,
        interestRate: rate,
        termMonths: remainingTermMonths,
        monthsElapsed: 0,
        monthlyPayment: mp,
        monthlyPrincipal: mp - interestPortion(reinvestAmount, rate),
        monthlyInterest: interestPortion(reinvestAmount, rate),
        totalInterestPaid: 0,
        totalPrincipalPaid: 0,
        transferable: true,
        listedForSale: false,
        transferHistory: [],
        status: 'active',
        funded: true,
        tierLabel: `reinvest@${(rate * 100).toFixed(0)}%`,
        reinvestmentRate: rate,
        isReinvested: true,
        parentTrancheId: tranche.id,
        reinvestmentPool: 0,
      }

      next.tranches.push(newTranche)
      tranche.reinvestmentPool = 0
    }
  }

  // Simulate some secondary market activity (transfers every ~6 months for a few tranches)
  if (next.currentMonth % 6 === 0 && next.currentMonth > 0) {
    const activeForSale = next.tranches.filter(t =>
      t.status === 'active' && !t.isReinvested && t.monthsElapsed > 12
    )
    // ~5% of eligible tranches get transferred per cycle
    const transferCount = Math.max(0, Math.floor(activeForSale.length * 0.05))
    for (let i = 0; i < transferCount; i++) {
      const idx = (next.currentMonth * 7 + i * 13) % activeForSale.length
      const tranche = activeForSale[idx]
      if (!tranche || tranche.transferHistory.length >= 3) continue

      const buyerIdx = next.tranches.length + 100 + next.currentMonth + i
      const buyer = generateLender(buyerIdx)
      const premium = 1 + (0.02 + (idx % 5) * 0.01) // 2-6% premium
      const price = tranche.principalRemaining * premium

      tranche.transferHistory.push({
        id: `transfer-${tranche.id}-m${next.currentMonth}`,
        fromLenderId: tranche.lender.id,
        toLenderId: buyer.id,
        price,
        principalRemaining: tranche.principalRemaining,
        premiumPercent: (premium - 1) * 100,
        date: next.currentMonth,
      })
      tranche.lender = buyer
    }
  }

  next.totalInterestPaid += totalInterestThisMonth
  next.totalPrincipalPaid += totalPrincipalThisMonth
  next.totalPrincipalRemaining = next.tranches.reduce((s, t) => s + t.principalRemaining, 0)
  next.tranchesRepaid = next.tranches.filter(t => t.status === 'repaid').length
  next.communityFundBalance += communityContribution

  // Recalculate monthly payment (decreases as tranches are repaid)
  next.monthlyPayment = next.tranches
    .filter(t => t.status === 'active')
    .reduce((s, t) => s + t.monthlyPayment, 0)

  return next
}

// ─── Run Full Simulation ─────────────────────────────────

export function runFullSimulation(config: MortgageSimulatorConfig): MortgageState[] {
  const states: MortgageState[] = []
  let state = initializeMortgage(config)
  states.push(state)

  const maxMonths = config.termYears * 12
  for (let m = 0; m < maxMonths; m++) {
    if (state.totalPrincipalRemaining < 0.01) break
    state = advanceMonth(state)
    states.push(state)
  }

  return states
}

// ─── Tranche Transfer (Secondary Market) ─────────────────

export function transferTranche(
  state: MortgageState,
  trancheId: string,
  buyerLender: Lender,
  price: number,
): MortgageState {
  const next = { ...state, tranches: state.tranches.map(t => ({ ...t, transferHistory: [...t.transferHistory] })) }

  const tranche = next.tranches.find(t => t.id === trancheId)
  if (!tranche || tranche.status === 'repaid' || !tranche.transferable) return state

  const premiumPercent = ((price - tranche.principalRemaining) / tranche.principalRemaining) * 100

  tranche.transferHistory.push({
    id: `transfer-${tranche.transferHistory.length}`,
    fromLenderId: tranche.lender.id,
    toLenderId: buyerLender.id,
    price,
    principalRemaining: tranche.principalRemaining,
    premiumPercent,
    date: Date.now(),
  })

  tranche.lender = buyerLender
  tranche.listedForSale = false
  tranche.askingPrice = undefined

  return next
}

// ─── Yield Calculator for Secondary Market ───────────────

export function calculateBuyerYield(
  tranche: MortgageTranche,
  purchasePrice: number,
): { annualYield: number; totalReturn: number; monthsRemaining: number } {
  const remainingPrincipal = tranche.principalRemaining
  const monthsRemaining = tranche.termMonths - tranche.monthsElapsed

  // Estimate total remaining payments
  let totalPayments = 0
  let balance = remainingPrincipal
  for (let m = 0; m < monthsRemaining && balance > 0.01; m++) {
    const interest = balance * (tranche.interestRate / 12)
    const payment = tranche.monthlyPayment
    const principal = Math.min(balance, payment - interest)
    totalPayments += payment
    balance -= principal
  }

  const totalReturn = totalPayments - purchasePrice
  const annualYield = monthsRemaining > 0
    ? (totalReturn / purchasePrice) / (monthsRemaining / 12) * 100
    : 0

  return { annualYield, totalReturn, monthsRemaining }
}

// ─── Summary Stats ───────────────────────────────────────

export interface MortgageSummary {
  // Myco
  mycoTotalInterest: number
  mycoMonthlyPayment: number
  mycoPayoffMonths: number
  avgLenderYield: number
  communityRetained: number    // interest that stays in community
  // Traditional
  tradTotalInterest: number
  tradMonthlyPayment: number
  tradPayoffMonths: number
  // Delta
  interestSaved: number
  monthsSaved: number
}

export function computeSummary(states: MortgageState[]): MortgageSummary {
  const final = states[states.length - 1]
  const initial = states[0]

  const mycoPayoffMonths = final.currentMonth
  const tradSchedule = amortizationSchedule(
    initial.totalPrincipal,
    initial.baseInterestRate,
    initial.termMonths,
  )
  const tradPayoffMonths = tradSchedule.length

  // Average lender yield: weighted by tranche size
  const totalWeight = final.tranches.reduce((s, t) => s + t.principal, 0)
  const avgYield = totalWeight > 0
    ? final.tranches.reduce((s, t) => {
        const yieldPct = t.principal > 0 ? (t.totalInterestPaid / t.principal) / (mycoPayoffMonths / 12) * 100 : 0
        return s + yieldPct * (t.principal / totalWeight)
      }, 0)
    : 0

  return {
    mycoTotalInterest: final.totalInterestPaid,
    mycoMonthlyPayment: initial.monthlyPayment,
    mycoPayoffMonths,
    avgLenderYield: avgYield,
    communityRetained: final.totalInterestPaid, // all interest stays local
    tradTotalInterest: final.traditionalTotalInterest,
    tradMonthlyPayment: initial.traditionalMonthlyPayment,
    tradPayoffMonths,
    interestSaved: final.traditionalTotalInterest - final.totalInterestPaid,
    monthsSaved: tradPayoffMonths - mycoPayoffMonths,
  }
}

// ─── Lender Return Calculator ────────────────────────────

export interface LenderReturnScenario {
  tierLabel: string
  termYears: number
  rate: number
  investment: number
  // Monthly liquidity: take all returns each month
  liquid: {
    monthlyPayment: number
    totalInterest: number
    totalReturn: number
    effectiveYield: number // annualized
  }
  // Reinvest to term: compound returns at the same rate
  reinvested: {
    finalValue: number
    totalInterest: number
    totalReturn: number
    effectiveYield: number // annualized
  }
}

export function calculateLenderReturns(
  investment: number,
  tiers: { label: string; termYears: number; rate: number }[],
): LenderReturnScenario[] {
  return tiers.map(tier => {
    const termMonths = tier.termYears * 12
    const r = tier.rate / 12
    const mp = r === 0
      ? investment / termMonths
      : investment * (r * Math.pow(1 + r, termMonths)) / (Math.pow(1 + r, termMonths) - 1)

    // Liquid: lender receives mp each month, keeps interest, gets principal back over time
    const liquidTotalPayments = mp * termMonths
    const liquidTotalInterest = liquidTotalPayments - investment
    const liquidEffectiveYield = investment > 0
      ? (liquidTotalInterest / investment) / tier.termYears * 100
      : 0

    // Reinvested: compound monthly payments at the tier rate
    // Each monthly payment is reinvested and earns interest for remaining months
    let reinvestAccum = 0
    for (let m = 0; m < termMonths; m++) {
      const monthsRemaining = termMonths - m - 1
      // Future value of this month's payment compounded for remaining months
      reinvestAccum += mp * Math.pow(1 + r, monthsRemaining)
    }
    const reinvestTotalInterest = reinvestAccum - investment
    const reinvestEffectiveYield = investment > 0 && tier.termYears > 0
      ? (Math.pow(reinvestAccum / investment, 1 / tier.termYears) - 1) * 100
      : 0

    return {
      tierLabel: tier.label,
      termYears: tier.termYears,
      rate: tier.rate,
      investment,
      liquid: {
        monthlyPayment: mp,
        totalInterest: liquidTotalInterest,
        totalReturn: liquidTotalPayments,
        effectiveYield: liquidEffectiveYield,
      },
      reinvested: {
        finalValue: reinvestAccum,
        totalInterest: reinvestTotalInterest,
        totalReturn: reinvestAccum,
        effectiveYield: reinvestEffectiveYield,
      },
    }
  })
}

// ─── Borrower Affordability Calculator ───────────────────

/** Given a monthly payment, how much can you borrow at a given rate and term? */
export function maxPrincipal(monthlyBudget: number, annualRate: number, termMonths: number): number {
  if (annualRate === 0) return monthlyBudget * termMonths
  const r = annualRate / 12
  return monthlyBudget * (Math.pow(1 + r, termMonths) - 1) / (r * Math.pow(1 + r, termMonths))
}

export interface AffordabilityScenario {
  label: string
  description: string
  // Tier mix used
  tiers: { label: string; termYears: number; rate: number; allocation: number }[]
  // Results
  maxLoan: number
  propertyValue: number // with down payment
  monthlyPayment: number
  totalInterest: number
  totalPaid: number
  payoffYears: number
  // Per-tier breakdown
  breakdown: {
    tierLabel: string
    principal: number
    monthlyPayment: number
    totalInterest: number
    termYears: number
    rate: number
  }[]
}

export function calculateAffordability(
  monthlyBudget: number,
  downPaymentPercent: number,
  tiers: { label: string; termYears: number; rate: number; allocation: number }[],
): AffordabilityScenario[] {
  const scenarios: AffordabilityScenario[] = []

  // Helper: compute a scenario for a given tier mix
  function compute(
    label: string,
    description: string,
    mix: { label: string; termYears: number; rate: number; allocation: number }[],
  ): AffordabilityScenario {
    // Each tier gets a fraction of the monthly budget proportional to its allocation
    const totalAlloc = mix.reduce((s, t) => s + t.allocation, 0)
    const breakdown = mix.map(tier => {
      const allocFrac = tier.allocation / totalAlloc
      const tierBudget = monthlyBudget * allocFrac
      const termMonths = tier.termYears * 12
      const principal = maxPrincipal(tierBudget, tier.rate, termMonths)
      const mp = tierBudget
      const totalPaid = mp * termMonths
      const totalInterest = totalPaid - principal
      return {
        tierLabel: tier.label,
        principal,
        monthlyPayment: mp,
        totalInterest,
        termYears: tier.termYears,
        rate: tier.rate,
      }
    })

    const totalLoan = breakdown.reduce((s, b) => s + b.principal, 0)
    const totalInterest = breakdown.reduce((s, b) => s + b.totalInterest, 0)
    const totalPaid = breakdown.reduce((s, b) => s + b.monthlyPayment * b.termYears * 12, 0)
    const longestTerm = Math.max(...mix.map(t => t.termYears))
    const propertyValue = downPaymentPercent > 0
      ? totalLoan / (1 - downPaymentPercent / 100)
      : totalLoan

    return {
      label,
      description,
      tiers: mix,
      maxLoan: totalLoan,
      propertyValue,
      monthlyPayment: monthlyBudget,
      totalInterest,
      totalPaid,
      payoffYears: longestTerm,
      breakdown,
    }
  }

  // Scenario 1: Default tier mix
  if (tiers.length > 1) {
    scenarios.push(compute('Blended', 'Default tier allocation across all terms', tiers))
  }

  // Scenario 2: Each single tier
  for (const tier of tiers) {
    scenarios.push(compute(
      `All ${tier.label}`,
      `Entire loan at ${(tier.rate * 100).toFixed(1)}% for ${tier.termYears} years`,
      [{ ...tier, allocation: 1 }],
    ))
  }

  // Scenario 3: Short-heavy mix (if multiple tiers)
  if (tiers.length >= 3) {
    const sorted = [...tiers].sort((a, b) => a.termYears - b.termYears)
    const shortHeavy = sorted.map((t, i) => ({
      ...t,
      allocation: i === 0 ? 0.5 : (0.5 / (sorted.length - 1)),
    }))
    scenarios.push(compute(
      'Short-Heavy',
      `50% in shortest term (${sorted[0].label}), rest spread`,
      shortHeavy,
    ))
  }

  // Scenario 4: Long-heavy mix (if multiple tiers)
  if (tiers.length >= 3) {
    const sorted = [...tiers].sort((a, b) => b.termYears - a.termYears)
    const longHeavy = sorted.map((t, i) => ({
      ...t,
      allocation: i === 0 ? 0.5 : (0.5 / (sorted.length - 1)),
    }))
    scenarios.push(compute(
      'Long-Heavy',
      `50% in longest term (${sorted[0].label}), rest spread`,
      longHeavy,
    ))
  }

  // Sort by max loan descending
  scenarios.sort((a, b) => b.maxLoan - a.maxLoan)

  return scenarios
}
