import { useRef, useState, useEffect } from 'react';
import { useFileService } from '../hooks/useFileService';
import { FileViewer } from './FileViewer';
import { generateFilePreview } from '../utils/filePreview';
import { validateFile, formatFileSize } from '../utils/fileValidation';
import type { FileServiceConfig, FilePreview, ValidationResult } from '../types';

interface FileUploaderProps {
  config?: FileServiceConfig;
  onUploadSuccess?: (fileId: string) => void;
  onUploadError?: (error: string) => void;
  className?: string;
  accept?: string;
  multiple?: boolean;
  showPreviewAfterUpload?: boolean;
  showPreviewBeforeUpload?: boolean;
}

export function FileUploader({
  config,
  onUploadSuccess,
  onUploadError,
  className = '',
  accept,
  multiple = false,
  showPreviewAfterUpload = true,
  showPreviewBeforeUpload = true,
}: FileUploaderProps) {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [dragActive, setDragActive] = useState(false);
  const [uploadedFileId, setUploadedFileId] = useState<string | null>(null);
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [preview, setPreview] = useState<FilePreview | null>(null);
  const [filePreviewUrl, setFilePreviewUrl] = useState<string | null>(null);
  const [validation, setValidation] = useState<ValidationResult | null>(null);
  const [previewLoading, setPreviewLoading] = useState(false);
  const { uploadFile, loading, error } = useFileService(config);

  // Generate preview when file is selected
  useEffect(() => {
    if (selectedFile && showPreviewBeforeUpload) {
      setPreviewLoading(true);
      
      // Create object URL for preview
      const url = URL.createObjectURL(selectedFile);
      setFilePreviewUrl(url);

      // Generate preview metadata
      generateFilePreview(selectedFile)
        .then((previewData) => {
          setPreview(previewData);
          setPreviewLoading(false);
        })
        .catch((err) => {
          console.error('Preview generation failed:', err);
          setPreviewLoading(false);
        });

      // Validate file
      const validationResult = validateFile(selectedFile, config);
      setValidation(validationResult);

      return () => {
        URL.revokeObjectURL(url);
      };
    } else {
      setFilePreviewUrl(null);
      setPreview(null);
      setValidation(null);
    }
  }, [selectedFile, showPreviewBeforeUpload, config]);

  const handleFileSelect = (files: globalThis.FileList | null) => {
    if (!files || files.length === 0) {
      setSelectedFile(null);
      return;
    }

    const file = files[0];
    setSelectedFile(file);
  };

  const handleFileUpload = async () => {
    if (!selectedFile) return;

    const result = await uploadFile(selectedFile);

    if (result.success && result.file) {
      setUploadedFileId(result.file.id);
      setSelectedFile(null); // Clear selected file after upload
      onUploadSuccess?.(result.file.id);
    } else {
      setUploadedFileId(null);
      onUploadError?.(result.error || 'Upload failed');
    }
  };

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
      handleFileSelect(e.dataTransfer.files);
    }
  };

  const handleDrag = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === 'dragenter' || e.type === 'dragover') {
      setDragActive(true);
    } else if (e.type === 'dragleave') {
      setDragActive(false);
    }
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      handleFileSelect(e.target.files);
    }
  };

  const handleUploadNew = () => {
    setUploadedFileId(null);
    setSelectedFile(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  const handleCancel = () => {
    setSelectedFile(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  const renderFilePreview = () => {
    if (!selectedFile || !filePreviewUrl) return null;

    const fileExtension = selectedFile.name.split('.').pop()?.toLowerCase() || '';
    const isPdf = fileExtension === 'pdf';
    const isImage = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(fileExtension);
    const isText = ['txt', 'md', 'json', 'xml', 'html', 'css', 'js', 'ts', 'tsx', 'jsx'].includes(fileExtension);
    const isWord = ['doc', 'docx'].includes(fileExtension);
    const isCsv = fileExtension === 'csv';

    return (
      <div style={{ marginTop: '20px', border: '1px solid #ddd', borderRadius: '8px', padding: '20px' }}>
        <div style={{ marginBottom: '15px' }}>
          <h4 style={{ margin: '0 0 10px 0' }}>File Preview: {selectedFile.name}</h4>
          <div style={{ display: 'flex', gap: '15px', flexWrap: 'wrap', fontSize: '14px', color: '#666' }}>
            <span><strong>Size:</strong> {formatFileSize(selectedFile.size)}</span>
            <span><strong>Type:</strong> {selectedFile.type || fileExtension}</span>
            {preview?.pages && <span><strong>Pages:</strong> {preview.pages}</span>}
            {preview?.sheets && preview.sheets.length > 0 && (
              <span><strong>Sheets:</strong> {preview.sheets.join(', ')}</span>
            )}
          </div>
        </div>

        {previewLoading && (
          <div style={{ textAlign: 'center', padding: '40px' }}>
            <p>Generating preview...</p>
          </div>
        )}

        <div style={{ marginTop: '15px' }}>
          {isPdf && filePreviewUrl && (
            <iframe
              src={filePreviewUrl}
              title="PDF Preview"
              style={{
                width: '100%',
                height: '500px',
                border: '1px solid #ddd',
                borderRadius: '4px',
              }}
            />
          )}

          {isImage && filePreviewUrl && (
            <img
              src={filePreviewUrl}
              alt="File Preview"
              style={{
                maxWidth: '100%',
                maxHeight: '400px',
                border: '1px solid #ddd',
                borderRadius: '4px',
                objectFit: 'contain',
              }}
            />
          )}

          {isText && filePreviewUrl && (
            <iframe
              src={filePreviewUrl}
              title="Text Preview"
              style={{
                width: '100%',
                height: '400px',
                border: '1px solid #ddd',
                borderRadius: '4px',
              }}
            />
          )}

          {isWord && filePreviewUrl && (
            <div style={{ padding: '20px', backgroundColor: '#f5f5f5', borderRadius: '4px', textAlign: 'center' }}>
              <p>Word document preview</p>
              <p style={{ fontSize: '14px', color: '#666' }}>
                Upload the file to view it, or download after upload
              </p>
            </div>
          )}

          {isCsv && preview?.csvData && preview.csvData.length > 0 && (
            <div style={{ marginTop: '15px' }}>
              {preview.metadata && (
                <div style={{ padding: '10px', backgroundColor: '#f5f5f5', marginBottom: '10px', borderRadius: '4px' }}>
                  <div style={{ display: 'flex', gap: '20px', flexWrap: 'wrap', fontSize: '14px' }}>
                    {preview.metadata.rows && <span><strong>Total Rows:</strong> {preview.metadata.rows}</span>}
                    {preview.metadata.columns && <span><strong>Columns:</strong> {preview.metadata.columns}</span>}
                    {preview.metadata.rows && preview.metadata.rows > 100 && (
                      <span style={{ color: '#666' }}>Showing first 100 rows</span>
                    )}
                  </div>
                </div>
              )}
              <div style={{ 
                overflowX: 'auto', 
                overflowY: 'auto', 
                maxHeight: '400px',
                border: '1px solid #ddd',
                borderRadius: '4px',
              }}>
                <table style={{
                  width: '100%',
                  borderCollapse: 'collapse',
                  fontSize: '13px',
                }}>
                  <thead>
                    <tr style={{ backgroundColor: '#f8f9fa', position: 'sticky', top: 0 }}>
                      {preview.csvData[0]?.map((header: string, colIndex: number) => (
                        <th
                          key={colIndex}
                          style={{
                            padding: '10px',
                            textAlign: 'left',
                            borderBottom: '2px solid #dee2e6',
                            borderRight: '1px solid #dee2e6',
                            fontWeight: '600',
                            fontSize: '12px',
                          }}
                        >
                          {header || `Col ${colIndex + 1}`}
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {preview.csvData.slice(1, 21).map((row: string[], rowIndex: number) => (
                      <tr
                        key={rowIndex}
                        style={{
                          backgroundColor: rowIndex % 2 === 0 ? '#ffffff' : '#f8f9fa',
                        }}
                      >
                        {row.map((cell: string, colIndex: number) => (
                          <td
                            key={colIndex}
                            style={{
                              padding: '8px 10px',
                              borderBottom: '1px solid #dee2e6',
                              borderRight: '1px solid #dee2e6',
                              maxWidth: '150px',
                              overflow: 'hidden',
                              textOverflow: 'ellipsis',
                              whiteSpace: 'nowrap',
                              fontSize: '12px',
                            }}
                            title={cell}
                          >
                            {cell || ''}
                          </td>
                        ))}
                        {Array.from({ length: Math.max(0, (preview.csvData[0]?.length || 0) - row.length) }).map((_, idx) => (
                          <td
                            key={`empty-${idx}`}
                            style={{
                              padding: '8px 10px',
                              borderBottom: '1px solid #dee2e6',
                              borderRight: '1px solid #dee2e6',
                            }}
                          />
                        ))}
                      </tr>
                    ))}
                  </tbody>
                </table>
                {preview.csvData.length > 21 && (
                  <div style={{ padding: '10px', textAlign: 'center', backgroundColor: '#f8f9fa', fontSize: '12px', color: '#666' }}>
                    ... and {preview.csvData.length - 21} more rows (showing first 20)
                  </div>
                )}
              </div>
            </div>
          )}

          {!isPdf && !isImage && !isText && !isWord && !isCsv && (
            <div style={{ padding: '20px', backgroundColor: '#f5f5f5', borderRadius: '4px', textAlign: 'center' }}>
              <p>Preview not available for this file type</p>
              <p style={{ fontSize: '14px', color: '#666' }}>
                File: {selectedFile.name} ({formatFileSize(selectedFile.size)})
              </p>
            </div>
          )}
        </div>

        {validation && (
          <div style={{ marginTop: '15px' }}>
            {!validation.valid && validation.errors.length > 0 && (
              <div style={{
                padding: '10px',
                backgroundColor: '#ffebee',
                color: '#c62828',
                borderRadius: '4px',
                marginBottom: '10px',
              }}>
                {validation.errors.map((error, idx) => (
                  <p key={idx} style={{ margin: '5px 0' }}>❌ {error}</p>
                ))}
              </div>
            )}
            {validation.warnings.length > 0 && (
              <div style={{
                padding: '10px',
                backgroundColor: '#fff3e0',
                color: '#e65100',
                borderRadius: '4px',
              }}>
                {validation.warnings.map((warning, idx) => (
                  <p key={idx} style={{ margin: '5px 0' }}>⚠️ {warning}</p>
                ))}
              </div>
            )}
          </div>
        )}

        <div style={{ marginTop: '20px', display: 'flex', gap: '10px', justifyContent: 'flex-end' }}>
          <button
            onClick={handleCancel}
            style={{
              padding: '10px 20px',
              backgroundColor: '#757575',
              color: 'white',
              border: 'none',
              borderRadius: '4px',
              cursor: 'pointer',
            }}
          >
            Cancel
          </button>
          <button
            onClick={handleFileUpload}
            disabled={loading || (validation !== null && !validation.valid)}
            style={{
              padding: '10px 20px',
              backgroundColor: (validation !== null && !validation.valid) ? '#ccc' : '#4caf50',
              color: 'white',
              border: 'none',
              borderRadius: '4px',
              cursor: (validation !== null && !validation.valid) ? 'not-allowed' : 'pointer',
            }}
          >
            {loading ? 'Uploading...' : 'Upload File'}
          </button>
        </div>
      </div>
    );
  };

  return (
    <div className={`file-uploader ${className}`}>
      {!uploadedFileId && !selectedFile ? (
        <div
          className={`upload-area ${dragActive ? 'drag-active' : ''} ${loading ? 'loading' : ''}`}
          onDragEnter={handleDrag}
          onDragLeave={handleDrag}
          onDragOver={handleDrag}
          onDrop={handleDrop}
          onClick={() => fileInputRef.current?.click()}
          style={{
            border: '2px dashed #ccc',
            borderRadius: '8px',
            padding: '40px',
            textAlign: 'center',
            cursor: 'pointer',
            backgroundColor: dragActive ? '#f0f0f0' : '#fafafa',
            transition: 'background-color 0.2s',
          }}
        >
          <input
            ref={fileInputRef}
            type="file"
            onChange={handleChange}
            accept={accept}
            multiple={multiple}
            style={{ display: 'none' }}
          />
          <div className="upload-content">
            {loading ? (
              <div>
                <p style={{ fontSize: '18px', marginBottom: '10px' }}>Uploading...</p>
                <div style={{ 
                  width: '40px', 
                  height: '40px', 
                  border: '4px solid #f3f3f3',
                  borderTop: '4px solid #3498db',
                  borderRadius: '50%',
                  animation: 'spin 1s linear infinite',
                  margin: '0 auto',
                }} />
              </div>
            ) : (
              <>
                <p style={{ fontSize: '18px', marginBottom: '10px', fontWeight: 'bold' }}>
                  Click to upload or drag and drop
                </p>
                <p className="upload-hint" style={{ color: '#666', fontSize: '14px' }}>
                  Select a file to upload
                </p>
              </>
            )}
          </div>
        </div>
      ) : !uploadedFileId && selectedFile ? (
        <div>
          {showPreviewBeforeUpload && renderFilePreview()}
        </div>
      ) : (
        <div style={{ marginTop: '20px' }}>
          <div style={{ 
            display: 'flex', 
            justifyContent: 'space-between', 
            alignItems: 'center',
            marginBottom: '15px',
            padding: '10px',
            backgroundColor: '#e8f5e9',
            borderRadius: '4px',
          }}>
            <span style={{ color: '#2e7d32', fontWeight: 'bold' }}>
              ✅ File uploaded successfully!
            </span>
            <button
              onClick={handleUploadNew}
              style={{
                padding: '8px 16px',
                backgroundColor: '#2196f3',
                color: 'white',
                border: 'none',
                borderRadius: '4px',
                cursor: 'pointer',
                fontSize: '14px',
              }}
            >
              Upload Another
            </button>
          </div>
          
          {showPreviewAfterUpload && uploadedFileId && (
            <div style={{ marginTop: '20px' }}>
              <FileViewer 
                fileId={uploadedFileId} 
                config={config}
                showPreview={true}
              />
            </div>
          )}
        </div>
      )}
      
      {error && (
        <div 
          className="error-message" 
          style={{
            marginTop: '10px',
            padding: '10px',
            backgroundColor: '#ffebee',
            color: '#c62828',
            borderRadius: '4px',
            border: '1px solid #ef9a9a',
          }}
        >
          {error}
        </div>
      )}
    </div>
  );
}

