/**
 * Exportación de reportes a Excel (.xlsx) con formato de marca SKEEN.
 * Usa exceljs cargado on-demand (dynamic import) para no inflar el bundle inicial.
 */

export interface ExportColumn {
  header: string;
  key: string;
  width?: number;
  format?: 'currency' | 'number' | 'date' | 'text' | 'percent';
}

export interface ExportOptions {
  filename: string;
  sheetName: string;
  title: string;
  subtitle?: string;
  columns: ExportColumn[];
  rows: Record<string, unknown>[];
  totals?: Record<string, unknown>;
}

const NUM_FORMATS: Record<string, string> = {
  currency: '"$"#,##0.00',
  number: '#,##0',
  date: 'DD/MM/YYYY',
  percent: '0%',
};

const toCellValue = (value: unknown, format?: string) => {
  if (value === null || value === undefined || value === '') return '';
  if (format === 'currency' || format === 'number') {
    const n = typeof value === 'number' ? value : parseFloat(String(value));
    return Number.isNaN(n) ? String(value) : n;
  }
  if (format === 'percent') {
    const n = typeof value === 'number' ? value : parseFloat(String(value));
    return Number.isNaN(n) ? String(value) : (n > 1 ? n / 100 : n);
  }
  if (format === 'date') {
    const s = String(value);
    const d = new Date(s.length === 10 ? `${s}T12:00:00` : s.replace(' ', 'T'));
    return Number.isNaN(d.getTime()) ? s : d;
  }
  return String(value);
};

export const buildWorkbook = async (opts: ExportOptions) => {
  const mod: unknown = await import('exceljs');
  const ExcelJS = ((mod as { default?: unknown }).default ?? mod) as typeof import('exceljs');
  const wb = new ExcelJS.Workbook();
  const ws = wb.addWorksheet(opts.sheetName.slice(0, 31));
  const lastCol = Math.max(opts.columns.length, 1);
  const lastColLetter = ws.getColumn(lastCol).letter;

  // Título (marca)
  ws.mergeCells(`A1:${lastColLetter}1`);
  const titleCell = ws.getCell('A1');
  titleCell.value = opts.title;
  titleCell.font = { bold: true, size: 14, color: { argb: 'FF1A1A1A' } };
  titleCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFEDA588' } };
  titleCell.alignment = { vertical: 'middle' };
  ws.getRow(1).height = 24;

  let rowIdx = 2;
  if (opts.subtitle) {
    ws.mergeCells(`A2:${lastColLetter}2`);
    const sub = ws.getCell('A2');
    sub.value = opts.subtitle;
    sub.font = { size: 10, color: { argb: 'FF6B6B6B' } };
    rowIdx = 3;
  }
  rowIdx += 1; // línea en blanco

  // Encabezados
  const headerRow = ws.getRow(rowIdx);
  opts.columns.forEach((col, i) => {
    const cell = headerRow.getCell(i + 1);
    cell.value = col.header;
    cell.font = { bold: true, color: { argb: 'FFFFFFFF' } };
    cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF1A1A1A' } };
    cell.border = { bottom: { style: 'thin', color: { argb: 'FFD2D6DE' } } };
    cell.alignment = { vertical: 'middle' };
  });
  headerRow.height = 18;
  rowIdx += 1;

  // Datos
  for (const row of opts.rows) {
    const r = ws.getRow(rowIdx);
    opts.columns.forEach((col, i) => {
      const cell = r.getCell(i + 1);
      cell.value = toCellValue(row[col.key], col.format) as never;
      if (col.format && NUM_FORMATS[col.format]) {
        cell.numFmt = NUM_FORMATS[col.format];
      }
    });
    rowIdx += 1;
  }

  // Totales
  if (opts.totals) {
    const r = ws.getRow(rowIdx);
    opts.columns.forEach((col, i) => {
      const cell = r.getCell(i + 1);
      const v = opts.totals![col.key];
      cell.value = (i === 0 && (v === undefined || v === '')) ? 'Totales' : toCellValue(v, col.format) as never;
      cell.font = { bold: true };
      cell.border = { top: { style: 'thin', color: { argb: 'FF1A1A1A' } } };
      if (col.format && NUM_FORMATS[col.format]) {
        cell.numFmt = NUM_FORMATS[col.format];
      }
    });
  }

  // Anchos: explícito o estimado por contenido (tope 50)
  opts.columns.forEach((col, i) => {
    if (col.width) {
      ws.getColumn(i + 1).width = col.width;
      return;
    }
    let max = col.header.length;
    for (const row of opts.rows.slice(0, 500)) {
      const v = row[col.key];
      if (v !== null && v !== undefined) max = Math.max(max, String(v).length);
    }
    if (opts.totals && opts.totals[col.key] !== undefined) {
      max = Math.max(max, String(opts.totals[col.key]).length);
    }
    ws.getColumn(i + 1).width = Math.min(max + 3, 50);
  });

  return wb;
};

export const exportToExcel = async (opts: ExportOptions): Promise<void> => {
  const wb = await buildWorkbook(opts);
  const buffer = await wb.xlsx.writeBuffer();
  const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = opts.filename.endsWith('.xlsx') ? opts.filename : `${opts.filename}.xlsx`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
};
