import React, { useState, useRef, useEffect } from 'react';
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { FileUp, Loader2, File, FileText, Image, Film, Music, Archive, ChevronDown, Search, HelpCircle } from "lucide-react";
import CustomDialog from '@/components/CustomDialog';
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";

export interface FileUploadData {
  file: File;
  description: string;
  documentType?: string; // Optional document type field
}

// Document type interface
export interface DocumentType {
  name: string;
  description: string;
}

interface UploadAttachmentDialogProps {
  isOpen: boolean;
  onClose: () => void;
  selectedFiles: FileUploadData[];
  onUpdateDescription: (index: number, description: string) => void;
  onUpdateDocumentType?: (index: number, documentType: string) => void; // Optional handler for document type
  onUpload: () => void;
  isUploading: boolean;
  entityType: string;
  documentTypes?: DocumentType[] | string[]; // Can accept either structure
}

/**
 * A custom dialog component for uploading attachments with descriptions
 */
const UploadAttachmentDialog: React.FC<UploadAttachmentDialogProps> = ({
  isOpen,
  onClose,
  selectedFiles,
  onUpdateDescription,
  onUpdateDocumentType,
  onUpload,
  isUploading,
  entityType,
  documentTypes = []
}) => {
  // State for custom dropdowns
  const [openDropdowns, setOpenDropdowns] = useState<Record<number, boolean>>({});
  const dropdownRefs = useRef<Record<number, HTMLDivElement | null>>({});
  const [dropdownPositions, setDropdownPositions] = useState<Record<number, 'top' | 'bottom'>>({});
  const [dropdownWidths, setDropdownWidths] = useState<Record<number, number>>({});
  const [searchQueries, setSearchQueries] = useState<Record<number, string>>({});

  // Check if documentTypes has the new structure
  const hasDetailedDocTypes = documentTypes.length > 0 &&
    typeof documentTypes[0] !== 'string' &&
    'name' in documentTypes[0];

  // 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 = (file: File) => {
    const fileType = file.type.toLowerCase();
    const fileName = file.name.toLowerCase();

    if (fileType.includes('image') || fileName.match(/\.(jpg|jpeg|png|gif|webp)$/i)) {
      return <Image className="h-5 w-5 text-purple-500" />;
    }

    if (fileType.includes('pdf') || fileName.endsWith('.pdf')) {
      return <FileText className="h-5 w-5 text-red-500" />;
    }

    if (fileType.includes('word') || fileName.match(/\.(doc|docx)$/i)) {
      return <FileText className="h-5 w-5 text-blue-500" />;
    }

    if (fileType.includes('excel') || fileName.match(/\.(xls|xlsx)$/i)) {
      return <FileText className="h-5 w-5 text-green-500" />;
    }

    if (fileType.includes('video') || fileName.match(/\.(mp4|mov|avi|wmv)$/i)) {
      return <Film className="h-5 w-5 text-orange-500" />;
    }

    if (fileType.includes('audio') || fileName.match(/\.(mp3|wav|ogg)$/i)) {
      return <Music className="h-5 w-5 text-blue-500" />;
    }

    if (fileType.includes('zip') || fileName.match(/\.(zip|rar|7z|tar|gz)$/i)) {
      return <Archive className="h-5 w-5 text-yellow-500" />;
    }

    return <File className="h-5 w-5 text-gray-500" />;
  };

  const handleCancel = () => {
    if (!isUploading) {
      onClose();
    }
  };

  // Get normalized document types for filtering
  const getNormalizedDocTypes = (): Array<{ name: string, description: string }> => {
    if (hasDetailedDocTypes) {
      return documentTypes as DocumentType[];
    } else {
      return (documentTypes as string[]).map(name => ({
        name,
        description: ""
      }));
    }
  };

  // Determine dropdown position when toggling open
  const toggleDropdown = (index: number) => {
    if (isUploading) return;

    if (!openDropdowns[index]) {
      // Only calculate position when opening
      const dropdownRef = dropdownRefs.current[index];
      if (dropdownRef) {
        const rect = dropdownRef.getBoundingClientRect();
        const spaceBelow = window.innerHeight - rect.bottom;
        const requiredSpace = Math.min(documentTypes.length * 28, 200) + 50; // Extra space for search box

        setDropdownPositions(prev => ({
          ...prev,
          [index]: spaceBelow < requiredSpace ? 'top' : 'bottom'
        }));

        // Store the exact width
        setDropdownWidths(prev => ({
          ...prev,
          [index]: rect.width
        }));
      }
    }

    setOpenDropdowns(prev => ({
      ...prev,
      [index]: !prev[index]
    }));

    // Reset search when opening
    if (!openDropdowns[index]) {
      setSearchQueries(prev => ({
        ...prev,
        [index]: ''
      }));
    }
  };

  // Update search query
  const handleSearchChange = (index: number, value: string) => {
    setSearchQueries(prev => ({
      ...prev,
      [index]: value
    }));
  };

  // Handle selecting a document type
  const handleSelectDocumentType = (index: number, type: string) => {
    if (onUpdateDocumentType) {
      onUpdateDocumentType(index, type);
    }

    // Close the dropdown
    setOpenDropdowns(prev => ({
      ...prev,
      [index]: false
    }));
  };

  // Filter document types based on search query
  const getFilteredDocumentTypes = (index: number) => {
    const query = searchQueries[index] || '';
    const normalizedDocTypes = getNormalizedDocTypes();

    if (!query) return normalizedDocTypes;

    return normalizedDocTypes.filter(docType =>
      docType.name.toLowerCase().includes(query.toLowerCase()) ||
      docType.description.toLowerCase().includes(query.toLowerCase())
    );
  };

  // Get document type name to display in dropdown
  const getDocumentTypeDisplay = (fileData: FileUploadData) => {
    if (!fileData.documentType) return "Select document type";

    // If using new structure, find the matching document type
    if (hasDetailedDocTypes) {
      const docTypes = documentTypes as DocumentType[];
      const foundType = docTypes.find(dt => dt.name === fileData.documentType);
      return foundType ? foundType.name : fileData.documentType;
    }

    return fileData.documentType;
  };

  // Close dropdowns when clicking outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      Object.entries(dropdownRefs.current).forEach(([indexStr, ref]) => {
        const index = parseInt(indexStr);
        if (ref && !ref.contains(event.target as Node) && openDropdowns[index]) {
          setOpenDropdowns(prev => ({
            ...prev,
            [index]: false
          }));
        }
      });
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [openDropdowns]);

  // Determine if we should show document type selection
  const showDocumentTypes = documentTypes.length > 0 && onUpdateDocumentType;

  // Validation: Check if all files have a description and at least one file is selected
  const isFormValid = selectedFiles.length > 0 &&
    selectedFiles.every(fileData => fileData.description.trim() !== '');

  return (
    <CustomDialog
      isOpen={isOpen}
      onClose={handleCancel}
      title={`Upload ${entityType} Documents`}
      description={`Add files to this ${entityType.toLowerCase()}. You can provide a description for each file.`}
      allowClose={!isUploading}
      isPending={isUploading}
    >
      <div className="space-y-4 py-2">
        {selectedFiles.map((fileData, index) => (
          <div key={index} className="space-y-2 border rounded-lg p-3 relative">
            <div className="flex items-center gap-2">
              {getFileIcon(fileData.file)}
              <span className="text-sm font-medium">{fileData.file.name}</span>
              <span className="text-xs text-muted-foreground ml-auto">
                {(fileData.file.size / 1024).toFixed(1)} KB
              </span>
            </div>

            {/* Custom Document Type Dropdown - Only show if document types are provided */}
            {showDocumentTypes && (
              <div className="space-y-1">
                <Label htmlFor={`doctype-${index}`} className="text-xs">Document Type</Label>
                <div
                  ref={ref => dropdownRefs.current[index] = ref}
                  className="relative"
                >
                  <div
                    className={cn(
                      "flex items-center justify-between rounded-md border border-input px-3 py-2 text-sm ring-offset-background",
                      isUploading ? "bg-muted text-muted-foreground" : "bg-transparent",
                      "cursor-pointer select-none"
                    )}
                    onClick={() => toggleDropdown(index)}
                    id={`doctype-${index}`}
                  >
                    <span className={fileData.documentType ? "text-foreground" : "text-muted-foreground"}>
                      {getDocumentTypeDisplay(fileData)}
                    </span>
                    <ChevronDown className="h-4 w-4 opacity-50" />
                  </div>

                  {openDropdowns[index] && (
                    <div
                      className={cn(
                        "fixed z-[1010] rounded-md border bg-popover shadow-md",
                        dropdownPositions[index] === 'top'
                          ? "bottom-full mb-1" // Position above the trigger
                          : "mt-1"    // Position below the trigger
                      )}
                      style={{
                        width: `${dropdownWidths[index]}px`,
                        maxHeight: '250px',
                        overflowY: 'auto',
                        left: dropdownRefs.current[index]?.getBoundingClientRect().left,
                        [dropdownPositions[index] === 'top' ? 'bottom' : 'top']:
                          dropdownPositions[index] === 'top'
                            ? window.innerHeight - dropdownRefs.current[index]?.getBoundingClientRect().top
                            : dropdownRefs.current[index]?.getBoundingClientRect().bottom
                      }}
                    >
                      <div className="p-2 border-b sticky top-0 bg-popover">
                        <div className="relative">
                          <Search className="absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                          <Input
                            placeholder="Search document types..."
                            value={searchQueries[index] || ''}
                            onChange={(e) => handleSearchChange(index, e.target.value)}
                            className="pl-8 h-8 text-sm"
                            onClick={(e) => e.stopPropagation()}
                          />
                        </div>
                      </div>

                      <div className="p-1">
                        {getFilteredDocumentTypes(index).length > 0 ? (
                          getFilteredDocumentTypes(index).map((docType) => (
                            <TooltipProvider key={docType.name} delayDuration={300}>
                              <Tooltip>
                                <TooltipTrigger asChild>
                                  <div
                                    className={cn(
                                      "flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
                                      "hover:bg-accent hover:text-accent-foreground",
                                      fileData.documentType === docType.name && "bg-accent/50"
                                    )}
                                    onClick={() => handleSelectDocumentType(index, docType.name)}
                                  >
                                    <span className="flex-1 truncate">{docType.name}</span>
                                    {docType.description && (
                                      <HelpCircle className="h-3.5 w-3.5 ml-1 text-muted-foreground opacity-70" />
                                    )}
                                  </div>
                                </TooltipTrigger>
                                {docType.description && (
                                  <TooltipContent className="max-w-xs p-2 text-xs" side="right">
                                    {docType.description}
                                  </TooltipContent>
                                )}
                              </Tooltip>
                            </TooltipProvider>
                          ))
                        ) : (
                          <div className="px-2 py-3 text-sm text-muted-foreground text-center">
                            No matching document types
                          </div>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              </div>
            )}

            <div className="space-y-1">
              <Label htmlFor={`desc-${index}`} className="text-xs ">Description <span className="text-red-500">*</span></Label>
              <Textarea
                id={`desc-${index}`}
                placeholder="Add a description for this file..."
                value={fileData.description}
                onChange={(e) => onUpdateDescription(index, e.target.value)}
                className="resize-none h-20 text-sm"
                disabled={isUploading}
              />
            </div>
            <div>
              <p className="text-xs text-muted-foreground text-red-500 ">*Required</p>
            </div>
          </div>
        ))}
      </div>

      <div className="flex justify-end gap-2 mt-6 pt-4 border-t">
        <Button
          type="button"
          variant="outline"
          onClick={handleCancel}
          disabled={isUploading}
        >
          Cancel
        </Button>
        <Button
          type="button"
          onClick={onUpload}
          disabled={isUploading || !isFormValid}
          className="min-w-24"
        >
          {isUploading ? (
            <>
              <Loader2 className="h-4 w-4 animate-spin mr-2" />
              Uploading...
            </>
          ) : (
            <>
              <FileUp className="h-4 w-4 mr-2" />
              Upload
            </>
          )}
        </Button>
      </div>
    </CustomDialog>
  );
};

export default UploadAttachmentDialog; 