/**
 * Tests de las fórmulas "Ahorro esperado" y "Eficiencia" de ComparisonTable (Sprint 5, Etapa 5).
 * expectedSavings = savings × executionProbability
 * efficiency       = expectedSavings / executionTimeMinutes
 * Reglas de null: no automatable → null; savings <= 0 → null; efficiency además requiere
 * executionTimeMinutes > 0.
 *
 * Las fórmulas viven inline en el useMemo de ComparisonTable.tsx (no hay función pura
 * exportada — por scope de la etapa no se modifica el dominio). Estos tests replican
 * exactamente esa lógica para verificar las fórmulas y las reglas de null/ranking.
 */
import { describe, it, expect } from 'vitest'

interface Activity {
  savings: number
  automatable: boolean
  executionProbability: number
  executionTimeMinutes: number
}

function computeExpectedSavings(act: Activity): number | null {
  return act.automatable && act.savings > 0 ? act.savings * act.executionProbability : null
}

function computeEfficiency(act: Activity): number | null {
  return act.automatable && act.savings > 0 && act.executionTimeMinutes > 0
    ? (act.savings * act.executionProbability) / act.executionTimeMinutes
    : null
}

describe('ComparisonTable — fórmula Ahorro esperado', () => {
  it('calcula savings × executionProbability', () => {
    const act: Activity = { savings: 540, automatable: true, executionProbability: 0.8, executionTimeMinutes: 60 }
    expect(computeExpectedSavings(act)).toBeCloseTo(432)
  })

  it('probability 1.0 → expectedSavings === savings', () => {
    const act: Activity = { savings: 270, automatable: true, executionProbability: 1.0, executionTimeMinutes: 30 }
    expect(computeExpectedSavings(act)).toBe(270)
  })

  it('no automatable → null', () => {
    const act: Activity = { savings: 540, automatable: false, executionProbability: 1.0, executionTimeMinutes: 60 }
    expect(computeExpectedSavings(act)).toBeNull()
  })

  it('savings <= 0 → null', () => {
    const act: Activity = { savings: 0, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 }
    expect(computeExpectedSavings(act)).toBeNull()
    const negative: Activity = { savings: -100, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 }
    expect(computeExpectedSavings(negative)).toBeNull()
  })

  it('executionProbability 0 → resultado 0, no null (0 sigue siendo un valor válido salvo que savings <= 0)', () => {
    const act: Activity = { savings: 540, automatable: true, executionProbability: 0, executionTimeMinutes: 60 }
    expect(computeExpectedSavings(act)).toBe(0)
  })
})

describe('ComparisonTable — fórmula Eficiencia', () => {
  it('calcula (savings × executionProbability) / executionTimeMinutes', () => {
    const act: Activity = { savings: 540, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 }
    expect(computeEfficiency(act)).toBeCloseTo(9.0)
  })

  it('considera executionProbability fraccionaria', () => {
    const act: Activity = { savings: 300, automatable: true, executionProbability: 0.5, executionTimeMinutes: 30 }
    expect(computeEfficiency(act)).toBeCloseTo(5.0)
  })

  it('no automatable → null', () => {
    const act: Activity = { savings: 540, automatable: false, executionProbability: 1.0, executionTimeMinutes: 60 }
    expect(computeEfficiency(act)).toBeNull()
  })

  it('savings <= 0 → null', () => {
    const act: Activity = { savings: -50, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 }
    expect(computeEfficiency(act)).toBeNull()
  })

  it('executionTimeMinutes === 0 → null aunque savings sea válido', () => {
    const act: Activity = { savings: 540, automatable: true, executionProbability: 1.0, executionTimeMinutes: 0 }
    expect(computeEfficiency(act)).toBeNull()
  })

  it('executionTimeMinutes === 0 pero expectedSavings sigue siendo válido (no null)', () => {
    const act: Activity = { savings: 540, automatable: true, executionProbability: 1.0, executionTimeMinutes: 0 }
    expect(computeExpectedSavings(act)).toBe(540)
    expect(computeEfficiency(act)).toBeNull()
  })

  it('executionProbability 0 → resultado 0, no null', () => {
    const act: Activity = { savings: 540, automatable: true, executionProbability: 0, executionTimeMinutes: 60 }
    expect(computeEfficiency(act)).toBe(0)
  })
})

describe('ComparisonTable — ranking con valores null', () => {
  function rankByEfficiency(acts: Activity[]): (number | null)[] {
    return acts
      .map(computeEfficiency)
      .sort((a, b) => (b ?? -Infinity) - (a ?? -Infinity))
  }

  it('filas con efficiency null quedan siempre al final del sort descendente', () => {
    const acts: Activity[] = [
      { savings: -10, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 },  // null
      { savings: 600, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 },  // 10
      { savings: 60, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 },   // 1
    ]
    const ranked = rankByEfficiency(acts)
    expect(ranked[0]).toBeCloseTo(10)
    expect(ranked[1]).toBeCloseTo(1)
    expect(ranked[ranked.length - 1]).toBeNull()
  })

  it('fila nula siempre por debajo de una fila con efficiency 0.01', () => {
    const acts: Activity[] = [
      { savings: -5, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 },     // null
      { savings: 0.6, automatable: true, executionProbability: 1.0, executionTimeMinutes: 60 },    // 0.01
    ]
    const ranked = rankByEfficiency(acts)
    expect(ranked[0]).toBeCloseTo(0.01)
    expect(ranked[1]).toBeNull()
  })
})
