import { describe, it, expect } from 'vitest'
import { formatCurrency, formatPercent, formatMinutes, formatSimulationTimestamp } from '@/lib/format'

// ─── formatCurrency ───────────────────────────────────────────────────────────
describe('formatCurrency', () => {
  // USD
  it('USD: formatea 0 correctamente', () => {
    const result = formatCurrency(0, 'USD')
    expect(result).toMatch(/0/)
    expect(result).toMatch(/\$|USD/)
  })

  it('USD: formatea 1 con 2 decimales', () => {
    const result = formatCurrency(1, 'USD')
    expect(result).toMatch(/1[.,]00/)
  })

  it('USD: formatea 1000 con separador de miles', () => {
    const result = formatCurrency(1000, 'USD')
    // Debe tener separador (coma o punto) antes de los tres ceros
    expect(result).toMatch(/1[.,]000/)
  })

  it('USD: formatea 1234567 con separadores', () => {
    const result = formatCurrency(1234567, 'USD')
    expect(result).toMatch(/1/)
    expect(result).toMatch(/234/)
    expect(result).toMatch(/567/)
  })

  it('USD: formatea decimales correctamente', () => {
    const result = formatCurrency(1234.56, 'USD')
    expect(result).toMatch(/1[.,]234/)
    expect(result).toMatch(/56/)
  })

  // PYG — el guaraní no tiene decimales centavos en la práctica
  it('PYG: devuelve una cadena con el valor', () => {
    const result = formatCurrency(1000000, 'PYG')
    expect(result).toBeTruthy()
    expect(typeof result).toBe('string')
    expect(result.length).toBeGreaterThan(0)
  })

  it('PYG: 0 formatea sin crash', () => {
    expect(() => formatCurrency(0, 'PYG')).not.toThrow()
  })

  it('PYG: número grande formatea sin crash', () => {
    expect(() => formatCurrency(1_234_567_890, 'PYG')).not.toThrow()
    const result = formatCurrency(1_234_567_890, 'PYG')
    expect(result).toMatch(/1/)
  })

  // BRL
  it('BRL: formatea con símbolo correcto', () => {
    const result = formatCurrency(1000, 'BRL')
    expect(result).toBeTruthy()
    // El símbolo R$ puede aparecer o la abreviatura BRL
    expect(result).toMatch(/1/)
  })

  // EUR
  it('EUR: formatea 1234.56 sin crash', () => {
    expect(() => formatCurrency(1234.56, 'EUR')).not.toThrow()
    const result = formatCurrency(1234.56, 'EUR')
    expect(result).toMatch(/1/)
  })

  // Negativos — el reporte no debe tener valores negativos, pero la función no debe crashear
  it('No crashea con valores negativos', () => {
    expect(() => formatCurrency(-100, 'USD')).not.toThrow()
    const result = formatCurrency(-100, 'USD')
    expect(result).toMatch(/-|100/)
  })

  // Múltiples monedas producen outputs distintos
  it('USD y PYG producen outputs distintos para el mismo número', () => {
    const usd = formatCurrency(1000, 'USD')
    const pyg = formatCurrency(1000, 'PYG')
    expect(usd).not.toBe(pyg)
  })
})

// ─── formatMinutes ────────────────────────────────────────────────────────────
describe('formatMinutes', () => {
  it('5 min → "5 min"', () => {
    expect(formatMinutes(5)).toBe('5 min')
  })

  it('30 min → "30 min"', () => {
    expect(formatMinutes(30)).toBe('30 min')
  })

  it('59 min → "59 min" (aún no llega a 1h)', () => {
    expect(formatMinutes(59)).toBe('59 min')
  })

  it('60 min → "1h" (exactamente 1 hora)', () => {
    expect(formatMinutes(60)).toBe('1h')
  })

  it('90 min → "1h 30min"', () => {
    expect(formatMinutes(90)).toBe('1h 30min')
  })

  it('125 min → "2h 5min"', () => {
    expect(formatMinutes(125)).toBe('2h 5min')
  })

  it('120 min → "2h" (horas exactas, sin fracción)', () => {
    expect(formatMinutes(120)).toBe('2h')
  })

  it('1440 min → "24h" (un día completo)', () => {
    expect(formatMinutes(1440)).toBe('24h')
  })

  it('0 min → "0 min"', () => {
    expect(formatMinutes(0)).toBe('0 min')
  })

  it('No crashea con valores decimales', () => {
    expect(() => formatMinutes(90.7)).not.toThrow()
  })
})

// ─── formatPercent ────────────────────────────────────────────────────────────
// Nota: el locale es-PY usa coma como separador decimal → "23,4%" no "23.4%".
// Los tests verifican estructura (contiene el valor y el símbolo) sin asumir separador.
describe('formatPercent', () => {
  it('23.4 → contiene "23" y "4" y "%" con 1 decimal', () => {
    const result = formatPercent(23.4)
    expect(result).toContain('23')
    expect(result).toContain('4')
    expect(result).toContain('%')
  })

  it('100 → contiene "100" y "%" con 1 decimal', () => {
    const result = formatPercent(100)
    expect(result).toContain('100')
    expect(result).toContain('%')
  })

  it('0 → contiene "0" y "%" sin crash', () => {
    const result = formatPercent(0)
    expect(result).toContain('0')
    expect(result).toContain('%')
  })

  it('el locale es-PY usa coma decimal: 23.4 → "23,4%"', () => {
    // Documenta el comportamiento real del locale configurado
    expect(formatPercent(23.4)).toBe('23,4%')
  })

  it('100% con 0 decimales → "100%"', () => {
    expect(formatPercent(100, 0)).toBe('100%')
  })

  it('20 con 0 decimales → "20%"', () => {
    expect(formatPercent(20, 0)).toBe('20%')
  })
})

// ─── formatSimulationTimestamp ────────────────────────────────────────────────
describe('formatSimulationTimestamp', () => {
  // Timestamp fijo para reproducibilidad: 13 de mayo de 2026, 09:45 UTC-4 (PY hora de verano)
  // Usamos una fecha conocida y verificamos la estructura del output sin depender de TZ del CI.
  const KNOWN_TS = new Date('2026-05-13T13:45:00Z').getTime() // UTC

  it('devuelve objeto con date y time strings no vacíos', () => {
    const { date, time } = formatSimulationTimestamp(KNOWN_TS)
    expect(date.length).toBeGreaterThan(0)
    expect(time.length).toBeGreaterThan(0)
  })

  it('date contiene el año 2026', () => {
    const { date } = formatSimulationTimestamp(KNOWN_TS)
    expect(date).toContain('2026')
  })

  it('date contiene el número 13 (día)', () => {
    const { date } = formatSimulationTimestamp(KNOWN_TS)
    expect(date).toContain('13')
  })

  it('date contiene "mayo" (nombre del mes en es-PY)', () => {
    const { date } = formatSimulationTimestamp(KNOWN_TS)
    expect(date).toMatch(/mayo/i)
  })

  it('time tiene formato HH:mm (dos pares de dígitos separados por ":")', () => {
    const { time } = formatSimulationTimestamp(KNOWN_TS)
    expect(time).toMatch(/\d{1,2}:\d{2}/)
  })

  it('no crashea con timestamp 0 (epoch)', () => {
    expect(() => formatSimulationTimestamp(0)).not.toThrow()
    const { date, time } = formatSimulationTimestamp(0)
    expect(date.length).toBeGreaterThan(0)
    expect(time.length).toBeGreaterThan(0)
  })

  it('timestamps distintos producen salidas distintas', () => {
    const ts1 = new Date('2026-01-01T10:00:00Z').getTime()
    const ts2 = new Date('2026-06-15T18:30:00Z').getTime()
    const r1 = formatSimulationTimestamp(ts1)
    const r2 = formatSimulationTimestamp(ts2)
    expect(r1.date).not.toBe(r2.date)
  })
})
