/**
 * Tests del recálculo de ROI ajustado por sliders de sensibilidad (Sprint 6, Etapa 2).
 *
 * La lógica vive inline en el useMemo `adjustedRoi` de ReportPage.tsx — no hay una función
 * pura exportada (no se modifica domain/roi.ts por scope de la etapa). Estos tests replican
 * exactamente esa transformación de inputs y verifican el comportamiento de calculateRoi()
 * con los valores ajustados, igual que lo hace el componente.
 */
import { describe, it, expect } from 'vitest'
import { calculateRoi, type RoiInput } from '@/domain/roi'

const BASE: Omit<RoiInput, 'annualFrequency' | 'automationInvestment'> = {
  costPerExecutionActual: 600,
  costPerExecutionAutomated: 60,
  analysisHorizonYears: 3,
}

const BASE_FREQUENCY = 1200
const BASE_INVESTMENT = 50_000

function adjustedRoi(volumeAdjust: number, investmentAdjust: number) {
  return calculateRoi({
    ...BASE,
    annualFrequency: BASE_FREQUENCY * (1 + volumeAdjust / 100),
    automationInvestment: BASE_INVESTMENT * (1 + investmentAdjust / 100),
  })
}

describe('Sensibilidad — ajuste de volumen anual', () => {
  it('volumen +20%: annualFrequency y annualSavings escalan 1.2x respecto al base', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(20, 0)
    expect(adjusted.annualSavings).toBeCloseTo(base.annualSavings * 1.2)
  })

  it('volumen -30%: annualSavings escala 0.7x, payback se alarga', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(-30, 0)
    expect(adjusted.annualSavings).toBeCloseTo(base.annualSavings * 0.7)
    expect(adjusted.paybackMonths).toBeGreaterThan(base.paybackMonths)
  })
})

describe('Sensibilidad — ajuste de inversión en automatización', () => {
  it('inversión +50%: payback se alarga 1.5x, ROI% baja proporcionalmente', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(0, 50)
    expect(adjusted.paybackMonths).toBeCloseTo(base.paybackMonths * 1.5)
    expect(adjusted.roiAnnualPercent).toBeCloseTo(base.roiAnnualPercent / 1.5)
  })

  it('inversión -50%: payback se acorta a la mitad, ROI% se duplica', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(0, -50)
    expect(adjusted.paybackMonths).toBeCloseTo(base.paybackMonths * 0.5)
    expect(adjusted.roiAnnualPercent).toBeCloseTo(base.roiAnnualPercent * 2)
  })
})

describe('Sensibilidad — ajuste combinado', () => {
  it('volumen +20% e inversión +50% simultáneos: ambos efectos se componen', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(20, 50)
    // annualSavings depende solo de volumen
    expect(adjusted.annualSavings).toBeCloseTo(base.annualSavings * 1.2)
    // payback = inversión / annualSavings → (1.5 * inv) / (1.2 * savings) = base * 1.25
    expect(adjusted.paybackMonths).toBeCloseTo(base.paybackMonths * (1.5 / 1.2))
  })

  it('volumen -30% e inversión -50% simultáneos', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(-30, -50)
    expect(adjusted.annualSavings).toBeCloseTo(base.annualSavings * 0.7)
    expect(adjusted.paybackMonths).toBeCloseTo(base.paybackMonths * (0.5 / 0.7))
  })
})

describe('Sensibilidad — reset a 0', () => {
  it('volumeAdjust=0 e investmentAdjust=0 reproduce exactamente el ROI base', () => {
    const base = calculateRoi({
      ...BASE,
      annualFrequency: BASE_FREQUENCY,
      automationInvestment: BASE_INVESTMENT,
    })
    const reset = adjustedRoi(0, 0)
    expect(reset).toEqual(base)
  })

  it('después de mover sliders, volver a 0/0 coincide con el valor base original', () => {
    adjustedRoi(40, -20) // simula haber movido los sliders
    const resetAgain = adjustedRoi(0, 0)
    const base = adjustedRoi(0, 0)
    expect(resetAgain).toEqual(base)
  })
})

describe('Sensibilidad — límites del rango (-50 a +100)', () => {
  it('volumen en el límite inferior (-50%) no produce frecuencia negativa', () => {
    const adjusted = adjustedRoi(-50, 0)
    expect(adjusted.annualSavings).toBeGreaterThanOrEqual(0)
  })

  it('volumen en el límite superior (+100%) duplica el ahorro anual', () => {
    const base = adjustedRoi(0, 0)
    const adjusted = adjustedRoi(100, 0)
    expect(adjusted.annualSavings).toBeCloseTo(base.annualSavings * 2)
  })
})
