
/**
 * PDF/Export Generation Utility: MoneyManagerX Exports
 * 
 * Expected Usage:
 * Used for exporting DOM elements (charts, tables) to CSV, Excel, Image, and PDF.
 * 
 * Troubleshooting Blank PDFs:
 * - Ensure the 'selector' matches an element currently visible in the DOM.
 * - If dynamic charts are rendering, `waitForElement` might timeout if rendering takes too long. Increase `maxRetries`.
 * - Blank PDFs often result from `html2canvas` failing to capture cross-origin images or CSS transforms. Ensure `useCORS: true`.
 * 
 * Supported Content:
 * - HTML Tables (for CSV/Excel)
 * - DOM Elements including Recharts/Canvas (for PNG/PDF via html2canvas)
 * 
 * Limitations:
 * - Complex CSS (like filters, mix-blend-mode) might not render correctly in html2canvas.
 * - Large DOM trees may cause performance issues or browser crashes during capture.
 */

import { jsPDF } from 'jspdf';
import html2canvas from 'html2canvas';
import * as XLSX from 'xlsx';
import Papa from 'papaparse';

// Helper to wait for an element to render (handles race conditions with dynamic charts/tables)
const waitForElement = async (selector, maxRetries = 40, interval = 250) => {
  for (let i = 0; i < maxRetries; i++) {
    const el = document.querySelector(selector);
    if (el) {
      // Check if it has content (not just an empty container)
      if (el.innerHTML.trim().length > 0) return el;
    }
    await new Promise(resolve => setTimeout(resolve, interval));
  }
  throw new Error(`Element "${selector}" not found or empty after waiting. Please ensure the content is visible.`);
};

// Helper to extract table data from a DOM container
const extractTableData = (containerElement) => {
  const table = containerElement.querySelector('table');
  if (!table) {
    throw new Error('No table found inside the report container to extract data from.');
  }

  const data = [];
  const rows = table.querySelectorAll('tr');
  
  if (rows.length === 0) {
    throw new Error('The report table contains no data rows.');
  }

  rows.forEach(row => {
    const rowData = [];
    const cells = row.querySelectorAll('th, td');
    cells.forEach(cell => {
      let text = cell.innerText || cell.textContent || '';
      text = text.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim();
      rowData.push(text);
    });
    if (rowData.some(cell => cell.length > 0)) {
      data.push(rowData);
    }
  });

  if (data.length <= 1) {
    throw new Error('Extracted data appears empty or only contains headers. Cannot export empty table.');
  }

  return data;
};

export const exportToCSV = async (dataOrSelector, filename) => {
  try {
    console.log(`Starting CSV export for ${filename}...`);
    let dataToExport = dataOrSelector;

    if (typeof dataOrSelector === 'string') {
      const container = await waitForElement(dataOrSelector);
      dataToExport = extractTableData(container);
    } else if (!Array.isArray(dataOrSelector) || dataOrSelector.length === 0) {
      throw new Error('No valid data provided for CSV export.');
    }

    const csv = Papa.unparse(dataToExport);
    const { saveCsv } = await import('@/lib/saveFile');
    await saveCsv(csv, `${filename}.csv`);

    
    console.log('CSV export completed successfully.');
    return true;
  } catch (error) {
    console.error('Error exporting to CSV:', error);
    throw error;
  }
};

export const exportToExcel = async (dataOrSelector, filename, sheetName = 'Sheet 1') => {
  try {
    console.log(`Starting Excel export for ${filename}...`);
    let dataToExport = dataOrSelector;

    if (typeof dataOrSelector === 'string') {
      const container = await waitForElement(dataOrSelector);
      dataToExport = extractTableData(container);
    } else if (!Array.isArray(dataOrSelector) || dataOrSelector.length === 0) {
      throw new Error('No valid data provided for Excel export.');
    }

    const worksheet = Array.isArray(dataToExport[0])
      ? XLSX.utils.aoa_to_sheet(dataToExport)
      : XLSX.utils.json_to_sheet(dataToExport);

    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
    const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
    const { saveFile } = await import('@/lib/saveFile');
    await saveFile(wbout, {
      suggestedName: `${filename}.xlsx`,
      mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      description: 'Excel Workbook',
    });
    
    console.log('Excel export completed successfully.');
    return true;
  } catch (error) {
    console.error('Error exporting to Excel:', error);
    throw error;
  }
};

export const exportElementToImage = async (selector, filename) => {
  try {
    console.log(`Starting Image export for selector: ${selector}...`);
    const element = await waitForElement(selector);

    const canvas = await html2canvas(element, {
      scale: 2,
      useCORS: true,
      logging: false,
      backgroundColor: '#ffffff'
    });

    const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png', 1.0));
    const { saveFile } = await import('@/lib/saveFile');
    await saveFile(blob, { suggestedName: `${filename}.png`, mimeType: 'image/png', description: 'PNG Image' });
    
    console.log('Image export completed successfully.');
    return true;
  } catch (error) {
    console.error('Error exporting image:', error);
    throw error;
  }
};

export const exportElementToPDF = async (selector, filename, options = {}) => {
  const { title = '', subtitle = '', orientation = 'p' } = options;
  try {
    console.log(`Starting PDF export for selector: ${selector}...`);
    const element = await waitForElement(selector);

    if (!element || element.offsetHeight === 0 || element.offsetWidth === 0) {
      throw new Error("Target element has 0 dimensions, cannot generate PDF.");
    }

    const canvas = await html2canvas(element, {
      scale: 2,
      useCORS: true,
      logging: false,
      backgroundColor: '#ffffff'
    });

    const imgData = canvas.toDataURL('image/png');
    const pdf = new jsPDF({
      orientation: orientation,
      unit: 'mm',
      format: 'a4',
      compress: true
    });

    const pdfWidth = pdf.internal.pageSize.getWidth();
    const pdfHeight = pdf.internal.pageSize.getHeight();
    const margin = 15;
    
    let currentY = margin;

    if (title) {
      pdf.setFontSize(18);
      pdf.setTextColor(15, 23, 42);
      pdf.text(title, margin, currentY);
      currentY += 8;
    }
    
    if (subtitle) {
      pdf.setFontSize(11);
      pdf.setTextColor(100, 116, 139);
      pdf.text(subtitle, margin, currentY);
      currentY += 10;
    }

    const maxImgWidth = pdfWidth - (margin * 2);
    const maxImgHeight = pdfHeight - currentY - margin;
    
    let imgWidth = maxImgWidth;
    let imgHeight = (canvas.height * imgWidth) / canvas.width;

    if (imgHeight > maxImgHeight) {
      imgHeight = maxImgHeight;
      imgWidth = (canvas.width * imgHeight) / canvas.height;
    }

    pdf.addImage(imgData, 'PNG', margin, currentY, imgWidth, imgHeight, undefined, 'FAST');
    
    pdf.setFontSize(8);
    pdf.setTextColor(148, 163, 184);
    const safeDate = new Date().toISOString().split('T')[0];
    pdf.text(`Generated on ${new Date().toLocaleString()}`, margin, pdfHeight - 10);

    pdf.save(`${filename}_${safeDate}.pdf`);
    console.log('PDF export completed successfully.');
    return true;
  } catch (error) {
    console.error('Error exporting to PDF:', error);
    throw error;
  }
};
