/**
 * Tests del módulo compartido de header/footer PDF — Etapa 4 Sprint 1.5.
 */
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { PDF_COLORS, drawSharedHeader, drawSharedFooter, applyFootersToAllPages } from '@/lib/export/pdf-sections-shared'

// ─── Mock DocLike ─────────────────────────────────────────────────────────────

function makeMockDoc(pageW = 210, pageH = 297, totalPages = 2) {
  return {
    setFont: vi.fn(),
    setFontSize: vi.fn(),
    setTextColor: vi.fn(),
    setFillColor: vi.fn(),
    setDrawColor: vi.fn(),
    setLineWidth: vi.fn(),
    text: vi.fn(),
    rect: vi.fn(),
    roundedRect: vi.fn(),
    line: vi.fn(),
    addImage: vi.fn(),
    addPage: vi.fn(),
    setPage: vi.fn(),
    splitTextToSize: vi.fn().mockImplementation((t: string) => [t]),
    internal: {
      getNumberOfPages: vi.fn().mockReturnValue(totalPages),
      pageSize: {
        getWidth: vi.fn().mockReturnValue(pageW),
        getHeight: vi.fn().mockReturnValue(pageH),
      },
    },
  }
}

const BASE_OPTS = { processName: 'Proceso de prueba', simulatedAt: new Date('2026-05-17T10:00:00Z').getTime() }

// ─── PDF_COLORS ───────────────────────────────────────────────────────────────

describe('PDF_COLORS', () => {
  it('expone inqOrange como array RGB válido [245, 152, 69]', () => {
    expect(PDF_COLORS.inqOrange).toEqual([245, 152, 69])
  })

  it('NO incluye colores de CONCILIA (#572FA2 → [87, 47, 162])', () => {
    const all = JSON.stringify(PDF_COLORS)
    expect(all).not.toContain('87, 47, 162')   // #572FA2 morado CONCILIA
    expect(all).not.toContain('203, 24, 137')  // #CB1889 magenta CONCILIA
  })

  it('tiene al menos 8 colores definidos', () => {
    expect(Object.keys(PDF_COLORS).length).toBeGreaterThanOrEqual(8)
  })
})

// ─── drawSharedHeader ─────────────────────────────────────────────────────────

describe('drawSharedHeader', () => {
  let doc: ReturnType<typeof makeMockDoc>

  beforeEach(() => { doc = makeMockDoc() })

  it('retorna un número mayor que el margen (20mm) — espacio del header', () => {
    const y = drawSharedHeader(doc, { ...BASE_OPTS, pageNumber: 1 })
    expect(y).toBeGreaterThan(20)
  })

  it('dibuja border-bottom más grueso en página 1 que en páginas siguientes', () => {
    drawSharedHeader(doc, { ...BASE_OPTS, pageNumber: 1 })
    const page1LineWidths = doc.setLineWidth.mock.calls.map((c: number[]) => c[0])

    doc.setLineWidth.mockClear()
    drawSharedHeader(doc, { ...BASE_OPTS, pageNumber: 2 })
    const page2LineWidths = doc.setLineWidth.mock.calls.map((c: number[]) => c[0])

    // El grosor máximo de página 1 debe ser mayor que el de página 2
    expect(Math.max(...page1LineWidths)).toBeGreaterThan(Math.max(...page2LineWidths))
  })

  it('dibuja el texto "InQ ROI" en la primera llamada a text()', () => {
    drawSharedHeader(doc, { ...BASE_OPTS, pageNumber: 1 })
    const firstTextCall = doc.text.mock.calls[0]
    expect(firstTextCall[0]).toBe('InQ ROI')
  })

  it('usa inqOrange para el texto del logo', () => {
    drawSharedHeader(doc, { ...BASE_OPTS, pageNumber: 1 })
    // La primera llamada a setTextColor debe ser el naranja InQ
    const firstColor = doc.setTextColor.mock.calls[0]
    expect(firstColor).toEqual(PDF_COLORS.inqOrange)
  })

  it('usa doc.internal.pageSize.getWidth() — compatible con landscape', () => {
    const landscapeDoc = makeMockDoc(297, 210)
    const y = drawSharedHeader(landscapeDoc, { ...BASE_OPTS, pageNumber: 1 })
    expect(landscapeDoc.internal.pageSize.getWidth).toHaveBeenCalled()
    expect(y).toBeGreaterThan(20)
  })
})

// ─── drawSharedFooter ─────────────────────────────────────────────────────────

describe('drawSharedFooter', () => {
  let doc: ReturnType<typeof makeMockDoc>

  beforeEach(() => { doc = makeMockDoc() })

  it('incluye "InQ ROI" en el texto del footer', () => {
    drawSharedFooter(doc, { ...BASE_OPTS, pageNumber: 1, totalPages: 3 })
    const textCalls = doc.text.mock.calls.map((c: unknown[]) => c[0])
    expect(textCalls.some((t: unknown) => typeof t === 'string' && t.includes('InQ ROI'))).toBe(true)
  })

  it('incluye "Powered by InQuality" en el texto del footer', () => {
    drawSharedFooter(doc, { ...BASE_OPTS, pageNumber: 1, totalPages: 3 })
    const textCalls = doc.text.mock.calls.map((c: unknown[]) => c[0])
    expect(textCalls.some((t: unknown) => typeof t === 'string' && t.includes('Powered by InQuality'))).toBe(true)
  })

  it('muestra paginación correcta "Página X de Y"', () => {
    drawSharedFooter(doc, { ...BASE_OPTS, pageNumber: 2, totalPages: 4 })
    const textCalls = doc.text.mock.calls.map((c: unknown[]) => c[0])
    expect(textCalls.some((t: unknown) => typeof t === 'string' && t === 'Página 2 de 4')).toBe(true)
  })

  it('NO incluye versión del producto (v0.1.0)', () => {
    drawSharedFooter(doc, { ...BASE_OPTS, pageNumber: 1, totalPages: 3 })
    const allText = doc.text.mock.calls.map((c: unknown[]) => c[0]).join(' ')
    expect(allText).not.toContain('v0.')
    expect(allText).not.toContain('v0.1')
  })

  it('usa doc.internal.pageSize.getHeight() para posición inferior', () => {
    drawSharedFooter(doc, { ...BASE_OPTS, pageNumber: 1, totalPages: 3 })
    expect(doc.internal.pageSize.getHeight).toHaveBeenCalled()
  })
})

// ─── applyFootersToAllPages ───────────────────────────────────────────────────

describe('applyFootersToAllPages', () => {
  it('llama setPage para cada página del documento', () => {
    const doc = makeMockDoc(210, 297, 4)
    applyFootersToAllPages(doc, BASE_OPTS)
    expect(doc.setPage).toHaveBeenCalledTimes(4)
    expect(doc.setPage).toHaveBeenNthCalledWith(1, 1)
    expect(doc.setPage).toHaveBeenNthCalledWith(4, 4)
  })
})
