/**
 * Tests unitarios de drawResourcesSection (Sprint 2, Etapa 6).
 *
 * drawResourcesSection toma doc: any y autoTable: Function directamente,
 * por lo que no necesita mock de jspdf — se pasa un objeto plano.
 */
import { describe, it, expect, vi, beforeEach } from 'vitest'
import type { ActivitySimResult, Resource, Activity } from '@/domain/types'

// ─── Mock doc (jsPDF API mínima usada por drawResourcesSection) ───────────────

const mockDoc = {
  setFont: vi.fn(),
  setFontSize: vi.fn(),
  setTextColor: vi.fn(),
  setDrawColor: vi.fn(),
  setLineWidth: vi.fn(),
  text: vi.fn(),
  line: vi.fn(),
}

// ─── Fixtures ─────────────────────────────────────────────────────────────────

const mockResource: Resource = {
  id: 'r1', processId: 'p1', name: 'Analista Senior', type: 'role', costPerHour: 60,
}

const mockActivity: Activity = {
  id: 'a1', processId: 'p1', bpmnElementId: 'task1', name: 'Recibir solicitud', type: 'task',
  directCostFixed: 600, executionTimeMinutes: 60,
  assignedResources: [{ resourceId: 'r1', utilizationMinutes: 60, units: 1 }],
  automatable: false, automatedCostFixed: 0, automatedTimeMinutes: 0,
  automatedAssignedResources: [{ resourceId: 'r1', utilizationMinutes: 5, units: 3 }],
}

const activityWithResources: ActivitySimResult = {
  activityId: 'a1', bpmnElementId: 'task1', activityName: 'Recibir solicitud',
  expectedDirectCost: 660, expectedIndirectCost: 0, expectedTotalCost: 660,
  percentOfTotal: 100, executionProbability: 1.0, expectedExecutions: 1.0,
  executionTimeMinutes: 60,
  resourceCostBreakdown: [{ resourceId: 'r1', resourceName: 'Analista Senior', cost: 60 }],
}

const activityWithoutResources: ActivitySimResult = {
  activityId: 'a2', bpmnElementId: 'task2', activityName: 'Archivar',
  expectedDirectCost: 100, expectedIndirectCost: 0, expectedTotalCost: 100,
  percentOfTotal: 0, executionProbability: 1.0, expectedExecutions: 1.0,
  executionTimeMinutes: 10, resourceCostBreakdown: [],
}

// ─── Tests ────────────────────────────────────────────────────────────────────

describe('drawResourcesSection', () => {
  let autoTableMock: ReturnType<typeof vi.fn>

  beforeEach(() => {
    vi.clearAllMocks()
    autoTableMock = vi.fn()
  })

  it('no lanza error con actividades que tienen recursos', async () => {
    const { drawResourcesSection } = await import('@/lib/export/pdf-sections')
    expect(() =>
      drawResourcesSection(
        mockDoc,
        autoTableMock,
        { perActivity: [activityWithResources] },
        [mockResource],
        [mockActivity],
        'USD',
        40
      )
    ).not.toThrow()
    expect(autoTableMock).toHaveBeenCalledTimes(1)
  })

  it('no llama a autoTable si todas las actividades tienen resourceCostBreakdown vacío', async () => {
    const { drawResourcesSection } = await import('@/lib/export/pdf-sections')
    drawResourcesSection(
      mockDoc,
      autoTableMock,
      { perActivity: [activityWithoutResources] },
      [mockResource],
      [mockActivity],
      'USD',
      40
    )
    expect(autoTableMock).not.toHaveBeenCalled()
  })

  it('el header de autoTable incluye la moneda correcta', async () => {
    const { drawResourcesSection } = await import('@/lib/export/pdf-sections')
    drawResourcesSection(
      mockDoc,
      autoTableMock,
      { perActivity: [activityWithResources] },
      [mockResource],
      [mockActivity],
      'PYG',
      40
    )
    const callArgs = autoTableMock.mock.calls[0][1] as { head: unknown[][] }
    const headFlat = JSON.stringify(callArgs.head)
    expect(headFlat).toContain('PYG')
  })

  it('llama a autoTable exactamente una vez aunque haya varias actividades con recursos', async () => {
    const { drawResourcesSection } = await import('@/lib/export/pdf-sections')
    const secondActivity: ActivitySimResult = {
      ...activityWithResources,
      activityId: 'a3', activityName: 'Evaluar solicitud',
      resourceCostBreakdown: [{ resourceId: 'r1', resourceName: 'Analista Senior', cost: 30 }],
    }
    drawResourcesSection(
      mockDoc,
      autoTableMock,
      { perActivity: [activityWithResources, secondActivity] },
      [mockResource],
      [mockActivity],
      'USD',
      40
    )
    expect(autoTableMock).toHaveBeenCalledTimes(1)
  })
})

// ─── Escenario automatizado usa automatedAssignedResources ────────────────────

describe('drawResourcesSection — escenario automatizado', () => {
  let autoTableMock: ReturnType<typeof vi.fn>

  beforeEach(() => {
    autoTableMock = vi.fn()
  })

  it('escenario automatizado: pasa utilizationMinutes y units de automatedAssignedResources', async () => {
    const { drawResourcesSection } = await import('@/lib/export/pdf-sections')
    drawResourcesSection(
      mockDoc, autoTableMock,
      { perActivity: [activityWithResources] },
      [mockResource], [mockActivity], 'USD', 40,
      'automatizado'
    )
    const body = (autoTableMock.mock.calls[0][1] as any).body as any[][]
    const row = body[0]
    // Min. (índice 4) y Uds. (índice 5) deben venir de automatedAssignedResources: { utilMin: 5, units: 3 }
    expect(row[4].content).toBe('5')
    expect(row[5].content).toBe('3')
  })

  it('escenario actual: pasa utilizationMinutes y units de assignedResources (sin regresión)', async () => {
    const { drawResourcesSection } = await import('@/lib/export/pdf-sections')
    drawResourcesSection(
      mockDoc, autoTableMock,
      { perActivity: [activityWithResources] },
      [mockResource], [mockActivity], 'USD', 40,
      'actual'
    )
    const body = (autoTableMock.mock.calls[0][1] as any).body as any[][]
    const row = body[0]
    // assignedResources: { utilMin: 60, units: 1 }
    expect(row[4].content).toBe('60')
    expect(row[5].content).toBe('1')
  })
})
