import React, { useState, useEffect, useRef } from "react";
import { Attachment, attachmentApi } from "@/services/attachmentApi";
import { Button } from "@/components/ui/button";
import { 
  Card, 
  CardContent, 
  CardDescription, 
  CardHeader, 
  CardTitle, 
  CardFooter 
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { 
  FileUp, 
  Download, 
  Trash2, 
  File, 
  FileText, 
  Image, 
  Film, 
  Music, 
  Archive, 
  FileX,
  Loader2,
  Plus,
  Eye,
  Info
} from "lucide-react";
import { toast } from "sonner";
import { Badge } from "../ui/badge";
import { cn } from "@/lib/utils";
import { Progress } from "@/components/ui/progress";
import AttachmentViewerDialog from "./AttachmentViewerDialog";
import UploadAttachmentDialog, { FileUploadData } from "./UploadAttachmentDialog";

interface TaskAttachmentsSectionProps {
  taskId: number;
  entityType?: "Task" | "Issue" | "Project";
}

const TaskAttachmentsSection: React.FC<TaskAttachmentsSectionProps> = ({ 
  taskId, 
  entityType = "Task" 
}) => {
  const [attachments, setAttachments] = useState<Attachment[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [downloadingFiles, setDownloadingFiles] = useState<Record<number, boolean>>({});
  const [downloadProgress, setDownloadProgress] = useState<Record<number, number>>({});
  const [downloadSizes, setDownloadSizes] = useState<Record<number, number>>({});
  const [viewerOpen, setViewerOpen] = useState(false);
  const [selectedAttachment, setSelectedAttachment] = useState<Attachment | null>(null);
  // New states for the upload dialog
  const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
  const [selectedFiles, setSelectedFiles] = useState<FileUploadData[]>([]);
  const desktopFileInputRef = useRef<HTMLInputElement>(null);
  const mobileFileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (taskId) {
      fetchAttachments();
    }
  }, [taskId, entityType]);

  const fetchAttachments = async () => {
    try {
      setIsLoading(true);
      const data = await attachmentApi.getByEntityTypeAndId(entityType, taskId);
      setAttachments(data);
    } catch (error) {
      console.error(`Error fetching attachments for ${entityType}:`, error);
      toast.error(`Failed to load attachments for ${entityType}`);
    } finally {
      setIsLoading(false);
    }
  };

  // Handle file selection for the upload dialog
  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    if (!files || files.length === 0) return;
    
    // Convert FileList to array of FileUploadData
    const newFiles = Array.from(files).map(file => ({
      file,
      description: ""
    }));
    
    setSelectedFiles(newFiles);
    setUploadDialogOpen(true);
    
    // Reset the file input
    if (e.target === desktopFileInputRef.current) {
      desktopFileInputRef.current.value = "";
    } else if (e.target === mobileFileInputRef.current) {
      mobileFileInputRef.current.value = "";
    }
  };

  // Update description for a file
  const updateFileDescription = (index: number, description: string) => {
    setSelectedFiles(prev => {
      const updated = [...prev];
      updated[index] = { ...updated[index], description };
      return updated;
    });
  };

  // Handle the actual file upload
  const handleUploadFiles = async () => {
    if (selectedFiles.length === 0) return;
    
    try {
      setIsUploading(true);
      
      for (const fileData of selectedFiles) {
        const { file, description } = fileData;
        const formData = new FormData();
        
        // Add file data
        formData.append("AttachmentId", "0");
        formData.append("FileName", file.name);
        formData.append("FileType", file.type || getFileExtension(file.name));
        formData.append("FilePath", ""); // Server will set this
        formData.append("EntityType", entityType);
        formData.append("EntityId", taskId.toString());
        formData.append("Description", description); // Add description
        formData.append("_IFormFile", file);
        
        await attachmentApi.upload(formData);
      }
      
      // Refresh the list after upload
      fetchAttachments();
      toast.success("File(s) uploaded successfully");
      
      // Reset state
      setSelectedFiles([]);
      setUploadDialogOpen(false);
      
    } catch (error) {
      console.error("Error uploading file:", error);
      toast.error("Failed to upload file");
    } finally {
      setIsUploading(false);
    }
  };

  const handleDeleteAttachment = async (attachmentId: number) => {
    if (window.confirm("Are you sure you want to delete this attachment?")) {
      try {
        await attachmentApi.delete(attachmentId);
        setAttachments(attachments.filter(a => a.attachmentId !== attachmentId));
        toast.success("Attachment deleted successfully");
      } catch (error) {
        console.error("Error deleting attachment:", error);
        toast.error("Failed to delete attachment");
      }
    }
  };

  const handleDownload = async (attachment: Attachment) => {
    try {
      // Set this file as downloading and reset progress
      setDownloadingFiles(prev => ({ ...prev, [attachment.attachmentId]: true }));
      setDownloadProgress(prev => ({ ...prev, [attachment.attachmentId]: 0 }));
      setDownloadSizes(prev => ({ ...prev, [attachment.attachmentId]: 0 }));
      
      // Show loading toast
      const toastId = toast.loading(`Downloading ${attachment.fileName}...`, {
        position: 'bottom-center'
      });
      
      // Progress tracking callback
      const onProgress = (progress: number, totalSize: number) => {
        setDownloadProgress(prev => ({ ...prev, [attachment.attachmentId]: progress }));
        setDownloadSizes(prev => ({ ...prev, [attachment.attachmentId]: totalSize }));
      };
      
      // Use the enhanced downloadAndSave method directly with progress callback
      await attachmentApi.downloadAndSave(attachment.attachmentId, onProgress);
      
      // Dismiss the loading toast and show success
      toast.dismiss(toastId);
      toast.success(`File downloaded successfully`, {
        position: 'bottom-center',
        duration: 2000
      });
    } catch (error) {
      console.error('Error downloading file:', error);
      toast.error('Failed to download attachment', {
        position: 'bottom-center'
      });
    } finally {
      // Clear downloading state for this file
      setDownloadingFiles(prev => {
        const newState = { ...prev };
        delete newState[attachment.attachmentId];
        return newState;
      });
      setDownloadProgress(prev => {
        const newState = { ...prev };
        delete newState[attachment.attachmentId];
        return newState;
      });
      setDownloadSizes(prev => {
        const newState = { ...prev };
        delete newState[attachment.attachmentId];
        return newState;
      });
    }
  };

  const handleViewAttachment = (attachment: Attachment) => {
    setSelectedAttachment(attachment);
    setViewerOpen(true);
  };

  // Helper to get file extension from filename
  const getFileExtension = (filename: string): string => {
    return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
  };

  // Helper to get file icon based on file type
  const getFileIcon = (attachment: Attachment) => {
    const fileType = attachment.fileType.toLowerCase();
    
    if (fileType.includes('image') || fileType.includes('.jpg') || fileType.includes('.jpeg') || 
        fileType.includes('.png') || fileType.includes('.gif') || fileType.includes('.webp')) {
      return <Image className="h-5 w-5 text-purple-500" />;
    } 
    
    if (fileType.includes('pdf')) {
      return <FileText className="h-5 w-5 text-red-500" />;
    }
    
    if (fileType.includes('word') || fileType.includes('.doc') || fileType.includes('.docx')) {
      return <FileText className="h-5 w-5 text-blue-500" />;
    }
    
    if (fileType.includes('excel') || fileType.includes('.xls') || fileType.includes('.xlsx')) {
      return <FileText className="h-5 w-5 text-green-500" />;
    }
    
    if (fileType.includes('video') || fileType.includes('.mp4') || fileType.includes('.mov')) {
      return <Film className="h-5 w-5 text-orange-500" />;
    }
    
    if (fileType.includes('audio') || fileType.includes('.mp3') || fileType.includes('.wav')) {
      return <Music className="h-5 w-5 text-blue-500" />;
    }
    
    if (fileType.includes('zip') || fileType.includes('.rar') || fileType.includes('.7z')) {
      return <Archive className="h-5 w-5 text-yellow-500" />;
    }
    
    return <File className="h-5 w-5 text-gray-500" />;
  };

  // Helper to format file size
  const formatFileSize = (bytes: number): string => {
    if (!bytes) return 'Unknown size';
    
    const units = ['B', 'KB', 'MB', 'GB'];
    let size = bytes;
    let unitIndex = 0;
    
    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }
    
    return `${size.toFixed(1)} ${units[unitIndex]}`;
  };

  // Helper to format file name for display
  const formatDisplayName = (fileName: string, maxLength: number = 30): string => {
    if (fileName.length <= maxLength) return fileName;
    
    const extension = fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 1);
    const nameWithoutExt = fileName.substring(0, fileName.lastIndexOf("."));
    
    if (extension.length + 5 >= maxLength) {
      return `${nameWithoutExt.slice(0, maxLength - 10)}...${extension}`;
    }
    
    const charsToCut = fileName.length - maxLength + 3;
    return `${nameWithoutExt.slice(0, nameWithoutExt.length - charsToCut)}...${extension}`;
  };

  // Helper to determine a shorter max length for mobile screens
  const getResponsiveMaxLength = (): number => {
    if (typeof window !== 'undefined') {
      return window.innerWidth < 640 ? 15 : 30;
    }
    return 30;
  };

  return (
    <div className="w-full">
      {/* Attachment Viewer Dialog */}
      <AttachmentViewerDialog 
        isOpen={viewerOpen}
        onClose={() => {
          setViewerOpen(false);
          setSelectedAttachment(null);
        }}
        attachment={selectedAttachment}
        onDownload={handleDownload}
      />

      {/* Custom Upload Dialog */}
      <UploadAttachmentDialog
        isOpen={uploadDialogOpen}
        onClose={() => setUploadDialogOpen(false)}
        selectedFiles={selectedFiles}
        onUpdateDescription={updateFileDescription}
        onUpload={handleUploadFiles}
        isUploading={isUploading}
        entityType={entityType}
      />

      {/* Fixed Action Button for Mobile */}
      <div className="sm:hidden fixed bottom-6 right-6 z-10">
        <Label htmlFor="mobile-file-upload" className="cursor-pointer">
          <div className="h-14 w-14 rounded-full bg-primary text-primary-foreground flex items-center justify-center shadow-lg">
            <Plus className="h-6 w-6" />
          </div>
          <Input 
            id="mobile-file-upload"
            ref={mobileFileInputRef}
            type="file" 
            multiple
            className="hidden" 
            onChange={handleFileSelect}
            disabled={isUploading}
          />
        </Label>
      </div>

      <Card className="shadow-sm border">
        <CardHeader className="pb-3">
          <div className="flex justify-between items-center">
            <CardTitle className="text-xl flex items-center gap-2">
              <FileText className="h-5 w-5" />
              Attachments
            </CardTitle>
            <div className="hidden sm:block">
              <Label htmlFor="desktop-file-upload" className="cursor-pointer">
                <div className={cn(
                  "flex items-center gap-2 px-3 py-1.5 rounded-md text-sm border",
                  isUploading 
                    ? "bg-muted text-muted-foreground" 
                    : "bg-white hover:bg-accent transition-colors"
                )}>
                  {isUploading ? (
                    <>
                      <Loader2 className="h-4 w-4 animate-spin" />
                      <span>Uploading...</span>
                    </>
                  ) : (
                    <>
                      <FileUp className="h-4 w-4" />
                      <span>Upload</span>
                    </>
                  )}
                </div>
                <Input 
                  id="desktop-file-upload"
                  ref={desktopFileInputRef}
                  type="file" 
                  multiple
                  className="hidden" 
                  onChange={handleFileSelect}
                  disabled={isUploading}
                />
              </Label>
            </div>
          </div>
          <CardDescription>
            Files and documents related to this {entityType.toLowerCase()}
          </CardDescription>
        </CardHeader>
        
        <CardContent>
          {isLoading ? (
            <div className="flex justify-center items-center py-8">
              <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
            </div>
          ) : attachments.length === 0 ? (
            <div className="text-center py-8 border border-dashed rounded-lg flex flex-col items-center">
              <FileX className="h-10 w-10 text-muted-foreground mb-2" />
              <p className="text-sm text-muted-foreground mb-2">No attachments yet</p>
              <Label htmlFor="empty-file-upload" className="cursor-pointer sm:block hidden">
                <div className="bg-primary text-primary-foreground px-4 py-2 rounded-md text-sm hover:bg-primary/90 transition-colors">
                  Upload Files
                </div>
                <Input 
                  id="empty-file-upload"
                  type="file" 
                  multiple
                  className="hidden" 
                  onChange={handleFileSelect}
                  disabled={isUploading}
                />
              </Label>
              <p className="text-xs text-muted-foreground mt-2 sm:hidden">
                Tap the + button to upload files
              </p>
            </div>
          ) : (
            <div className="space-y-4">
              <div className="grid gap-3">
                {attachments.map((attachment) => (
                  <div 
                    key={attachment.attachmentId} 
                    className={cn(
                      "flex items-center justify-between border rounded-lg p-3 bg-card transition-colors",
                      downloadingFiles[attachment.attachmentId] 
                        ? "bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800" 
                        : "hover:bg-accent/50"
                    )}
                  >
                    <div 
                      className="flex items-center gap-2 sm:gap-3 overflow-hidden flex-1 min-w-0 cursor-pointer"
                      onClick={() => handleViewAttachment(attachment)}
                    >
                      <div className={cn(
                        "p-2 rounded-md flex-shrink-0",
                        downloadingFiles[attachment.attachmentId] 
                          ? "bg-blue-100 dark:bg-blue-800/30" 
                          : "bg-accent"
                      )}>
                        {downloadingFiles[attachment.attachmentId] ? (
                          <Loader2 className="h-5 w-5 text-blue-600 dark:text-blue-400 animate-spin" />
                        ) : (
                          getFileIcon(attachment)
                        )}
                      </div>
                      <div className="min-w-0 flex-1">
                        <p className="font-medium text-sm truncate" title={attachment.fileName}>
                          {formatDisplayName(attachment.fileName, getResponsiveMaxLength())}
                        </p>
                        
                        {/* Display the description if it exists */}
                        {attachment.description && (
                          <p className="text-xs text-muted-foreground mt-0.5 truncate" title={attachment.description}>
                            <Info className="h-3 w-3 inline mr-1" />
                            {attachment.description}
                          </p>
                        )}
                        
                        <div className="flex items-center gap-2 mt-1">
                          <Badge variant="secondary" className={cn(
                            "px-1.5 py-0 h-5 text-xs",
                            downloadingFiles[attachment.attachmentId] 
                              ? "bg-blue-100 dark:bg-blue-800/30 text-blue-600 dark:text-blue-400" 
                              : "bg-accent"
                          )}>
                            {downloadingFiles[attachment.attachmentId] ? "Downloading..." : attachment.fileType || getFileExtension(attachment.fileName)}
                          </Badge>
                          
                          {!downloadingFiles[attachment.attachmentId] && (
                            <span className="text-xs text-muted-foreground">
                              {attachment.createdBy && `Added by ${attachment.createdBy}`}
                              {attachment.createdAt && attachment.createdBy && ' · '}
                              {attachment.createdAt && new Date(attachment.createdAt).toLocaleDateString(undefined, {
                                year: 'numeric',
                                month: 'short',
                                day: 'numeric'
                              })}
                            </span>
                          )}
                          
                          {downloadingFiles[attachment.attachmentId] && (
                            <div className="mt-2 w-full">
                              <Progress 
                                value={downloadProgress[attachment.attachmentId] || 0} 
                                className="h-1.5 bg-blue-100 dark:bg-blue-900/30" 
                              />
                              <div className="flex justify-between text-xs text-muted-foreground mt-1">
                                <span>{downloadProgress[attachment.attachmentId] || 0}%</span>
                                {downloadSizes[attachment.attachmentId] && (
                                  <span>{formatFileSize(downloadSizes[attachment.attachmentId])}</span>
                                )}
                              </div>
                            </div>
                          )}
                        </div>
                      </div>
                    </div>
                    <div className="flex items-center gap-1">
                      <Button 
                        variant="ghost" 
                        size="icon"
                        onClick={(e) => {
                          e.stopPropagation();
                          handleViewAttachment(attachment);
                        }}
                        title="View attachment"
                        className="h-8 w-8 text-blue-500 hover:text-blue-600 hover:bg-blue-50"
                        disabled={downloadingFiles[attachment.attachmentId]}
                      >
                        <Eye className="h-4 w-4" />
                      </Button>
                      <Button 
                        variant="ghost" 
                        size="icon"
                        onClick={(e) => {
                          e.stopPropagation();
                          handleDownload(attachment);
                        }}
                        title="Download file"
                        className="h-8 w-8 text-blue-500 hover:text-blue-600 hover:bg-blue-50"
                        disabled={downloadingFiles[attachment.attachmentId]}
                      >
                        {downloadingFiles[attachment.attachmentId] ? (
                          <Loader2 className="h-4 w-4 animate-spin" />
                        ) : (
                          <Download className="h-4 w-4" />
                        )}
                      </Button>
                      <Button 
                        variant="ghost" 
                        size="icon"
                        onClick={(e) => {
                          e.stopPropagation();
                          handleDeleteAttachment(attachment.attachmentId);
                        }}
                        title="Delete attachment"
                        className="h-8 w-8 text-red-500 hover:text-red-600 hover:bg-red-50"
                        disabled={downloadingFiles[attachment.attachmentId]}
                      >
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}
        </CardContent>
        
        <CardFooter className="border-t pt-4 flex justify-between">
          <div className="text-sm text-muted-foreground">
            {attachments.length} attachment{attachments.length !== 1 ? 's' : ''}
          </div>
          <Label htmlFor="footer-file-upload" className="cursor-pointer hidden sm:block">
            <div className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm border ${
              isUploading ? 'bg-muted text-muted-foreground' : 'bg-white hover:bg-accent transition-colors'
            }`}>
              {isUploading ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  <span>Uploading...</span>
                </>
              ) : (
                <>
                  <FileUp className="h-4 w-4" />
                  <span>Upload Files</span>
                </>
              )}
            </div>
            <Input 
              id="footer-file-upload"
              type="file" 
              multiple
              className="hidden" 
              onChange={handleFileSelect}
              disabled={isUploading}
            />
          </Label>
        </CardFooter>
      </Card>
    </div>
  );
};

export default TaskAttachmentsSection; 