import { buildFileName } from './slug'
import { formatPayback } from '@/lib/format'
import { calculateRoi } from '@/domain/roi'
import {
  drawScenarioPage1,
  drawHeatmapImage, drawHeatmapLegend,
  drawAnalysisSection, drawMethodologySection, drawResourcesSection, PDF,
} from './pdf-sections'
import {
  drawRoiPage1, buildComparisonTableConfig,
  drawRoiAnalysisPage, drawRoiMethodologySection, drawTrajectoryChart,
} from './pdf-sections-roi'
import { drawSharedHeader, applyFootersToAllPages } from './pdf-sections-shared'
import type { Process, Simulation, Resource, Activity } from '@/domain/types'

export type ReportTab = 'actual' | 'automatizado' | 'roi'

export interface PdfExportParams {
  process: Process
  simulation: Simulation
  resources: Resource[]
  heatmapImageData: string | null
  tab?: ReportTab           // default: 'actual'
  activities?: Activity[]  // requerido para tab='roi' (transparencia + tabla)
}

export async function exportToPdf(params: PdfExportParams): Promise<void> {
  const { process, simulation, resources, heatmapImageData, tab = 'actual', activities = [] } = params
  const currency = process.currency

  const [{ jsPDF }, { default: autoTable }] = await Promise.all([
    import('jspdf'),
    import('jspdf-autotable'),
  ])

  const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' })

  if (tab === 'roi') {
    await exportRoiPdf(doc, autoTable, process, simulation, activities, currency)
  } else {
    const result = tab === 'automatizado'
      ? (simulation.resultAutomated ?? simulation.result)
      : simulation.result
    await exportScenarioPdf(doc, autoTable, process, simulation, result, resources, heatmapImageData, currency, tab as 'actual' | 'automatizado', activities)
  }

  const suffix = tab === 'roi' ? '_roi' : tab === 'automatizado' ? '_automatizado' : '_actual'
  const fileName = buildFileName(process.name, process.clientName, new Date(simulation.executedAt), 'pdf', suffix)
  doc.save(fileName)
}

// ─── Escenario único (actual o automatizado) ──────────────────────────────────

async function exportScenarioPdf(
  doc: any,
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
  autoTable: Function,
  process: Process,
  simulation: Simulation,
  result: Simulation['result'],
  resources: Resource[],
  heatmapImageData: string | null,
  currency: string,
  tab: 'actual' | 'automatizado',
  activities: Activity[] = []
): Promise<void> {
  const docAny = doc as any
  const scenarioLabel = tab === 'actual' ? 'Escenario actual' : 'Escenario automatizado'

  docAny.setProperties({
    title: `Análisis de costos — ${scenarioLabel} — ${process.name}`,
    author: process.clientName || '',
    subject: 'Simulación de proceso BPMN',
    creator: 'InQ ROI',
    keywords: 'bpmn, costos, simulación',
  })

  const headerOpts = { processName: process.name, clientName: process.clientName || undefined, simulatedAt: simulation.executedAt }

  // ── Página 1 (portrait): Header denso + metadata + KPI grid (Etapa 8) ────────
  drawScenarioPage1(docAny, tab, process, simulation.executedAt, result, currency)
  let y: number

  // ── Página 2 (landscape): Diagrama BPMN con heatmap ─────────────────────────
  // Método obligatorio: doc.addPage('a4', 'landscape') — ver ETAPA_5_PROMPT §3.1
  docAny.addPage('a4', 'landscape')
  y = drawSharedHeader(docAny, { ...headerOpts, pageNumber: 2 })
  docAny.setFont('helvetica', 'bold')
  docAny.setFontSize(10)
  docAny.setTextColor(...PDF.slate900)
  docAny.text('Mapa de calor de costos', PDF.margin, y)
  y += 5
  y = drawHeatmapImage(docAny, heatmapImageData, y)
  y = drawHeatmapLegend(docAny, y)

  // ── Página 3 (portrait): Análisis + tabla + metodología ──────────────────────
  docAny.addPage('a4', 'portrait')
  y = drawSharedHeader(docAny, { ...headerOpts, pageNumber: 3 })
  y = drawAnalysisSection(docAny, result, currency, y)
  y += 6

  const RA = 'right' as const
  const tableHead = [[
    { content: 'Actividad', styles: { cellWidth: 48 } },
    { content: `Dir. (${currency})`, styles: { halign: RA, cellWidth: 25 } },
    { content: `Indir. (${currency})`, styles: { halign: RA, cellWidth: 25 } },
    { content: `Total (${currency})`, styles: { halign: RA, cellWidth: 28 } },
    { content: '% total', styles: { halign: RA, cellWidth: 16 } },
    { content: 'Tiempo', styles: { halign: RA, cellWidth: 14 } },
    { content: 'Prob.', styles: { halign: RA, cellWidth: 14 } },
  ]]

  const tableBody = result.perActivity.map((act) => [
    { content: act.activityName },
    { content: formatNum(act.expectedDirectCost), styles: { halign: RA, font: 'courier' } },
    { content: formatNum(act.expectedIndirectCost), styles: { halign: RA, font: 'courier' } },
    { content: formatNum(act.expectedTotalCost), styles: { halign: RA, font: 'courier' } },
    { content: `${act.percentOfTotal.toFixed(1)}%`, styles: { halign: RA, font: 'courier' } },
    { content: act.executionTimeMinutes > 0 ? formatTime(act.executionTimeMinutes) : '—', styles: { halign: RA } },
    { content: `${(act.executionProbability * 100).toFixed(0)}%`, styles: { halign: RA } },
  ])

  autoTable(docAny, {
    head: tableHead,
    body: tableBody,
    startY: y,
    margin: { left: PDF.margin, right: PDF.margin },
    styles: { fontSize: 7.5, cellPadding: 2.5, overflow: 'ellipsize', lineColor: [226, 232, 240], lineWidth: 0.2 },
    headStyles: {
      fillColor: [255, 248, 237],   // #FFF8ED naranja claro
      textColor: [146, 64, 14],     // #92400E naranja oscuro
      fontStyle: 'bold',
      fontSize: 8,
      lineColor: [245, 152, 69],    // #F59845 border naranja
      lineWidth: 0.5,
    },
    alternateRowStyles: { fillColor: PDF.slate50 },
    columnStyles: { 0: { cellWidth: 48 } },
  })

  // ── Página 4 condicional: Tabla de recursos (solo si hay actividades con recursos)
  const hasResources = result.perActivity.some((act) => act.resourceCostBreakdown.length > 0)

  if (hasResources) {
    docAny.addPage('a4', 'portrait')
    y = drawSharedHeader(docAny, { ...headerOpts, pageNumber: 4 })
    drawResourcesSection(docAny, autoTable, result, resources, activities, currency, y, tab)
  }

  // ── Página 4 o 5: Nota metodológica ──────────────────────────────────────────
  docAny.addPage('a4', 'portrait')
  y = drawSharedHeader(docAny, { ...headerOpts, pageNumber: hasResources ? 5 : 4 })
  drawMethodologySection(docAny, process, y)

  applyFootersToAllPages(docAny, { clientName: process.clientName || undefined, simulatedAt: simulation.executedAt })
}

// ─── ROI — 5 páginas (Etapa 6) ───────────────────────────────────────────────

async function exportRoiPdf(
  doc: any,
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
  autoTable: Function,
  process: Process,
  simulation: Simulation,
  activities: Activity[],
  currency: string
): Promise<void> {
  const result = simulation.result
  const resultAutomated = simulation.resultAutomated ?? result

  const roi = calculateRoi({
    costPerExecutionActual: result.totalCost,
    costPerExecutionAutomated: resultAutomated.totalCost,
    annualFrequency: process.annualFrequency,
    analysisHorizonYears: process.analysisHorizonYears,
    automationInvestment: process.automationInvestment,
  })

  doc.setProperties({
    title: `Análisis de ROI - ${process.name}`,
    author: process.clientName || '',
    subject: 'Análisis de retorno de inversión para automatización BPMN',
    creator: 'InQ ROI',
    keywords: 'bpmn, roi, automatización, payback',
  })

  const roiHeaderOpts = { processName: process.name, clientName: process.clientName || undefined, simulatedAt: simulation.executedAt }

  // ── Página 1: Rediseño completo InQ (Etapa 6) ───────────────────────────────
  drawRoiPage1(doc, process, roi, simulation.executedAt, result.perActivity, resultAutomated.perActivity, currency)

  // ── Página 2: Tabla comparativa ────────────────────────────────────────────
  doc.addPage()
  let y = drawSharedHeader(doc, { ...roiHeaderOpts, pageNumber: 2 })

  doc.setFont('helvetica', 'bold')
  doc.setFontSize(12)
  doc.setTextColor(...PDF.slate900)
  doc.text('Comparación por actividad', PDF.margin, y)
  y += 4

  doc.setFont('helvetica', 'normal')
  doc.setFontSize(8)
  doc.setTextColor(...PDF.slate500)
  doc.text('(*) Actividades en negrita están marcadas como automatizables', PDF.margin, y + 3)
  y += 8

  const tableConfig = buildComparisonTableConfig(
    result.perActivity,
    resultAutomated.perActivity,
    activities,
    currency,
    y
  )
  autoTable(doc, tableConfig)

  // ── Página 3: Análisis textual + transparencia ─────────────────────────────
  doc.addPage()
  y = drawSharedHeader(doc, { ...roiHeaderOpts, pageNumber: 3 })
  drawRoiAnalysisPage(doc, roi, process, result.perActivity, resultAutomated.perActivity, activities, currency, y)

  // ── Página 4: Metodología ──────────────────────────────────────────────────
  doc.addPage()
  y = drawSharedHeader(doc, { ...roiHeaderOpts, pageNumber: 4 })
  drawRoiMethodologySection(doc, process, y)

  // ── Página 5: Trayectoria del ahorro acumulado (gráfico SVG nativo) ──────────
  doc.addPage()
  y = drawSharedHeader(doc, { ...roiHeaderOpts, pageNumber: 5 })

  // Título y subtítulo de la página
  doc.setFont('helvetica', 'bold')
  doc.setFontSize(11)
  doc.setTextColor(146, 64, 14)  // #92400E naranja oscuro
  doc.text('TRAYECTORIA DEL AHORRO ACUMULADO', PDF.margin, y)
  y += 6

  const subtitleText = roi.breaksEvenInHorizon
    ? `Evolución del ahorro neto acumulado a lo largo de ${process.analysisHorizonYears} años. El payback se alcanza en ${formatPayback(roi.paybackMonths)}.`
    : `Evolución del ahorro neto acumulado a lo largo de ${process.analysisHorizonYears} años. El payback no se alcanza en el horizonte analizado.`

  doc.setFont('helvetica', 'normal')
  doc.setFontSize(9)
  doc.setTextColor(...PDF.slate500)
  const subtitleLines = doc.splitTextToSize(subtitleText, PDF.contentW)
  doc.text(subtitleLines, PDF.margin, y)
  y += subtitleLines.length * 4.5 + 6

  drawTrajectoryChart(doc, roi, process, currency, PDF.margin, PDF.contentW, y)

  applyFootersToAllPages(doc, { clientName: process.clientName || undefined, simulatedAt: simulation.executedAt })
}

function formatNum(n: number): string {
  return n.toLocaleString('es-PY', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}

function formatTime(minutes: number): string {
  if (minutes < 60) return `${Math.round(minutes)}m`
  const h = Math.floor(minutes / 60)
  const m = Math.round(minutes % 60)
  return m > 0 ? `${h}h ${m}m` : `${h}h`
}
