/**
 * Export Utilities
 *
 * Utilities for exporting data to CSV and JSON formats.
 * Triggers file download in the browser.
 *
 * @example
 * ```tsx
 * import { exportToCSV, exportToJSON, exportData } from '@/prism/headless/utils';
 *
 * // Export to CSV
 * exportToCSV({
 *   data: users,
 *   filename: 'users',
 *   columns: ['id', 'name', 'email'],
 *   headers: { id: 'ID', name: 'Name', email: 'Email Address' },
 * });
 *
 * // Export to JSON
 * exportToJSON({
 *   data: users,
 *   filename: 'users-export',
 * });
 *
 * // Generic export with format selection
 * exportData({
 *   data: users,
 *   filename: 'users',
 *   format: 'csv',
 * });
 * ```
 *
 * ⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
 */

import type { ExportFormat, ExportOptions } from '../types';

// ============================================================================
// CSV Export
// ============================================================================

/**
 * Escape a value for CSV format.
 * Wraps in quotes if contains comma, newline, or quote.
 */
function escapeCSVValue(value: unknown): string {
  if (value === null || value === undefined) {
    return '';
  }

  const str = String(value);

  // Check if we need to quote the value
  if (str.includes(',') || str.includes('\n') || str.includes('"')) {
    // Escape double quotes by doubling them
    return `"${str.replace(/"/g, '""')}"`;
  }

  return str;
}

/**
 * Convert an array of objects to CSV string.
 */
function toCSV<T extends Record<string, unknown>>(
  data: T[],
  columns?: (keyof T)[],
  headers?: Partial<Record<keyof T, string>>
): string {
  if (data.length === 0) {
    return '';
  }

  // Determine columns to export
  const cols = columns ?? (Object.keys(data[0]) as (keyof T)[]);

  // Build header row
  const headerRow = cols
    .map((col) => escapeCSVValue(headers?.[col] ?? String(col)))
    .join(',');

  // Build data rows
  const dataRows = data.map((item) =>
    cols.map((col) => escapeCSVValue(item[col])).join(',')
  );

  return [headerRow, ...dataRows].join('\n');
}

/**
 * Export data to CSV format and trigger download.
 *
 * @param options - Export options
 */
export function exportToCSV<T extends Record<string, unknown>>(
  options: Omit<ExportOptions<T>, 'format'>
): void {
  const csv = toCSV(options.data, options.columns, options.headers);
  downloadFile(csv, `${options.filename}.csv`, 'text/csv;charset=utf-8;');
}

// ============================================================================
// JSON Export
// ============================================================================

/**
 * Convert an array of objects to JSON string.
 */
function toJSON<T extends Record<string, unknown>>(
  data: T[],
  columns?: (keyof T)[]
): string {
  if (!columns) {
    return JSON.stringify(data, null, 2);
  }

  // Filter to only include specified columns
  const filtered = data.map((item) => {
    const result: Partial<T> = {};
    for (const col of columns) {
      result[col] = item[col];
    }
    return result;
  });

  return JSON.stringify(filtered, null, 2);
}

/**
 * Export data to JSON format and trigger download.
 *
 * @param options - Export options
 */
export function exportToJSON<T extends Record<string, unknown>>(
  options: Omit<ExportOptions<T>, 'format'>
): void {
  const json = toJSON(options.data, options.columns);
  downloadFile(json, `${options.filename}.json`, 'application/json;charset=utf-8;');
}

// ============================================================================
// Generic Export
// ============================================================================

/**
 * Export data to the specified format and trigger download.
 *
 * @param options - Export options with format
 */
export function exportData<T extends Record<string, unknown>>(
  options: ExportOptions<T>
): void {
  switch (options.format) {
    case 'csv':
      exportToCSV(options);
      break;
    case 'json':
      exportToJSON(options);
      break;
    default:
      throw new Error(`Unsupported export format: ${options.format}`);
  }
}

// ============================================================================
// Download Helper
// ============================================================================

/**
 * Trigger a file download in the browser.
 *
 * @param content - File content
 * @param filename - Filename with extension
 * @param mimeType - MIME type
 */
function downloadFile(
  content: string,
  filename: string,
  mimeType: string
): void {
  // Create blob
  const blob = new Blob([content], { type: mimeType });

  // Create download link
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;

  // Trigger download
  document.body.appendChild(link);
  link.click();

  // Cleanup
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
}

export default exportData;
