/**
 * Client-side export utilities
 */

import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
import { Booking } from '@/types/booking';

export interface ExportField {
  key: string;
  label: string;
  formatter?: (value: any) => string;
}

const DEFAULT_BOOKING_FIELDS: ExportField[] = [
  { key: 'bookingNumber', label: 'Booking Number' },
  { key: 'status', label: 'Status' },
  { key: 'rateQuote.carrierName', label: 'Carrier' },
  { key: 'rateQuote.origin', label: 'Origin' },
  { key: 'rateQuote.destination', label: 'Destination' },
  { key: 'shipper.name', label: 'Shipper' },
  { key: 'consignee.name', label: 'Consignee' },
  {
    key: 'rateQuote.etd',
    label: 'ETD',
    formatter: value => (value ? new Date(value).toLocaleDateString() : ''),
  },
  {
    key: 'rateQuote.eta',
    label: 'ETA',
    formatter: value => (value ? new Date(value).toLocaleDateString() : ''),
  },
  {
    key: 'containers',
    label: 'Containers',
    formatter: value => (Array.isArray(value) ? value.length.toString() : '0'),
  },
  {
    key: 'createdAt',
    label: 'Created',
    formatter: value => new Date(value).toLocaleDateString(),
  },
];

/**
 * Get nested object value by key path
 */
function getNestedValue(obj: any, path: string): any {
  return path.split('.').reduce((current, key) => current?.[key], obj);
}

/**
 * Export bookings to CSV
 */
export function exportToCSV(
  data: Booking[],
  fields: ExportField[] = DEFAULT_BOOKING_FIELDS,
  filename: string = 'bookings-export.csv'
): void {
  // Create CSV header
  const header = fields.map(f => f.label).join(',');

  // Create CSV rows
  const rows = data.map(booking => {
    return fields
      .map(field => {
        const value = getNestedValue(booking, field.key);
        const formatted = field.formatter ? field.formatter(value) : value;
        // Escape quotes and wrap in quotes if contains comma
        const escaped = String(formatted || '').replace(/"/g, '""');
        return `"${escaped}"`;
      })
      .join(',');
  });

  // Combine header and rows
  const csv = [header, ...rows].join('\n');

  // Create blob and download
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
  saveAs(blob, filename);
}

/**
 * Export bookings to Excel
 */
export function exportToExcel(
  data: Booking[],
  fields: ExportField[] = DEFAULT_BOOKING_FIELDS,
  filename: string = 'bookings-export.xlsx'
): void {
  // Create worksheet data
  const wsData = [
    // Header row
    fields.map(f => f.label),
    // Data rows
    ...data.map(booking =>
      fields.map(field => {
        const value = getNestedValue(booking, field.key);
        return field.formatter ? field.formatter(value) : value || '';
      })
    ),
  ];

  // Create worksheet
  const ws = XLSX.utils.aoa_to_sheet(wsData);

  // Set column widths
  ws['!cols'] = fields.map(() => ({ wch: 20 }));

  // Create workbook
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, 'Bookings');

  // Generate Excel file
  const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
  const blob = new Blob([excelBuffer], {
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  });
  saveAs(blob, filename);
}

/**
 * Export bookings to JSON
 */
export function exportToJSON(data: Booking[], filename: string = 'bookings-export.json'): void {
  const json = JSON.stringify(data, null, 2);
  const blob = new Blob([json], { type: 'application/json;charset=utf-8;' });
  saveAs(blob, filename);
}

/**
 * Export bookings based on format
 */
export function exportBookings(
  data: Booking[],
  format: 'csv' | 'excel' | 'json',
  fields?: ExportField[],
  filename?: string
): void {
  switch (format) {
    case 'csv':
      exportToCSV(data, fields, filename);
      break;
    case 'excel':
      exportToExcel(data, fields, filename);
      break;
    case 'json':
      exportToJSON(data, filename);
      break;
    default:
      throw new Error(`Unsupported export format: ${format}`);
  }
}
