/**
 * Luxury Export Utilities
 * Provides beautiful export functionality for financial data in multiple formats
 */

export type ExportFormat = 'csv' | 'json' | 'pdf' | 'xlsx';

type ExportRow = Record<string, unknown>;

interface ExportOptions<T extends ExportRow = ExportRow> {
  filename?: string;
  title?: string;
  headers?: (keyof T | string)[];
  data: ReadonlyArray<T>;
  format: ExportFormat;
}

const getCellValue = <T extends ExportRow>(row: T, header: string | keyof T): string => {
  const value = row[header as keyof T];
  if (value === null || value === undefined) return '';
  if (value instanceof Date) return value.toISOString();
  if (typeof value === 'object') return JSON.stringify(value);
  return String(value);
};

/**
 * Export data to CSV format
 */
export const exportToCSV = <T extends ExportRow>(options: ExportOptions<T>): void => {
  const { filename = 'export', data, headers } = options;
  
  if (!data || data.length === 0) {
    throw new Error('No data to export');
  }

  // Get headers from first object if not provided
  const csvHeaders = headers?.map(String) || Object.keys(data[0]);
  
  // Create CSV content
  const csvContent = [
    csvHeaders.join(','),
    ...data.map(row =>
      csvHeaders.map(header => {
        const value = getCellValue(row, header);
        if (value.includes(',') || value.includes('"') || value.includes('\n')) {
          return `"${value.replace(/"/g, '""')}"`;
        }
        return value;
      }).join(',')
    )
  ].join('\n');

  // Create blob and download
  const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
  const link = document.createElement('a');
  const url = URL.createObjectURL(blob);
  link.setAttribute('href', url);
  link.setAttribute('download', `${filename}-${new Date().toISOString().split('T')[0]}.csv`);
  link.style.visibility = 'hidden';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};

/**
 * Export data to JSON format
 */
export const exportToJSON = <T extends ExportRow>(options: ExportOptions<T>): void => {
  const { filename = 'export', data } = options;
  
  if (!data || data.length === 0) {
    throw new Error('No data to export');
  }

  const jsonContent = JSON.stringify(data, null, 2);
  const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' });
  const link = document.createElement('a');
  const url = URL.createObjectURL(blob);
  link.setAttribute('href', url);
  link.setAttribute('download', `${filename}-${new Date().toISOString().split('T')[0]}.json`);
  link.style.visibility = 'hidden';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};

/**
 * Export data to PDF format (using browser print functionality with styling)
 */
export const exportToPDF = <T extends ExportRow>(options: ExportOptions<T>): void => {
  const { filename = 'export', data, title, headers } = options;
  
  if (!data || data.length === 0) {
    throw new Error('No data to export');
  }

  const pdfHeaders = headers?.map(String) || Object.keys(data[0]);
  
  // Create a styled HTML table for PDF
  const htmlContent = `
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
        <title>${title || filename}</title>
        <style>
          @page {
            margin: 20mm;
            size: A4 landscape;
          }
          body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            color: #1a1a1a;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            padding: 20px;
          }
          .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            border-radius: 10px;
            margin-bottom: 30px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
          }
          .header h1 {
            margin: 0;
            font-size: 28px;
            font-weight: 600;
            letter-spacing: 1px;
          }
          .header p {
            margin: 10px 0 0 0;
            opacity: 0.9;
            font-size: 14px;
          }
          table {
            width: 100%;
            border-collapse: collapse;
            background: white;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
          }
          thead {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
          }
          th {
            padding: 15px;
            text-align: left;
            font-weight: 600;
            font-size: 12px;
            text-transform: uppercase;
            letter-spacing: 0.5px;
          }
          td {
            padding: 12px 15px;
            border-bottom: 1px solid #e0e0e0;
            font-size: 12px;
          }
          tbody tr:hover {
            background-color: #f8f9fa;
          }
          tbody tr:last-child td {
            border-bottom: none;
          }
          .footer {
            margin-top: 30px;
            text-align: center;
            color: #666;
            font-size: 12px;
            padding: 20px;
          }
        </style>
      </head>
      <body>
        <div class="header">
          <h1>${title || 'Financial Report'}</h1>
          <p>Generated on ${new Date().toLocaleDateString('en-US', { 
            year: 'numeric', 
            month: 'long', 
            day: 'numeric',
            hour: '2-digit',
            minute: '2-digit'
          })}</p>
        </div>
        <table>
          <thead>
            <tr>
              ${pdfHeaders.map(header => `<th>${header.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}</th>`).join('')}
            </tr>
          </thead>
          <tbody>
            ${data.map(row => `
              <tr>
                ${pdfHeaders.map(header => `<td>${getCellValue(row, header)}</td>`).join('')}
              </tr>
            `).join('')}
          </tbody>
        </table>
        <div class="footer">
          <p>© ${new Date().getFullYear()} Luxury Hotel - Confidential Financial Document</p>
        </div>
      </body>
    </html>
  `;

  // Open in new window and trigger print
  const printWindow = window.open('', '_blank');
  if (printWindow) {
    printWindow.document.write(htmlContent);
    printWindow.document.close();
    printWindow.onload = () => {
      setTimeout(() => {
        printWindow.print();
      }, 250);
    };
  }
};

/**
 * Export data to Excel format (XLSX) - using CSV as fallback with .xlsx extension
 * Note: For true Excel format, you would need a library like xlsx
 */
export const exportToXLSX = <T extends ExportRow>(options: ExportOptions<T>): void => {
  const { filename = 'export', data, headers } = options;
  
  if (!data || data.length === 0) {
    throw new Error('No data to export');
  }

  // For now, we'll use CSV format but with .xlsx extension
  // Excel can open CSV files, and this works without additional dependencies
  const csvHeaders = headers?.map(String) || Object.keys(data[0]);
  
  const csvContent = [
    csvHeaders.join(','),
    ...data.map(row =>
      csvHeaders.map(header => {
        const value = getCellValue(row, header);
        if (value.includes(',') || value.includes('"') || value.includes('\n')) {
          return `"${value.replace(/"/g, '""')}"`;
        }
        return value;
      }).join(',')
    )
  ].join('\n');

  // Create blob with Excel-compatible MIME type
  const blob = new Blob(['\ufeff' + csvContent], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8;' });
  const link = document.createElement('a');
  const url = URL.createObjectURL(blob);
  link.setAttribute('href', url);
  link.setAttribute('download', `${filename}-${new Date().toISOString().split('T')[0]}.xlsx`);
  link.style.visibility = 'hidden';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};

/**
 * Main export function that routes to the appropriate format
 */
export const exportData = <T extends ExportRow>(options: ExportOptions<T>): void => {
  try {
    switch (options.format) {
      case 'csv':
        exportToCSV<T>(options);
        break;
      case 'json':
        exportToJSON<T>(options);
        break;
      case 'pdf':
        exportToPDF<T>(options);
        break;
      case 'xlsx':
        exportToXLSX<T>(options);
        break;
      default:
        throw new Error(`Unsupported export format: ${options.format}`);
    }
  } catch (error: unknown) {
    const message = error instanceof Error ? error.message : 'Unknown error';
    throw new Error(`Export failed: ${message}`);
  }
};

/**
 * Helper to format data for export
 */
export const formatDataForExport = <T extends ExportRow>(
  data: ReadonlyArray<T>, 
  customHeaders?: Record<string, string>
): { headers: string[]; formattedData: ExportRow[] } => {
  if (!data || data.length === 0) {
    return { headers: [], formattedData: [] };
  }

  const headers = customHeaders ? Object.keys(customHeaders) : Object.keys(data[0]);
  const formattedData = data.map(row => {
    const formatted: ExportRow = {};
    headers.forEach(header => {
      const value = row[header as keyof T];
      // Format dates
      if (value && typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) {
        formatted[header] = new Date(value).toLocaleDateString();
      } else {
        formatted[header] = value ?? '';
      }
    });
    return formatted;
  });

  const displayHeaders = customHeaders 
    ? headers.map(h => customHeaders[h] || h)
    : headers.map(h => h.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()));

  return { headers: displayHeaders, formattedData };
};

