/**
 * E2E: Verifica el export PDF y CSV del tab "Comparación + ROI".
 *
 * Flujo completo:
 *   1. Importar medium-with-gateways
 *   2. Configurar task_recv como automatizable ($50 de costo, 5 min)
 *   3. Configurar volumetría e inversión en el tab Global
 *   4. Simular ambos escenarios
 *   5. Navegar al tab "Comparación + ROI"
 *   6. Exportar PDF → verificar tamaño, páginas, keywords, acentos
 *   7. Exportar CSV → verificar BOM, 16 columnas, metadata ROI
 *
 * Test adicional: con BPMN sin automatizables, los tabs ROI y Automatizado
 * están disabled y los botones de export funcionan para el tab actual.
 *
 * Ejecutar: npx playwright test tests/e2e/export-roi.spec.ts
 */
import { test, expect } from '@playwright/test'
import { readFileSync, mkdirSync } from 'fs'
import { resolve } from 'path'
import { fileURLToPath } from 'url'
import { PDFParse } from 'pdf-parse'

const __dirname = fileURLToPath(new URL('.', import.meta.url))
const BPMN_DIR = resolve(__dirname, '../../public/sample-processes')
const OUTPUT_DIR = resolve(__dirname, '__output__')

test.beforeAll(() => {
  mkdirSync(OUTPUT_DIR, { recursive: true })
})

async function parsePdf(buffer: Buffer): Promise<{ numpages: number; text: string }> {
  const parser = new PDFParse({ data: buffer })
  const result = await parser.getText()
  await parser.destroy()
  return { numpages: result.total, text: result.text }
}

// ─── Helper: importar BPMN y llegar al workspace ──────────────────────────────

async function importBpmn(page: import('@playwright/test').Page, bpmnFile: string) {
  await page.goto('/')
  const fileInput = page.locator('#bpmn-file-input')
  await fileInput.setInputFiles(resolve(BPMN_DIR, bpmnFile))
  await page.waitForURL(/\/workspace\//, { timeout: 15_000 })
  await page.waitForSelector('button:has-text("Simular")', { timeout: 15_000 })
  await page.waitForTimeout(1_500)
}

// ─── Helper: configurar una actividad como automatizable ──────────────────────

async function makeAutomatable(
  page: import('@playwright/test').Page,
  elementId: string,
  cost: number,
  timeMin: number
) {
  // Click en el elemento BPMN en el canvas
  await page.locator(`[data-element-id="${elementId}"]`).first().click()
  await page.waitForTimeout(500)

  // Activar el toggle de automatizable
  const toggle = page.getByRole('switch', { name: /automatizable/i })
  if (await toggle.getAttribute('aria-checked') === 'false') {
    await toggle.click()
    await page.waitForTimeout(300)
  }

  // Ingresar costo automatizado
  const costInput = page.getByLabel(/Costo automatizado/i)
  await costInput.fill(String(cost))

  // Ingresar tiempo automatizado
  const timeInput = page.getByLabel(/Tiempo automatizado/i)
  await timeInput.fill(String(timeMin))

  // Guardar
  const guardarBtn = page.getByRole('button', { name: /Guardar/i })
  await guardarBtn.click()
  await page.waitForTimeout(500)
}

// ─── Helper: configurar volumetría en tab Global ──────────────────────────────

async function configureGlobal(
  page: import('@playwright/test').Page,
  annualFrequency: number,
  investment: number
) {
  // Ir al tab Global
  const globalTab = page.getByRole('tab', { name: /Global/i })
  await globalTab.click()
  await page.waitForTimeout(300)

  // Frecuencia anual
  const freqInput = page.getByLabel(/Frecuencia anual/i)
  await freqInput.fill(String(annualFrequency))

  // Inversión
  const investInput = page.getByLabel(/Inversión en automatización/i)
  await investInput.fill(String(investment))

  // Guardar
  const guardarBtn = page.getByRole('button', { name: /Guardar/i })
  await guardarBtn.click()
  await page.waitForTimeout(500)
}

// ─── Helper: simular y llegar al reporte ──────────────────────────────────────

async function simulateAndGoToReport(page: import('@playwright/test').Page) {
  const simBtn = page.getByRole('button', { name: 'Simular' })
  await expect(simBtn).not.toBeDisabled({ timeout: 5_000 })
  await simBtn.click()
  await page.waitForURL(/\/report\//, { timeout: 20_000 })
  await page.waitForSelector('button:has-text("Exportar PDF")', { timeout: 30_000 })
  await page.waitForSelector('.bpmn-container .djs-group', { timeout: 30_000 })
}

// ─── Test principal: flujo ROI completo ───────────────────────────────────────

test('Export ROI — flujo completo con medium-with-gateways', async ({ page }) => {
  await importBpmn(page, 'medium-with-gateways.bpmn')

  // Configurar task_recv como automatizable ($50, 5 min)
  await makeAutomatable(page, 'task_recv', 50, 5)

  // Configurar volumetría e inversión
  await configureGlobal(page, 12_000, 50_000)

  // Simular
  await simulateAndGoToReport(page)

  // Navegar al tab ROI
  const roiTab = page.getByRole('tab', { name: /Comparación/i })
  await expect(roiTab).not.toBeDisabled({ timeout: 5_000 })
  await roiTab.click()
  await page.waitForTimeout(500)

  // ── PDF ROI ────────────────────────────────────────────────────────────────
  const pdfPath = resolve(OUTPUT_DIR, 'roi-test.pdf')
  const pdfDownload = page.waitForEvent('download', { timeout: 90_000 })
  await page.getByRole('button', { name: 'Exportar PDF' }).click()
  const dlPdf = await pdfDownload
  await dlPdf.saveAs(pdfPath)

  await page.waitForSelector('button:has-text("Exportar PDF")', { timeout: 30_000 })

  const pdfBuffer = readFileSync(pdfPath)
  const pdfBytes = pdfBuffer.length
  console.log(`\n📊 ROI PDF: ${pdfBytes} bytes (${(pdfBytes / 1024).toFixed(1)} KB)`)

  // Tamaño razonable: < 400 KB
  expect(pdfBytes).toBeGreaterThan(30_000)
  expect(pdfBytes).toBeLessThan(400_000)

  // Nombre con sufijo _roi
  const downloadName = dlPdf.suggestedFilename()
  console.log(`   Nombre archivo: ${downloadName}`)
  expect(downloadName).toMatch(/_roi\.pdf$/)

  // Contenido mínimo
  const { numpages, text } = await parsePdf(pdfBuffer)
  console.log(`   Páginas: ${numpages}`)
  console.log(`   Primeros 300 chars: ${text.slice(0, 300).replace(/\n/g, ' ')}`)

  // Al menos 3 páginas (hay 4 en el ROI PDF)
  expect(numpages).toBeGreaterThanOrEqual(3)

  // Keywords que deben estar en el texto del PDF
  expect(text).toMatch(/ROI|retorno|automatizaci/i)
  expect(text).toMatch(/Payback|payback|recupera/i)
  expect(text).toMatch(/ahorro|Ahorro/i)
  expect(text).toContain('USD')

  // ── CSV ROI ────────────────────────────────────────────────────────────────
  const csvPath = resolve(OUTPUT_DIR, 'roi-test.csv')
  const csvDownload = page.waitForEvent('download', { timeout: 30_000 })
  await page.getByRole('button', { name: 'Exportar CSV' }).click()
  const dlCsv = await csvDownload
  await dlCsv.saveAs(csvPath)

  const csvBuffer = readFileSync(csvPath)
  const csvBytes = csvBuffer.length
  console.log(`   CSV: ${csvBytes} bytes`)
  console.log(`   Nombre archivo CSV: ${dlCsv.suggestedFilename()}`)

  // Nombre con sufijo _roi
  expect(dlCsv.suggestedFilename()).toMatch(/_roi\.csv$/)

  const csvText = csvBuffer.toString('utf-8')

  // BOM UTF-8
  expect(csvText).toMatch(/^/)

  // Metadata ROI presente
  expect(csvText).toContain('# Ahorro por ejecución')
  expect(csvText).toContain('# Payback (meses)')
  expect(csvText).toContain('# ROI anualizado')
  expect(csvText).toContain('# Frecuencia anual: 12000')

  // 16 columnas en el header de datos
  const csvNoBom = csvText.startsWith('') ? csvText.slice(1) : csvText
  const headerLine = csvNoBom.split('\r\n').find((l) => !l.startsWith('#') && l.trim())!
  const colCount = headerLine.split('","').length
  console.log(`   Columnas CSV: ${colCount}`)
  expect(colCount).toBe(16)

  // Columna Automatizable presente
  expect(csvText).toContain('Automatizable')
})

// ─── Test: sin automatizables → tab ROI disabled, export de "Actual" OK ──────

test('Tabs ROI/Automatizado disabled cuando no hay actividades automatizables', async ({ page }) => {
  await importBpmn(page, 'simple-linear.bpmn')
  await simulateAndGoToReport(page)

  // Los tabs deben estar disabled
  const autoTab = page.getByRole('tab', { name: /Automatizado/i })
  const roiTab = page.getByRole('tab', { name: /Comparación/i })

  await expect(autoTab).toBeDisabled()
  await expect(roiTab).toBeDisabled()

  // El export PDF/CSV del tab "Actual" sigue funcionando
  const pdfPath = resolve(OUTPUT_DIR, 'no-automatable.pdf')
  const pdfDownload = page.waitForEvent('download', { timeout: 90_000 })
  await page.getByRole('button', { name: 'Exportar PDF' }).click()
  const dlPdf = await pdfDownload
  await dlPdf.saveAs(pdfPath)

  const downloadName = dlPdf.suggestedFilename()
  console.log(`\n📄 Sin automatizables — nombre PDF: ${downloadName}`)
  expect(downloadName).toMatch(/_actual\.pdf$/)

  const pdfBuffer = readFileSync(pdfPath)
  expect(pdfBuffer.length).toBeGreaterThan(30_000)

  const csvDownload = page.waitForEvent('download', { timeout: 30_000 })
  await page.getByRole('button', { name: 'Exportar CSV' }).click()
  const dlCsv = await csvDownload

  console.log(`   Nombre CSV: ${dlCsv.suggestedFilename()}`)
  expect(dlCsv.suggestedFilename()).toMatch(/_actual\.csv$/)
})

// ─── Test: tab Automatizado → PDF y CSV con sufijo correcto ───────────────────

test('Export Automatizado — sufijo _automatizado en nombres de archivo', async ({ page }) => {
  await importBpmn(page, 'medium-with-gateways.bpmn')
  await makeAutomatable(page, 'task_recv', 30, 5)
  await simulateAndGoToReport(page)

  // Ir al tab Automatizado
  const autoTab = page.getByRole('tab', { name: /^Automatizado$/i })
  await expect(autoTab).not.toBeDisabled()
  await autoTab.click()
  await page.waitForTimeout(500)

  // PDF con sufijo _automatizado
  const pdfPath = resolve(OUTPUT_DIR, 'automatizado.pdf')
  const pdfDownload = page.waitForEvent('download', { timeout: 90_000 })
  await page.getByRole('button', { name: 'Exportar PDF' }).click()
  const dlPdf = await pdfDownload
  await dlPdf.saveAs(pdfPath)

  const pdfName = dlPdf.suggestedFilename()
  console.log(`\n⚙️ Automatizado PDF: ${pdfName}`)
  expect(pdfName).toMatch(/_automatizado\.pdf$/)

  const pdfBuffer = readFileSync(pdfPath)
  expect(pdfBuffer.length).toBeGreaterThan(30_000)

  // CSV con sufijo _automatizado
  const csvDownload = page.waitForEvent('download', { timeout: 30_000 })
  await page.getByRole('button', { name: 'Exportar CSV' }).click()
  const dlCsv = await csvDownload
  expect(dlCsv.suggestedFilename()).toMatch(/_automatizado\.csv$/)
})
