import React, { useState, useCallback } from 'react';
import { Upload, FileText, Image, FileCode, Loader2, CheckCircle, XCircle, AlertCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
import { Badge } from '@/components/ui/badge';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

interface UploadedFile {
  id: string;
  file: File;
  status: 'pending' | 'uploading' | 'processing' | 'completed' | 'failed';
  progress: number;
  documentId?: number;
  error?: string;
}

interface Document {
  id: number;
  title: string;
  fileName: string;
  fileSize: number;
  mimeType: string;
  processingStatus: string;
  createdAt: string;
}

export default function DocumentUpload() {
  const [files, setFiles] = useState<UploadedFile[]>([]);
  const [isDragging, setIsDragging] = useState(false);
  const [uploadTitle, setUploadTitle] = useState('');
  const [uploadSource, setUploadSource] = useState('');
  const [documents, setDocuments] = useState<Document[]>([]);
  const [isProcessing, setIsProcessing] = useState(false);

  const acceptedTypes = [
    'application/pdf',
    'image/jpeg',
    'image/png', 
    'image/gif',
    'image/webp',
    'text/plain',
    'text/markdown',
    'application/json',
    'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
  ];

  const getFileIcon = (mimeType: string) => {
    if (mimeType.startsWith('image/')) return <Image className="w-5 h-5" />;
    if (mimeType === 'application/pdf') return <FileText className="w-5 h-5" />;
    if (mimeType.includes('text') || mimeType.includes('json')) return <FileCode className="w-5 h-5" />;
    return <FileText className="w-5 h-5" />;
  };

  const getStatusIcon = (status: string) => {
    switch (status) {
      case 'completed':
        return <CheckCircle className="w-4 h-4 text-green-500" />;
      case 'failed':
        return <XCircle className="w-4 h-4 text-red-500" />;
      case 'processing':
      case 'uploading':
        return <Loader2 className="w-4 h-4 text-blue-500 animate-spin" />;
      default:
        return <AlertCircle className="w-4 h-4 text-yellow-500" />;
    }
  };

  const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };

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

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

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

  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      const selectedFiles = Array.from(e.target.files);
      handleFiles(selectedFiles);
    }
  };

  const handleFiles = (newFiles: File[]) => {
    const validFiles = newFiles.filter(file => {
      if (!acceptedTypes.includes(file.type)) {
        alert(`File type ${file.type} is not supported`);
        return false;
      }
      if (file.size > 50 * 1024 * 1024) { // 50MB limit
        alert(`File ${file.name} is too large. Maximum size is 50MB`);
        return false;
      }
      return true;
    });

    const uploadFiles: UploadedFile[] = validFiles.map(file => ({
      id: `${Date.now()}-${Math.random()}`,
      file,
      status: 'pending',
      progress: 0
    }));

    setFiles(prev => [...prev, ...uploadFiles]);
  };

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

    for (const uploadFile of pendingFiles) {
      try {
        // Update status to uploading
        setFiles(prev => prev.map(f => 
          f.id === uploadFile.id 
            ? { ...f, status: 'uploading', progress: 0 }
            : f
        ));

        const formData = new FormData();
        formData.append('files', uploadFile.file);
        if (uploadTitle) formData.append('title', uploadTitle);
        if (uploadSource) formData.append('source', uploadSource);

        const response = await fetch('/api/documents/upload', {
          method: 'POST',
          body: formData,
        });

        if (!response.ok) {
          throw new Error(`Upload failed: ${response.statusText}`);
        }

        const result = await response.json();
        
        if (result.success && result.documents?.length > 0) {
          const document = result.documents[0];
          
          // Update file status to processing
          setFiles(prev => prev.map(f => 
            f.id === uploadFile.id 
              ? { 
                  ...f, 
                  status: 'processing', 
                  progress: 100,
                  documentId: document.id 
                }
              : f
          ));

          // Add to documents list
          setDocuments(prev => [document, ...prev]);

          // If file requires processing, start processing
          if (document.processingStatus === 'pending') {
            await processDocument(document.id, uploadFile.id);
          } else {
            // Mark as completed if no processing needed
            setFiles(prev => prev.map(f => 
              f.id === uploadFile.id 
                ? { ...f, status: 'completed' }
                : f
            ));
          }
        } else {
          throw new Error(result.message || 'Upload failed');
        }

      } catch (error) {
        console.error('Upload error:', error);
        setFiles(prev => prev.map(f => 
          f.id === uploadFile.id 
            ? { 
                ...f, 
                status: 'failed', 
                error: error instanceof Error ? error.message : 'Upload failed'
              }
            : f
        ));
      }
    }
  };

  const processDocument = async (documentId: number, fileId: string) => {
    try {
      const response = await fetch(`/api/documents/process/${documentId}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          operations: ['extract_text', 'generate_embedding']
        })
      });

      const result = await response.json();

      if (result.success) {
        // Update file status to completed
        setFiles(prev => prev.map(f => 
          f.id === fileId 
            ? { ...f, status: 'completed' }
            : f
        ));

        // Update document in list
        setDocuments(prev => prev.map(doc => 
          doc.id === documentId 
            ? { ...doc, processingStatus: 'completed' }
            : doc
        ));
      } else {
        throw new Error(result.message || 'Processing failed');
      }

    } catch (error) {
      console.error('Processing error:', error);
      setFiles(prev => prev.map(f => 
        f.id === fileId 
          ? { 
              ...f, 
              status: 'failed', 
              error: error instanceof Error ? error.message : 'Processing failed'
            }
          : f
      ));
    }
  };

  const batchProcessDocuments = async () => {
    const completedDocuments = documents.filter(doc => doc.processingStatus === 'completed');
    if (completedDocuments.length === 0) {
      alert('No processed documents available for batch operations');
      return;
    }

    setIsProcessing(true);
    
    try {
      // Build vector index
      const response = await fetch('/api/documents/index/build', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          documentIds: completedDocuments.map(doc => doc.id),
          indexName: 'main_index'
        })
      });

      const result = await response.json();

      if (result.success) {
        alert(`Vector index built successfully with ${result.documentCount} documents`);
      } else {
        throw new Error(result.message || 'Index building failed');
      }

    } catch (error) {
      console.error('Batch processing error:', error);
      alert(`Batch processing failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    } finally {
      setIsProcessing(false);
    }
  };

  const removeFile = (fileId: string) => {
    setFiles(prev => prev.filter(f => f.id !== fileId));
  };

  const clearCompleted = () => {
    setFiles(prev => prev.filter(f => f.status !== 'completed' && f.status !== 'failed'));
  };

  return (
    <div className="space-y-6">
      {/* Upload Area */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <Upload className="w-5 h-5" />
            Document Upload
          </CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          {/* Optional metadata */}
          <div className="grid grid-cols-2 gap-4">
            <div>
              <Label htmlFor="title">Title (optional)</Label>
              <Input
                id="title"
                placeholder="Document title"
                value={uploadTitle}
                onChange={(e) => setUploadTitle(e.target.value)}
              />
            </div>
            <div>
              <Label htmlFor="source">Source (optional)</Label>
              <Input
                id="source"
                placeholder="Document source"
                value={uploadSource}
                onChange={(e) => setUploadSource(e.target.value)}
              />
            </div>
          </div>

          {/* Drag and drop area */}
          <div
            className={`
              border-2 border-dashed rounded-lg p-8 text-center transition-colors
              ${isDragging 
                ? 'border-blue-500 bg-blue-50 dark:bg-blue-950' 
                : 'border-gray-300 hover:border-gray-400 dark:border-gray-600'
              }
            `}
            onDragOver={handleDragOver}
            onDragLeave={handleDragLeave}
            onDrop={handleDrop}
          >
            <Upload className="w-12 h-12 mx-auto text-gray-400 mb-4" />
            <p className="text-lg font-medium mb-2">
              Drop files here or click to browse
            </p>
            <p className="text-sm text-gray-500 mb-4">
              Supports PDF, images, text files, Word documents (max 50MB each)
            </p>
            <input
              type="file"
              multiple
              accept={acceptedTypes.join(',')}
              onChange={handleFileSelect}
              className="hidden"
              id="file-upload"
            />
            <Button asChild variant="outline">
              <label htmlFor="file-upload" className="cursor-pointer">
                Browse Files
              </label>
            </Button>
          </div>

          {/* File list */}
          {files.length > 0 && (
            <div className="space-y-2">
              <div className="flex justify-between items-center">
                <h3 className="font-medium">Files ({files.length})</h3>
                <div className="space-x-2">
                  <Button onClick={uploadFiles} size="sm" disabled={!files.some(f => f.status === 'pending')}>
                    Upload All
                  </Button>
                  <Button onClick={clearCompleted} variant="outline" size="sm">
                    Clear Completed
                  </Button>
                </div>
              </div>

              {files.map((file) => (
                <div key={file.id} className="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800 rounded-lg">
                  <div className="flex items-center gap-3 flex-1">
                    {getFileIcon(file.file.type)}
                    <div className="flex-1 min-w-0">
                      <p className="font-medium truncate">{file.file.name}</p>
                      <p className="text-sm text-gray-500">
                        {formatFileSize(file.file.size)}
                      </p>
                    </div>
                  </div>

                  <div className="flex items-center gap-3">
                    <Badge variant={
                      file.status === 'completed' ? 'default' :
                      file.status === 'failed' ? 'destructive' : 
                      'secondary'
                    }>
                      {file.status}
                    </Badge>
                    
                    {getStatusIcon(file.status)}
                    
                    {(file.status === 'uploading' || file.status === 'processing') && (
                      <div className="w-24">
                        <Progress value={file.progress} className="h-2" />
                      </div>
                    )}

                    {(file.status === 'pending' || file.status === 'failed') && (
                      <Button 
                        variant="ghost" 
                        size="sm"
                        onClick={() => removeFile(file.id)}
                      >
                        <XCircle className="w-4 h-4" />
                      </Button>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}

          {/* Error alerts */}
          {files.some(f => f.error) && (
            <Alert variant="destructive">
              <AlertCircle className="w-4 h-4" />
              <AlertDescription>
                Some files failed to upload. Check individual file status above.
              </AlertDescription>
            </Alert>
          )}
        </CardContent>
      </Card>

      {/* Document Management */}
      {documents.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle className="flex items-center justify-between">
              <span>Uploaded Documents ({documents.length})</span>
              <Button 
                onClick={batchProcessDocuments}
                disabled={isProcessing || documents.filter(d => d.processingStatus === 'completed').length === 0}
              >
                {isProcessing ? (
                  <>
                    <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                    Building Index...
                  </>
                ) : (
                  'Build Vector Index'
                )}
              </Button>
            </CardTitle>
          </CardHeader>
          <CardContent>
            <div className="space-y-2">
              {documents.map((doc) => (
                <div key={doc.id} className="flex items-center justify-between p-3 border rounded-lg">
                  <div className="flex items-center gap-3 flex-1">
                    {getFileIcon(doc.mimeType)}
                    <div className="flex-1 min-w-0">
                      <p className="font-medium truncate">{doc.title}</p>
                      <p className="text-sm text-gray-500">
                        {doc.fileName} • {formatFileSize(doc.fileSize)}
                      </p>
                    </div>
                  </div>

                  <div className="flex items-center gap-3">
                    <Badge variant={
                      doc.processingStatus === 'completed' ? 'default' :
                      doc.processingStatus === 'failed' ? 'destructive' : 
                      'secondary'
                    }>
                      {doc.processingStatus}
                    </Badge>
                    {getStatusIcon(doc.processingStatus)}
                  </div>
                </div>
              ))}
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}