import React, { useState, useRef } from 'react';
import { Download, FileText, FileSpreadsheet, Printer, ChevronDown, File } from 'lucide-react';
import { cn } from '@/lib/utils';
import { motion, AnimatePresence } from 'framer-motion';
import { ColumnConfig } from '@/components/common/ColumnSelector';
import { Button } from '../ui/buttonTsx';

// ============================================
// TYPES
// ============================================

export interface ExportColumnConfig {
  key: string;
  label: string;
  format?: (value: any, row: any) => string;
}

interface ExportDropdownProps {
  data: any[];
  columns: ColumnConfig[]; // Colonnes du ColumnSelector
  columnFormatters?: Record<string, (value: any, row: any) => string>; // Formateurs par clé
  filename?: string;
  className?: string;
  onExportStart?: () => void;
  onExportEnd?: () => void;
}

type ExportFormat = 'csv' | 'txt' | 'excel' | 'print';

// ============================================
// UTILITAIRES D'EXPORT
// ============================================

const formatValue = (
  value: any,
  key: string,
  row: any,
  formatters?: Record<string, (value: any, row: any) => string>
): string => {
  // Utiliser le formateur personnalisé si disponible
  if (formatters && formatters[key]) {
    return formatters[key](value, row);
  }
  if (value === null || value === undefined) return '';
  if (typeof value === 'number') return value.toLocaleString('fr-FR');
  if (typeof value === 'boolean') return value ? 'Oui' : 'Non';
  if (value instanceof Date) return value.toLocaleDateString('fr-FR');
  return String(value);
};

const sanitizeForCSV = (value: string): string => {
  if (value.includes(';') || value.includes('"') || value.includes('\n')) {
    return `"${value.replace(/"/g, '""')}"`;
  }
  return value;
};

const generateCSV = (
  data: any[],
  columns: ColumnConfig[],
  formatters?: Record<string, (value: any, row: any) => string>
): string => {
  const visibleColumns = columns.filter(col => col.visible);
  const header = visibleColumns.map(col => sanitizeForCSV(col.label)).join(';');
  const rows = data.map(row =>
    visibleColumns
      .map(col => sanitizeForCSV(formatValue(row[col.key], col.key, row, formatters)))
      .join(';')
  );
  return [header, ...rows].join('\n');
};

const generateTXT = (
  data: any[],
  columns: ColumnConfig[],
  formatters?: Record<string, (value: any, row: any) => string>
): string => {
  const visibleColumns = columns.filter(col => col.visible);
  const header = visibleColumns.map(col => col.label).join('\t');
  const rows = data.map(row =>
    visibleColumns
      .map(col => formatValue(row[col.key], col.key, row, formatters))
      .join('\t')
  );
  return [header, ...rows].join('\n');
};

const generateExcelXML = (
  data: any[],
  columns: ColumnConfig[],
  filename: string,
  formatters?: Record<string, (value: any, row: any) => string>
): string => {
  const visibleColumns = columns.filter(col => col.visible);
  
  const header = visibleColumns
    .map(col => `<Cell><Data ss:Type="String">${col.label}</Data></Cell>`)
    .join('');
  
  const rows = data
    .map(row => {
      const cells = visibleColumns
        .map(col => {
          const value = formatValue(row[col.key], col.key, row, formatters);
          const rawValue = row[col.key];
          const type = typeof rawValue === 'number' && !formatters?.[col.key] ? 'Number' : 'String';
          const displayValue = type === 'Number' ? rawValue : value;
          return `<Cell><Data ss:Type="${type}">${displayValue}</Data></Cell>`;
        })
        .join('');
      return `<Row>${cells}</Row>`;
    })
    .join('');

  return `<?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
  <Styles>
    <Style ss:ID="Header">
      <Font ss:Bold="1" ss:Color="#FFFFFF"/>
      <Interior ss:Color="#007E45" ss:Pattern="Solid"/>
      <Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
    </Style>
    <Style ss:ID="Currency">
      <NumberFormat ss:Format="#,##0.00\ &quot;€&quot;"/>
    </Style>
  </Styles>
  <Worksheet ss:Name="${filename}">
    <Table>
      <Row ss:StyleID="Header">${header}</Row>
      ${rows}
    </Table>
  </Worksheet>
</Workbook>`;
};

const downloadFile = (content: string, filename: string, mimeType: string) => {
  const BOM = '\uFEFF';
  const blob = new Blob([BOM + content], { type: `${mimeType};charset=utf-8` });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};

const printData = (
  data: any[],
  columns: ColumnConfig[],
  title: string,
  formatters?: Record<string, (value: any, row: any) => string>
) => {
  const printWindow = window.open('', '_blank');
  if (!printWindow) return;

  const visibleColumns = columns.filter(col => col.visible);

  const tableRows = data
    .map(row => {
      const cells = visibleColumns
        .map(col => `<td>${formatValue(row[col.key], col.key, row, formatters)}</td>`)
        .join('');
      return `<tr>${cells}</tr>`;
    })
    .join('');

  const headerCells = visibleColumns.map(col => `<th>${col.label}</th>`).join('');

  printWindow.document.write(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>${title}</title>
      <style>
        * { box-sizing: border-box; }
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 20px; margin: 0; }
        h1 { color: #007E45; margin-bottom: 8px; font-size: 24px; }
        .meta { color: #666; margin-bottom: 20px; font-size: 12px; }
        table { border-collapse: collapse; width: 100%; font-size: 12px; }
        th { background: #007E45; color: white; padding: 10px 8px; text-align: left; font-weight: 600; }
        td { border-bottom: 1px solid #e5e7eb; padding: 8px; }
        tr:hover { background-color: #f9fafb; }
        .footer { margin-top: 30px; padding-top: 15px; border-top: 1px solid #e5e7eb; font-size: 11px; color: #9ca3af; }
        @media print {
          body { padding: 0; }
          .no-print { display: none; }
          tr { page-break-inside: avoid; }
        }
      </style>
    </head>
    <body>
      <h1>${title}</h1>
      <p class="meta">
        ${data.length} élément(s) • Exporté le ${new Date().toLocaleDateString('fr-FR')} à ${new Date().toLocaleTimeString('fr-FR')}
        • Colonnes: ${visibleColumns.length}/${columns.length}
      </p>
      <table>
        <thead><tr>${headerCells}</tr></thead>
        <tbody>${tableRows}</tbody>
      </table>
      <div class="footer">
        <p>Document généré automatiquement - ${visibleColumns.map(c => c.label).join(', ')}</p>
      </div>
      <script>window.onload = function() { window.print(); }</script>
    </body>
    </html>
  `);
  printWindow.document.close();
};

// ============================================
// COMPOSANT PRINCIPAL
// ============================================

const ExportDropdown: React.FC<ExportDropdownProps> = ({
  data,
  columns,
  columnFormatters,
  filename = 'export',
  className,
  onExportStart,
  onExportEnd,
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [isExporting, setIsExporting] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);

  const visibleColumnsCount = columns.filter(col => col.visible).length;

  const exportOptions: { format: ExportFormat; label: string; icon: React.ElementType }[] = [
    { format: 'csv', label: 'CSV', icon: FileText },
    { format: 'txt', label: 'TXT', icon: File },
    { format: 'excel', label: 'EXCEL', icon: FileSpreadsheet },
    { format: 'print', label: 'PRINT', icon: Printer },
  ];

  const handleExport = async (format: ExportFormat) => {
    if (data.length === 0) {
      alert('Aucune donnée à exporter');
      return;
    }

    setIsExporting(true);
    onExportStart?.();

    try {
      const timestamp = new Date().toISOString().split('T')[0];
      const baseFilename = `${filename}_${timestamp}`;

      switch (format) {
        case 'csv': {
          const csv = generateCSV(data, columns, columnFormatters);
          downloadFile(csv, `${baseFilename}.csv`, 'text/csv');
          break;
        }
        case 'txt': {
          const txt = generateTXT(data, columns, columnFormatters);
          downloadFile(txt, `${baseFilename}.txt`, 'text/plain');
          break;
        }
        case 'excel': {
          const excel = generateExcelXML(data, columns, filename, columnFormatters);
          downloadFile(excel, `${baseFilename}.xls`, 'application/vnd.ms-excel');
          break;
        }
        case 'print': {
          printData(data, columns, filename, columnFormatters);
          break;
        }
      }
    } catch (error) {
      console.error("Erreur lors de l'export:", error);
      alert("Une erreur est survenue lors de l'export");
    } finally {
      setIsExporting(false);
      setIsOpen(false);
      onExportEnd?.();
    }
  };

  // Fermer le dropdown en cliquant à l'extérieur
  React.useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        setIsOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  return (
    <div className={cn('relative', className)} ref={dropdownRef}>
      {/* Bouton principal */}
      <Button
        onClick={() => setIsOpen(!isOpen)}
        variant="outline"
        disabled={isExporting}
        className={cn('border-solid border-[#338660] bg-[#338660]/5 text-[#338660] gap-2 h-10')}
      >
        {isExporting ? (
          <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
        ) : (
          <Download className="w-4 h-4" />
        )}
        <span>Exporter</span>
        <ChevronDown className={cn('w-4 h-4 transition-transform', isOpen && 'rotate-180')} />
      </Button>

      {/* Dropdown menu */}
      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0, y: -10, scale: 0.95 }}
            animate={{ opacity: 1, y: 0, scale: 1 }}
            exit={{ opacity: 0, y: -10, scale: 0.95 }}
            transition={{ duration: 0.15 }}
            className="absolute right-0 mt-2 w-48 bg-white dark:bg-gray-900 rounded-xl shadow-xl border border-gray-100 dark:border-gray-800 overflow-hidden z-50"
          >
            <div className="py-1">
              {exportOptions.map(({ format, label, icon: Icon }) => (
                <button
                  key={format}
                  onClick={() => handleExport(format)}
                  className="w-full flex items-center gap-3 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                >
                  <Icon className="w-4 h-4 text-gray-400" />
                  <span className="font-medium">{label}</span>
                </button>
              ))}
            </div>

            {/* Footer avec infos */}
            <div className="px-4 py-2.5 bg-gray-50 dark:bg-gray-800/50 border-t border-gray-100 dark:border-gray-800">
              <p className="text-xs text-gray-500 dark:text-gray-400">
                {data.length} ligne{data.length > 1 ? 's' : ''}
              </p>
              <p className="text-xs text-gray-400 dark:text-gray-500">
                {visibleColumnsCount} colonne{visibleColumnsCount > 1 ? 's' : ''} sélectionnée{visibleColumnsCount > 1 ? 's' : ''}
              </p>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

export default ExportDropdown;