import React, { useState, useMemo } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useForm, Controller } from 'react-hook-form';
import { format } from 'date-fns';
import jsPDF from 'jspdf';
import autoTable from 'jspdf-autotable';
import {
  X,
  Download,
  FileText,
  Code,
  File,
  Calendar,
  Filter,
  Settings,
  CheckCircle,
  AlertCircle
} from 'lucide-react';
import { AuditLogEntry, AuditSearchFilters, AuditExportRequest } from '@/types/audit';
import { toast } from 'react-toastify';

interface ExportModalProps {
  isOpen: boolean;
  onClose: () => void;
  logs: AuditLogEntry[];
  filters: AuditSearchFilters;
  totalCount: number;
  onExport: (request: AuditExportRequest) => Promise<Blob>;
}

interface FormData {
  format: 'csv' | 'json' | 'pdf';
  includeMetadata: boolean;
  includeCompliance: boolean;
  dateFormat: string;
  template: string;
  fields: string[];
  maxRecords: number;
  includeFilters: boolean;
}

const formatOptions = [
  {
    value: 'csv' as const,
    label: 'CSV',
    description: 'Comma-separated values for spreadsheet applications',
    icon: File,
    maxRecords: 100000,
    supportedFeatures: ['fields', 'dateFormat', 'maxRecords']
  },
  {
    value: 'json' as const,
    label: 'JSON',
    description: 'JavaScript Object Notation for programmatic use',
    icon: Code,
    maxRecords: 50000,
    supportedFeatures: ['metadata', 'compliance', 'maxRecords']
  },
  {
    value: 'pdf' as const,
    label: 'PDF',
    description: 'Portable Document Format for reports and documentation',
    icon: FileText,
    maxRecords: 10000,
    supportedFeatures: ['template', 'fields', 'dateFormat', 'maxRecords']
  }
];

const availableFields = [
  { value: 'timestamp', label: 'Timestamp', required: true },
  { value: 'user.username', label: 'Username', required: true },
  { value: 'user.email', label: 'User Email' },
  { value: 'user.roles', label: 'User Roles' },
  { value: 'action.type', label: 'Action Type', required: true },
  { value: 'action.resource', label: 'Resource', required: true },
  { value: 'action.resourceId', label: 'Resource ID' },
  { value: 'action.description', label: 'Description' },
  { value: 'result.success', label: 'Success', required: true },
  { value: 'result.decision', label: 'Decision' },
  { value: 'result.reason', label: 'Reason' },
  { value: 'severity', label: 'Severity', required: true },
  { value: 'context.sessionId', label: 'Session ID' },
  { value: 'context.requestId', label: 'Request ID' },
  { value: 'context.ipAddress', label: 'IP Address' },
  { value: 'context.location.country', label: 'Country' },
  { value: 'context.location.city', label: 'City' },
  { value: 'context.mfaEnabled', label: 'MFA Enabled' },
  { value: 'tags', label: 'Tags' },
  { value: 'compliance.soc2Relevant', label: 'SOC2 Relevant' },
  { value: 'compliance.hipaaRelevant', label: 'HIPAA Relevant' },
  { value: 'compliance.pciRelevant', label: 'PCI Relevant' },
  { value: 'compliance.gdprRelevant', label: 'GDPR Relevant' }
];

const dateFormatOptions = [
  { value: 'iso', label: 'ISO 8601 (2023-12-25T10:30:00Z)' },
  { value: 'human', label: 'Human Readable (Dec 25, 2023 10:30 AM)' },
  { value: 'unix', label: 'Unix Timestamp (1703500200)' },
  { value: 'custom', label: 'Custom Format' }
];

const templateOptions = [
  { value: 'standard', label: 'Standard Report' },
  { value: 'compliance', label: 'Compliance Report' },
  { value: 'executive', label: 'Executive Summary' },
  { value: 'incident', label: 'Incident Report' },
  { value: 'audit', label: 'Audit Trail Report' }
];

export const ExportModal: React.FC<ExportModalProps> = ({
  isOpen,
  onClose,
  logs,
  filters,
  totalCount,
  onExport
}) => {
  const [isExporting, setIsExporting] = useState(false);
  const [exportProgress, setExportProgress] = useState(0);

  const { control, watch, setValue, getValues } = useForm<FormData>({
    defaultValues: {
      format: 'csv',
      includeMetadata: true,
      includeCompliance: true,
      dateFormat: 'iso',
      template: 'standard',
      fields: availableFields.filter(f => f.required).map(f => f.value),
      maxRecords: 1000,
      includeFilters: true
    }
  });

  const watchedFormat = watch('format');
  const watchedFields = watch('fields');
  const watchedMaxRecords = watch('maxRecords');

  const selectedFormatOption = useMemo(
    () => formatOptions.find(option => option.value === watchedFormat),
    [watchedFormat]
  );

  const estimatedSize = useMemo(() => {
    const recordCount = Math.min(watchedMaxRecords, logs.length);
    const fieldsCount = watchedFields.length;

    switch (watchedFormat) {
      case 'csv':
        return Math.round((recordCount * fieldsCount * 20) / 1024); // ~20 bytes per field
      case 'json':
        return Math.round((recordCount * 500) / 1024); // ~500 bytes per record
      case 'pdf':
        return Math.round(recordCount / 50 + 100); // ~50 records per page, base 100KB
      default:
        return 0;
    }
  }, [watchedFormat, watchedFields.length, watchedMaxRecords, logs.length]);

  const handleFieldToggle = (fieldValue: string, isRequired = false) => {
    if (isRequired) return; // Don't allow toggling required fields

    const currentFields = watchedFields;
    const updatedFields = currentFields.includes(fieldValue)
      ? currentFields.filter(f => f !== fieldValue)
      : [...currentFields, fieldValue];

    setValue('fields', updatedFields);
  };

  const handleSelectAllFields = () => {
    setValue('fields', availableFields.map(f => f.value));
  };

  const handleSelectRequiredFields = () => {
    setValue('fields', availableFields.filter(f => f.required).map(f => f.value));
  };

  const convertToCSV = (logs: AuditLogEntry[], fields: string[]): string => {
    const headers = fields.map(field => {
      const fieldConfig = availableFields.find(f => f.value === field);
      return fieldConfig?.label || field;
    });

    const getValue = (log: AuditLogEntry, field: string): string => {
      const keys = field.split('.');
      let value: any = log;

      for (const key of keys) {
        value = value?.[key];
      }

      if (Array.isArray(value)) {
        return value.join(', ');
      }

      if (value instanceof Date) {
        return format(value, 'yyyy-MM-dd HH:mm:ss');
      }

      return value?.toString() || '';
    };

    const rows = logs.map(log =>
      fields.map(field => {
        const value = getValue(log, field);
        // Escape CSV values that contain commas or quotes
        return value.includes(',') || value.includes('"')
          ? `"${value.replace(/"/g, '""')}"`
          : value;
      })
    );

    return [headers.join(','), ...rows.map(row => row.join(','))].join('\n');
  };

  const generatePDF = (logs: AuditLogEntry[], fields: string[]): jsPDF => {
    const doc = new jsPDF();

    // Add title
    doc.setFontSize(20);
    doc.text('Audit Log Export', 20, 20);

    // Add metadata
    doc.setFontSize(10);
    doc.text(`Generated: ${format(new Date(), 'PPpp')}`, 20, 30);
    doc.text(`Records: ${logs.length}`, 20, 35);
    doc.text(`Filters Applied: ${Object.keys(filters).length > 0 ? 'Yes' : 'No'}`, 20, 40);

    // Prepare table data
    const headers = fields.map(field => {
      const fieldConfig = availableFields.find(f => f.value === field);
      return fieldConfig?.label || field;
    });

    const data = logs.map(log => {
      return fields.map(field => {
        const keys = field.split('.');
        let value: any = log;

        for (const key of keys) {
          value = value?.[key];
        }

        if (Array.isArray(value)) {
          return value.join(', ');
        }

        if (value instanceof Date) {
          return format(value, 'MMM dd, yyyy HH:mm');
        }

        return value?.toString() || '';
      });
    });

    // Add table
    autoTable(doc, {
      head: [headers],
      body: data,
      startY: 50,
      styles: { fontSize: 8 },
      headStyles: { fillColor: [59, 130, 246] },
      columnStyles: {
        0: { cellWidth: 30 }, // Timestamp
      },
      margin: { top: 50 },
      didDrawPage: (data) => {
        // Add page numbers
        doc.setFontSize(8);
        doc.text(
          `Page ${data.pageNumber}`,
          doc.internal.pageSize.width - 30,
          doc.internal.pageSize.height - 10
        );
      }
    });

    return doc;
  };

  const handleExport = async () => {
    setIsExporting(true);
    setExportProgress(0);

    try {
      const formData = getValues();
      const recordsToExport = logs.slice(0, formData.maxRecords);

      // Simulate progress
      const progressInterval = setInterval(() => {
        setExportProgress(prev => Math.min(prev + 10, 90));
      }, 100);

      let blob: Blob;
      let filename: string;

      switch (formData.format) {
        case 'csv':
          const csvContent = convertToCSV(recordsToExport, formData.fields);
          blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
          filename = `audit-logs-${format(new Date(), 'yyyy-MM-dd')}.csv`;
          break;

        case 'json':
          const jsonContent = JSON.stringify({
            exportedAt: new Date().toISOString(),
            totalRecords: logs.length,
            exportedRecords: recordsToExport.length,
            filters: formData.includeFilters ? filters : undefined,
            logs: recordsToExport
          }, null, 2);
          blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' });
          filename = `audit-logs-${format(new Date(), 'yyyy-MM-dd')}.json`;
          break;

        case 'pdf':
          const pdf = generatePDF(recordsToExport, formData.fields);
          blob = new Blob([pdf.output('blob')], { type: 'application/pdf' });
          filename = `audit-logs-${format(new Date(), 'yyyy-MM-dd')}.pdf`;
          break;

        default:
          throw new Error('Unsupported format');
      }

      clearInterval(progressInterval);
      setExportProgress(100);

      // Download file
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);

      toast.success(`Successfully exported ${recordsToExport.length} records as ${formData.format.toUpperCase()}`);

      setTimeout(() => {
        onClose();
      }, 1000);

    } catch (error) {
      console.error('Export failed:', error);
      toast.error('Export failed. Please try again.');
    } finally {
      setIsExporting(false);
      setExportProgress(0);
    }
  };

  if (!isOpen) return null;

  return (
    <AnimatePresence>
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        className="modal modal-open"
      >
        <motion.div
          initial={{ opacity: 0, scale: 0.95 }}
          animate={{ opacity: 1, scale: 1 }}
          exit={{ opacity: 0, scale: 0.95 }}
          className="modal-box w-11/12 max-w-4xl"
        >
          {/* Header */}
          <div className="flex items-center justify-between mb-6">
            <h2 className="text-xl font-bold">Export Audit Logs</h2>
            <button onClick={onClose} className="btn btn-ghost btn-sm">
              <X className="h-4 w-4" />
            </button>
          </div>

          {/* Export Summary */}
          <div className="bg-base-200 rounded-lg p-4 mb-6">
            <div className="flex items-center justify-between">
              <div className="flex items-center space-x-4">
                <div className="flex items-center space-x-2">
                  <File className="h-4 w-4 text-primary" />
                  <span className="font-medium">{logs.length.toLocaleString()} records available</span>
                </div>
                <div className="flex items-center space-x-2">
                  <Calendar className="h-4 w-4 text-base-content/60" />
                  <span className="text-sm text-base-content/60">
                    {totalCount > logs.length ? `${totalCount.toLocaleString()} total (filtered)` : 'All records'}
                  </span>
                </div>
              </div>
              <div className="text-right">
                <div className="text-sm font-medium">Estimated size: {estimatedSize}KB</div>
              </div>
            </div>
          </div>

          <div className="grid grid-cols-2 gap-6">
            {/* Format Selection */}
            <div className="space-y-4">
              <h3 className="text-lg font-semibold">Export Format</h3>
              <Controller
                name="format"
                control={control}
                render={({ field }) => (
                  <div className="space-y-3">
                    {formatOptions.map((option) => (
                      <label
                        key={option.value}
                        className={`block p-4 border rounded-lg cursor-pointer transition-colors ${
                          field.value === option.value
                            ? 'border-primary bg-primary/5'
                            : 'border-base-300 hover:border-base-400'
                        }`}
                      >
                        <input
                          type="radio"
                          {...field}
                          value={option.value}
                          className="sr-only"
                        />
                        <div className="flex items-start space-x-3">
                          <option.icon className="h-5 w-5 text-primary mt-0.5" />
                          <div>
                            <div className="font-medium">{option.label}</div>
                            <div className="text-sm text-base-content/60 mt-1">
                              {option.description}
                            </div>
                            <div className="text-xs text-base-content/50 mt-1">
                              Max records: {option.maxRecords.toLocaleString()}
                            </div>
                          </div>
                        </div>
                      </label>
                    ))}
                  </div>
                )}
              />
            </div>

            {/* Options */}
            <div className="space-y-4">
              <h3 className="text-lg font-semibold">Export Options</h3>

              {/* Max Records */}
              <div>
                <label className="label">
                  <span className="label-text">Maximum Records</span>
                </label>
                <Controller
                  name="maxRecords"
                  control={control}
                  render={({ field }) => (
                    <input
                      {...field}
                      type="number"
                      min="1"
                      max={selectedFormatOption?.maxRecords}
                      className="input input-bordered w-full"
                      onChange={(e) => field.onChange(parseInt(e.target.value) || 1)}
                    />
                  )}
                />
                <div className="label">
                  <span className="label-text-alt text-base-content/60">
                    Max allowed: {selectedFormatOption?.maxRecords.toLocaleString()}
                  </span>
                </div>
              </div>

              {/* Additional Options */}
              {selectedFormatOption?.supportedFeatures.includes('metadata') && (
                <div className="form-control">
                  <Controller
                    name="includeMetadata"
                    control={control}
                    render={({ field }) => (
                      <label className="label cursor-pointer justify-start space-x-2">
                        <input
                          type="checkbox"
                          className="checkbox"
                          checked={field.value}
                          onChange={field.onChange}
                        />
                        <span className="label-text">Include metadata</span>
                      </label>
                    )}
                  />
                </div>
              )}

              {selectedFormatOption?.supportedFeatures.includes('compliance') && (
                <div className="form-control">
                  <Controller
                    name="includeCompliance"
                    control={control}
                    render={({ field }) => (
                      <label className="label cursor-pointer justify-start space-x-2">
                        <input
                          type="checkbox"
                          className="checkbox"
                          checked={field.value}
                          onChange={field.onChange}
                        />
                        <span className="label-text">Include compliance data</span>
                      </label>
                    )}
                  />
                </div>
              )}

              <div className="form-control">
                <Controller
                  name="includeFilters"
                  control={control}
                  render={({ field }) => (
                    <label className="label cursor-pointer justify-start space-x-2">
                      <input
                        type="checkbox"
                        className="checkbox"
                        checked={field.value}
                        onChange={field.onChange}
                      />
                      <span className="label-text">Include applied filters</span>
                    </label>
                  )}
                />
              </div>

              {/* Date Format */}
              {selectedFormatOption?.supportedFeatures.includes('dateFormat') && (
                <div>
                  <label className="label">
                    <span className="label-text">Date Format</span>
                  </label>
                  <Controller
                    name="dateFormat"
                    control={control}
                    render={({ field }) => (
                      <select {...field} className="select select-bordered w-full">
                        {dateFormatOptions.map((option) => (
                          <option key={option.value} value={option.value}>
                            {option.label}
                          </option>
                        ))}
                      </select>
                    )}
                  />
                </div>
              )}

              {/* Template Selection for PDF */}
              {selectedFormatOption?.supportedFeatures.includes('template') && (
                <div>
                  <label className="label">
                    <span className="label-text">Report Template</span>
                  </label>
                  <Controller
                    name="template"
                    control={control}
                    render={({ field }) => (
                      <select {...field} className="select select-bordered w-full">
                        {templateOptions.map((option) => (
                          <option key={option.value} value={option.value}>
                            {option.label}
                          </option>
                        ))}
                      </select>
                    )}
                  />
                </div>
              )}
            </div>
          </div>

          {/* Field Selection */}
          {selectedFormatOption?.supportedFeatures.includes('fields') && (
            <div className="mt-6">
              <div className="flex items-center justify-between mb-3">
                <h3 className="text-lg font-semibold">Fields to Export</h3>
                <div className="space-x-2">
                  <button
                    type="button"
                    onClick={handleSelectRequiredFields}
                    className="btn btn-ghost btn-sm"
                  >
                    Required Only
                  </button>
                  <button
                    type="button"
                    onClick={handleSelectAllFields}
                    className="btn btn-ghost btn-sm"
                  >
                    Select All
                  </button>
                </div>
              </div>

              <div className="bg-base-200 rounded-lg p-4">
                <div className="grid grid-cols-3 gap-3">
                  {availableFields.map((field) => (
                    <label
                      key={field.value}
                      className="flex items-center space-x-2 cursor-pointer"
                    >
                      <input
                        type="checkbox"
                        className="checkbox checkbox-sm"
                        checked={watchedFields.includes(field.value)}
                        onChange={() => handleFieldToggle(field.value, field.required)}
                        disabled={field.required}
                      />
                      <span className={`text-sm ${field.required ? 'font-medium' : ''}`}>
                        {field.label}
                        {field.required && <span className="text-error ml-1">*</span>}
                      </span>
                    </label>
                  ))}
                </div>
                <div className="mt-2 text-xs text-base-content/60">
                  * Required fields cannot be deselected
                </div>
              </div>
            </div>
          )}

          {/* Export Progress */}
          {isExporting && (
            <div className="mt-6 bg-base-200 rounded-lg p-4">
              <div className="flex items-center space-x-3">
                <div className="loading-spinner"></div>
                <div className="flex-1">
                  <div className="flex items-center justify-between mb-1">
                    <span className="text-sm font-medium">Exporting...</span>
                    <span className="text-sm">{exportProgress}%</span>
                  </div>
                  <progress
                    className="progress progress-primary w-full"
                    value={exportProgress}
                    max="100"
                  ></progress>
                </div>
              </div>
            </div>
          )}

          {/* Actions */}
          <div className="modal-action">
            <button
              onClick={onClose}
              className="btn"
              disabled={isExporting}
            >
              Cancel
            </button>
            <button
              onClick={handleExport}
              className="btn btn-primary"
              disabled={isExporting || watchedFields.length === 0}
            >
              {isExporting ? (
                'Exporting...'
              ) : (
                <>
                  <Download className="h-4 w-4 mr-2" />
                  Export {watchedFormat.toUpperCase()}
                </>
              )}
            </button>
          </div>
        </motion.div>
      </motion.div>
    </AnimatePresence>
  );
};
