import Papa from 'papaparse'
import { formatPayback, formatSimulationTimestamp } from '@/lib/format'
import { calculateRoi } from '@/domain/roi'
import { buildFileName } from './slug'
import type { Process, Simulation, Resource, Activity, ActivitySimResult } from '@/domain/types'

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

// Monedas que usan coma como separador decimal (necesitan punto y coma en el CSV)
const COMMA_DECIMAL_CURRENCIES = new Set(['PYG', 'BRL', 'EUR', 'ARS', 'COP', 'MXN', 'CLP'])

function getDelimiter(currency: string): string {
  return COMMA_DECIMAL_CURRENCIES.has(currency) ? ';' : ','
}

function formatDecimalForCsv(value: number, currency: string): string {
  const formatted = value.toFixed(2)
  if (COMMA_DECIMAL_CURRENCIES.has(currency)) {
    return formatted.replace('.', ',')
  }
  return formatted
}

function buildResourcesCell(act: ActivitySimResult, resources: Resource[]): string {
  if (act.resourceCostBreakdown.length === 0) return ''
  const resourceById = new Map(resources.map((r) => [r.id, r]))
  return act.resourceCostBreakdown
    .map((rb) => resourceById.get(rb.resourceId)?.name ?? rb.resourceName)
    .join('; ')
}

export interface CsvExportParams {
  process: Process
  simulation: Simulation
  resources: Resource[]
  tab?: ReportTab       // default: 'actual'
  activities?: Activity[] // requerido para tab='roi'
}

export function generateCsvContent(params: CsvExportParams): string {
  const { process, simulation, resources, tab = 'actual', activities = [] } = params
  const { currency } = process

  if (tab === 'roi') {
    return generateRoiCsvContent(process, simulation, resources, activities, currency)
  }

  const result = tab === 'automatizado'
    ? (simulation.resultAutomated ?? simulation.result)
    : simulation.result

  const delimiter = getDelimiter(currency)
  const { date } = formatSimulationTimestamp(simulation.executedAt)

  const meta = [
    `# Proceso: ${process.name}`,
    `# Cliente: ${process.clientName || 'N/A'}`,
    `# Fecha simulación: ${date}`,
    `# Moneda: ${currency}`,
    `# Escenario: ${tab === 'automatizado' ? 'Automatizado' : 'Actual'}`,
    `# Costo total (${currency}): ${formatDecimalForCsv(result.totalCost, currency)}`,
    `# Costo directo: ${formatDecimalForCsv(result.totalDirectCost, currency)}`,
    `# Costo indirecto (overhead ${(process.overheadPercentage * 100).toFixed(0)}%): ${formatDecimalForCsv(result.totalIndirectCost, currency)}`,
    '',
  ].join('\r\n')

  const headers = [
    'ID BPMN', 'Actividad', 'Tipo',
    `Costo directo (${currency})`, `Costo indirecto (${currency})`, `Costo total (${currency})`,
    '% del total', 'Tiempo (min)', 'Ejecuciones esperadas', 'Recursos asignados',
  ]

  const rows = result.perActivity.map((act) => [
    act.bpmnElementId,
    act.activityName,
    act.bpmnElementId.includes('subprocess') ? 'subproceso' : 'tarea',
    formatDecimalForCsv(act.expectedDirectCost, currency),
    formatDecimalForCsv(act.expectedIndirectCost, currency),
    formatDecimalForCsv(act.expectedTotalCost, currency),
    formatDecimalForCsv(act.percentOfTotal, currency),
    formatDecimalForCsv(act.executionTimeMinutes, currency),
    formatDecimalForCsv(act.executionProbability * 100, currency),
    buildResourcesCell(act, resources),
  ])

  const csvBody = Papa.unparse({ fields: headers, data: rows }, { delimiter, newline: '\r\n', quotes: true })
  return '﻿' + meta + csvBody
}

// ─── CSV de ROI: 16 columnas + metadata extendida ────────────────────────────

function generateRoiCsvContent(
  process: Process,
  simulation: Simulation,
  resources: Resource[],
  activities: Activity[],
  currency: string
): string {
  const resultActual = simulation.result
  const resultAutomated = simulation.resultAutomated ?? simulation.result
  const delimiter = getDelimiter(currency)
  const { date } = formatSimulationTimestamp(simulation.executedAt)

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

  const roiStr = !Number.isFinite(roi.roiAnnualPercent)
    ? 'Infinito'
    : formatDecimalForCsv(roi.roiAnnualPercent, currency)

  const meta = [
    `# Proceso: ${process.name}`,
    `# Cliente: ${process.clientName || 'N/A'}`,
    `# Fecha simulación: ${date}`,
    `# Moneda: ${currency}`,
    `# Costo total actual (${currency}): ${formatDecimalForCsv(resultActual.totalCost, currency)}`,
    `# Costo total automatizado (${currency}): ${formatDecimalForCsv(resultAutomated.totalCost, currency)}`,
    `# Ahorro por ejecución (${currency}): ${formatDecimalForCsv(roi.savingsPerExecution, currency)}`,
    `# Ahorro anual (${currency}): ${formatDecimalForCsv(roi.annualSavings, currency)}`,
    `# Payback (meses): ${formatPayback(roi.paybackMonths)}`,
    `# Payback (meses, raw): ${Number.isFinite(roi.paybackMonths) ? roi.paybackMonths.toFixed(4) : roi.paybackMonths}`,
    `# Ahorro acumulado a ${process.analysisHorizonYears} años (${currency}): ${formatDecimalForCsv(roi.cumulativeSavingsHorizon, currency)}`,
    `# ROI anualizado (%): ${roiStr}`,
    `# Frecuencia anual: ${process.annualFrequency}`,
    `# Horizonte de análisis: ${process.analysisHorizonYears} años`,
    `# Inversión en automatización (${currency}): ${formatDecimalForCsv(process.automationInvestment, currency)}`,
    '',
  ].join('\r\n')

  // Mapas para lookup eficiente
  const autoByBpmnId = new Map(resultAutomated.perActivity.map((a) => [a.bpmnElementId, a]))
  const actByBpmnId = new Map(activities.map((a) => [a.bpmnElementId, a]))

  const headers = [
    'ID BPMN',
    'Actividad',
    'Tipo',
    'Automatizable',
    'Probabilidad (%)',
    `Costo actual directo (${currency})`,
    `Costo actual indirecto (${currency})`,
    `Costo actual total (${currency})`,
    'Tiempo actual (min)',
    `Costo automatizado directo (${currency})`,
    `Costo automatizado indirecto (${currency})`,
    `Costo automatizado total (${currency})`,
    'Tiempo automatizado (min)',
    `Ahorro (${currency})`,
    'Ahorro (%)',
    'Recursos asignados',
  ]

  const rows = [...resultActual.perActivity]
    .sort((a, b) => {
      const aSavings = a.expectedTotalCost - (autoByBpmnId.get(a.bpmnElementId)?.expectedTotalCost ?? a.expectedTotalCost)
      const bSavings = b.expectedTotalCost - (autoByBpmnId.get(b.bpmnElementId)?.expectedTotalCost ?? b.expectedTotalCost)
      return bSavings - aSavings
    })
    .map((act) => {
      const autoAct = autoByBpmnId.get(act.bpmnElementId)
      const domainAct = actByBpmnId.get(act.bpmnElementId)
      const isAutomatable = domainAct?.automatable ?? false
      const automatedTime = domainAct?.automatedTimeMinutes ?? act.executionTimeMinutes

      const autoCostDirect = autoAct?.expectedDirectCost ?? act.expectedDirectCost
      const autoCostIndirect = autoAct?.expectedIndirectCost ?? act.expectedIndirectCost
      const autoCostTotal = autoAct?.expectedTotalCost ?? act.expectedTotalCost
      const savings = act.expectedTotalCost - autoCostTotal
      const savingsPct = act.expectedTotalCost > 0 ? (savings / act.expectedTotalCost) * 100 : 0

      return [
        act.bpmnElementId,
        act.activityName,
        act.bpmnElementId.includes('subprocess') ? 'subproceso' : 'tarea',
        isAutomatable ? 'true' : 'false',
        formatDecimalForCsv(act.executionProbability * 100, currency),
        formatDecimalForCsv(act.expectedDirectCost, currency),
        formatDecimalForCsv(act.expectedIndirectCost, currency),
        formatDecimalForCsv(act.expectedTotalCost, currency),
        formatDecimalForCsv(act.executionTimeMinutes, currency),
        formatDecimalForCsv(autoCostDirect, currency),
        formatDecimalForCsv(autoCostIndirect, currency),
        formatDecimalForCsv(autoCostTotal, currency),
        formatDecimalForCsv(automatedTime, currency),
        formatDecimalForCsv(savings, currency),
        formatDecimalForCsv(savingsPct, currency),
        buildResourcesCell(act, resources),
      ]
    })

  const csvBody = Papa.unparse({ fields: headers, data: rows }, { delimiter, newline: '\r\n', quotes: true })
  return '﻿' + meta + csvBody
}

export function exportToCsv(params: CsvExportParams): void {
  const content = generateCsvContent(params)
  const tab = params.tab ?? 'actual'
  const suffix = tab === 'roi' ? '_roi' : tab === 'automatizado' ? '_automatizado' : '_actual'
  const fileName = buildFileName(
    params.process.name,
    params.process.clientName,
    new Date(params.simulation.executedAt),
    'csv',
    suffix
  )

  const blob = new Blob([content], { type: 'text/csv;charset=utf-8' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = fileName
  a.click()
  URL.revokeObjectURL(url)
}
