/**
 * FileDropzone - Drag and drop file upload component
 *
 * Supports drag-and-drop or click-to-browse for model files.
 * Accepts .prt, .sim, .fem, .afem files.
 */

import React, { useState, useCallback, useRef } from 'react';
import { Upload, FileText, X, Loader2, AlertCircle, CheckCircle } from 'lucide-react';
import { intakeApi } from '../../api/intake';

interface FileDropzoneProps {
  studyName: string;
  onUploadComplete: () => void;
  compact?: boolean;
}

interface FileStatus {
  file: File;
  status: 'pending' | 'uploading' | 'success' | 'error';
  message?: string;
}

const VALID_EXTENSIONS = ['.prt', '.sim', '.fem', '.afem'];

export const FileDropzone: React.FC<FileDropzoneProps> = ({
  studyName,
  onUploadComplete,
  compact = false,
}) => {
  const [isDragging, setIsDragging] = useState(false);
  const [files, setFiles] = useState<FileStatus[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const validateFile = (file: File): { valid: boolean; reason?: string } => {
    const ext = '.' + file.name.split('.').pop()?.toLowerCase();
    if (!VALID_EXTENSIONS.includes(ext)) {
      return { valid: false, reason: `Invalid type: ${ext}` };
    }
    // Max 500MB per file
    if (file.size > 500 * 1024 * 1024) {
      return { valid: false, reason: 'File too large (max 500MB)' };
    }
    return { valid: true };
  };

  const handleDragEnter = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(true);
  }, []);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
  }, []);

  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
  }, []);

  const addFiles = useCallback((newFiles: File[]) => {
    const validFiles: FileStatus[] = [];
    
    for (const file of newFiles) {
      // Skip duplicates
      if (files.some(f => f.file.name === file.name)) {
        continue;
      }
      
      const validation = validateFile(file);
      if (validation.valid) {
        validFiles.push({ file, status: 'pending' });
      } else {
        validFiles.push({ file, status: 'error', message: validation.reason });
      }
    }
    
    setFiles(prev => [...prev, ...validFiles]);
  }, [files]);

  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
    
    const droppedFiles = Array.from(e.dataTransfer.files);
    addFiles(droppedFiles);
  }, [addFiles]);

  const handleFileSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFiles = Array.from(e.target.files || []);
    addFiles(selectedFiles);
    // Reset input so the same file can be selected again
    e.target.value = '';
  }, [addFiles]);

  const removeFile = (index: number) => {
    setFiles(prev => prev.filter((_, i) => i !== index));
  };

  const handleUpload = async () => {
    const pendingFiles = files.filter(f => f.status === 'pending');
    if (pendingFiles.length === 0) return;

    setIsUploading(true);
    setError(null);

    try {
      // Upload files
      const response = await intakeApi.uploadFiles(
        studyName,
        pendingFiles.map(f => f.file)
      );

      // Update file statuses based on response
      const uploadResults = new Map(
        response.uploaded_files.map(f => [f.name, f.status === 'uploaded'])
      );

      setFiles(prev => prev.map(f => {
        if (f.status !== 'pending') return f;
        const success = uploadResults.get(f.file.name);
        return {
          ...f,
          status: success ? 'success' : 'error',
          message: success ? undefined : 'Upload failed',
        };
      }));

      // Clear successful uploads after a moment and refresh
      setTimeout(() => {
        setFiles(prev => prev.filter(f => f.status !== 'success'));
        onUploadComplete();
      }, 1500);

    } catch (err) {
      setError(err instanceof Error ? err.message : 'Upload failed');
      setFiles(prev => prev.map(f => 
        f.status === 'pending' 
          ? { ...f, status: 'error', message: 'Upload failed' }
          : f
      ));
    } finally {
      setIsUploading(false);
    }
  };

  const pendingCount = files.filter(f => f.status === 'pending').length;

  if (compact) {
    // Compact inline version
    return (
      <div className="space-y-2">
        <div className="flex items-center gap-2">
          <button
            onClick={() => fileInputRef.current?.click()}
            className="flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm font-medium
                       bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-white
                       transition-colors"
          >
            <Upload className="w-4 h-4" />
            Add Files
          </button>
          {pendingCount > 0 && (
            <button
              onClick={handleUpload}
              disabled={isUploading}
              className="flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm font-medium
                         bg-primary-500/10 text-primary-400 hover:bg-primary-500/20
                         disabled:opacity-50 transition-colors"
            >
              {isUploading ? (
                <Loader2 className="w-4 h-4 animate-spin" />
              ) : (
                <Upload className="w-4 h-4" />
              )}
              Upload {pendingCount} {pendingCount === 1 ? 'File' : 'Files'}
            </button>
          )}
        </div>
        
        {/* File list */}
        {files.length > 0 && (
          <div className="flex flex-wrap gap-2">
            {files.map((f, i) => (
              <span
                key={i}
                className={`inline-flex items-center gap-1.5 px-2 py-1 rounded text-xs
                           ${f.status === 'error' ? 'bg-red-500/10 text-red-400' : 
                             f.status === 'success' ? 'bg-green-500/10 text-green-400' :
                             'bg-dark-700 text-dark-300'}`}
              >
                {f.status === 'uploading' && <Loader2 className="w-3 h-3 animate-spin" />}
                {f.status === 'success' && <CheckCircle className="w-3 h-3" />}
                {f.status === 'error' && <AlertCircle className="w-3 h-3" />}
                {f.file.name}
                {f.status === 'pending' && (
                  <button onClick={() => removeFile(i)} className="hover:text-white">
                    <X className="w-3 h-3" />
                  </button>
                )}
              </span>
            ))}
          </div>
        )}
        
        <input
          ref={fileInputRef}
          type="file"
          multiple
          accept={VALID_EXTENSIONS.join(',')}
          onChange={handleFileSelect}
          className="hidden"
        />
      </div>
    );
  }

  // Full dropzone version
  return (
    <div className="space-y-4">
      {/* Dropzone */}
      <div
        onDragEnter={handleDragEnter}
        onDragLeave={handleDragLeave}
        onDragOver={handleDragOver}
        onDrop={handleDrop}
        onClick={() => fileInputRef.current?.click()}
        className={`
          relative border-2 border-dashed rounded-xl p-6 cursor-pointer
          transition-all duration-200
          ${isDragging 
            ? 'border-primary-400 bg-primary-400/5' 
            : 'border-dark-600 hover:border-primary-400/50 hover:bg-white/5'
          }
        `}
      >
        <div className="flex flex-col items-center text-center">
          <div className={`w-12 h-12 rounded-full flex items-center justify-center mb-3
                          ${isDragging ? 'bg-primary-400/20 text-primary-400' : 'bg-dark-700 text-dark-400'}`}>
            <Upload className="w-6 h-6" />
          </div>
          <p className="text-white font-medium mb-1">
            {isDragging ? 'Drop files here' : 'Drop model files here'}
          </p>
          <p className="text-sm text-dark-400">
            or <span className="text-primary-400">click to browse</span>
          </p>
          <p className="text-xs text-dark-500 mt-2">
            Accepts: {VALID_EXTENSIONS.join(', ')}
          </p>
        </div>
      </div>

      {/* Error */}
      {error && (
        <div className="p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-400 text-sm flex items-center gap-2">
          <AlertCircle className="w-4 h-4 flex-shrink-0" />
          {error}
        </div>
      )}

      {/* File List */}
      {files.length > 0 && (
        <div className="space-y-2">
          <h5 className="text-sm font-medium text-dark-300">Files to Upload</h5>
          <div className="space-y-1">
            {files.map((f, i) => (
              <div
                key={i}
                className={`flex items-center justify-between p-2 rounded-lg
                           ${f.status === 'error' ? 'bg-red-500/10' : 
                             f.status === 'success' ? 'bg-green-500/10' :
                             'bg-dark-700'}`}
              >
                <div className="flex items-center gap-2">
                  {f.status === 'pending' && <FileText className="w-4 h-4 text-dark-400" />}
                  {f.status === 'uploading' && <Loader2 className="w-4 h-4 text-primary-400 animate-spin" />}
                  {f.status === 'success' && <CheckCircle className="w-4 h-4 text-green-400" />}
                  {f.status === 'error' && <AlertCircle className="w-4 h-4 text-red-400" />}
                  <span className={`text-sm ${f.status === 'error' ? 'text-red-400' : 
                                              f.status === 'success' ? 'text-green-400' : 
                                              'text-white'}`}>
                    {f.file.name}
                  </span>
                  {f.message && (
                    <span className="text-xs text-red-400">({f.message})</span>
                  )}
                </div>
                {f.status === 'pending' && (
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      removeFile(i);
                    }}
                    className="p-1 hover:bg-white/10 rounded text-dark-400 hover:text-white"
                  >
                    <X className="w-4 h-4" />
                  </button>
                )}
              </div>
            ))}
          </div>

          {/* Upload Button */}
          {pendingCount > 0 && (
            <button
              onClick={handleUpload}
              disabled={isUploading}
              className="w-full flex items-center justify-center gap-2 px-4 py-2 rounded-lg
                         bg-primary-500 text-white font-medium
                         hover:bg-primary-400 disabled:opacity-50 disabled:cursor-not-allowed
                         transition-colors"
            >
              {isUploading ? (
                <>
                  <Loader2 className="w-4 h-4 animate-spin" />
                  Uploading...
                </>
              ) : (
                <>
                  <Upload className="w-4 h-4" />
                  Upload {pendingCount} {pendingCount === 1 ? 'File' : 'Files'}
                </>
              )}
            </button>
          )}
        </div>
      )}

      <input
        ref={fileInputRef}
        type="file"
        multiple
        accept={VALID_EXTENSIONS.join(',')}
        onChange={handleFileSelect}
        className="hidden"
      />
    </div>
  );
};

export default FileDropzone;
