/**
 * StudioDropZone - Smart file drop zone for Studio
 * 
 * Handles both model files (.sim, .prt, .fem) and context files (.pdf, .md, .txt)
 */

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

interface StudioDropZoneProps {
  draftId: string;
  type: 'model' | 'context';
  files: string[];
  onUploadComplete: () => void;
}

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

const MODEL_EXTENSIONS = ['.prt', '.sim', '.fem', '.afem'];
const CONTEXT_EXTENSIONS = ['.md', '.txt', '.pdf', '.json', '.csv', '.docx'];

export const StudioDropZone: React.FC<StudioDropZoneProps> = ({
  draftId,
  type,
  files,
  onUploadComplete,
}) => {
  const [isDragging, setIsDragging] = useState(false);
  const [pendingFiles, setPendingFiles] = useState<FileStatus[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  
  const validExtensions = type === 'model' ? MODEL_EXTENSIONS : CONTEXT_EXTENSIONS;
  
  const validateFile = (file: File): { valid: boolean; reason?: string } => {
    const ext = '.' + file.name.split('.').pop()?.toLowerCase();
    if (!validExtensions.includes(ext)) {
      return { valid: false, reason: `Invalid type: ${ext}` };
    }
    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) {
      if (pendingFiles.some(f => f.file.name === file.name)) {
        continue;
      }
      
      const validation = validateFile(file);
      validFiles.push({
        file,
        status: validation.valid ? 'pending' : 'error',
        message: validation.reason,
      });
    }
    
    setPendingFiles(prev => [...prev, ...validFiles]);
  }, [pendingFiles, validExtensions]);
  
  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
    addFiles(Array.from(e.dataTransfer.files));
  }, [addFiles]);
  
  const handleFileSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    addFiles(Array.from(e.target.files || []));
    e.target.value = '';
  }, [addFiles]);
  
  const removeFile = (index: number) => {
    setPendingFiles(prev => prev.filter((_, i) => i !== index));
  };
  
  const uploadFiles = async () => {
    const toUpload = pendingFiles.filter(f => f.status === 'pending');
    if (toUpload.length === 0) return;
    
    setIsUploading(true);
    
    try {
      const uploadFn = type === 'model' 
        ? intakeApi.uploadFiles 
        : intakeApi.uploadContextFiles;
      
      const response = await uploadFn(draftId, toUpload.map(f => f.file));
      
      const results = new Map(
        response.uploaded_files.map(f => [f.name, f.status === 'uploaded'])
      );
      
      setPendingFiles(prev => prev.map(f => {
        if (f.status !== 'pending') return f;
        const success = results.get(f.file.name);
        return {
          ...f,
          status: success ? 'success' : 'error',
          message: success ? undefined : 'Upload failed',
        };
      }));
      
      setTimeout(() => {
        setPendingFiles(prev => prev.filter(f => f.status !== 'success'));
        onUploadComplete();
      }, 1000);
      
    } catch (err) {
      setPendingFiles(prev => prev.map(f => 
        f.status === 'pending' 
          ? { ...f, status: 'error', message: 'Upload failed' }
          : f
      ));
    } finally {
      setIsUploading(false);
    }
  };
  
  // Auto-upload when files are added
  React.useEffect(() => {
    const pending = pendingFiles.filter(f => f.status === 'pending');
    if (pending.length > 0 && !isUploading) {
      uploadFiles();
    }
  }, [pendingFiles, isUploading]);
  
  return (
    <div className="space-y-2">
      {/* Drop Zone */}
      <div
        onDragEnter={handleDragEnter}
        onDragLeave={handleDragLeave}
        onDragOver={handleDragOver}
        onDrop={handleDrop}
        onClick={() => fileInputRef.current?.click()}
        className={`
          relative border-2 border-dashed rounded-lg p-4 cursor-pointer
          transition-all duration-200 text-center
          ${isDragging 
            ? 'border-primary-400 bg-primary-400/5' 
            : 'border-dark-600 hover:border-primary-400/50 hover:bg-white/5'
          }
        `}
      >
        <div className={`w-8 h-8 rounded-full flex items-center justify-center mx-auto mb-2
                        ${isDragging ? 'bg-primary-400/20 text-primary-400' : 'bg-dark-700 text-dark-400'}`}>
          <Upload className="w-4 h-4" />
        </div>
        <p className="text-sm text-dark-300">
          {isDragging ? 'Drop files here' : 'Drop or click to add'}
        </p>
        <p className="text-xs text-dark-500 mt-1">
          {validExtensions.join(', ')}
        </p>
      </div>
      
      {/* Existing Files */}
      {files.length > 0 && (
        <div className="space-y-1">
          {files.map((name, i) => (
            <div
              key={i}
              className="flex items-center gap-2 px-2 py-1.5 rounded bg-dark-700/50 text-sm"
            >
              <File className="w-3.5 h-3.5 text-dark-400" />
              <span className="text-dark-200 truncate flex-1">{name}</span>
              <CheckCircle className="w-3.5 h-3.5 text-green-400" />
            </div>
          ))}
        </div>
      )}
      
      {/* Pending Files */}
      {pendingFiles.length > 0 && (
        <div className="space-y-1">
          {pendingFiles.map((f, i) => (
            <div
              key={i}
              className={`flex items-center gap-2 px-2 py-1.5 rounded text-sm
                         ${f.status === 'error' ? 'bg-red-500/10' : 
                           f.status === 'success' ? 'bg-green-500/10' : 'bg-dark-700'}`}
            >
              {f.status === 'pending' && <Loader2 className="w-3.5 h-3.5 text-primary-400 animate-spin" />}
              {f.status === 'uploading' && <Loader2 className="w-3.5 h-3.5 text-primary-400 animate-spin" />}
              {f.status === 'success' && <CheckCircle className="w-3.5 h-3.5 text-green-400" />}
              {f.status === 'error' && <AlertCircle className="w-3.5 h-3.5 text-red-400" />}
              <span className={`truncate flex-1 ${f.status === 'error' ? 'text-red-400' : 'text-dark-200'}`}>
                {f.file.name}
              </span>
              {f.message && (
                <span className="text-xs text-red-400">({f.message})</span>
              )}
              {f.status === 'pending' && (
                <button onClick={(e) => { e.stopPropagation(); removeFile(i); }} className="p-0.5 hover:bg-white/10 rounded">
                  <X className="w-3 h-3 text-dark-400" />
                </button>
              )}
            </div>
          ))}
        </div>
      )}
      
      <input
        ref={fileInputRef}
        type="file"
        multiple
        accept={validExtensions.join(',')}
        onChange={handleFileSelect}
        className="hidden"
      />
    </div>
  );
};

export default StudioDropZone;
