import { useState } from "react";
import { toast } from "sonner";
import { UnassignedImage, Product } from "../types";

type HandleImageUploadFn = (files: FileList | File[], productIndex: number) => Promise<{ uploaded: number; skipped: number }>;

interface UseBulkImageUploadProps {
  data: Product[];
  handleImageUpload: HandleImageUploadFn;
}

export const useBulkImageUpload = ({ data, handleImageUpload }: UseBulkImageUploadProps) => {
  const [unassignedImages, setUnassignedImages] = useState<UnassignedImage[]>([]);
  const [processingBulk, setProcessingBulk] = useState(false);
  const [showUnassigned, setShowUnassigned] = useState(false);

  // Function to extract identifiers from a filename
  const extractIdentifiers = (filename: string): string[] => {
    // Remove file extension and convert to lowercase
    const nameWithoutExt = filename.split('.').slice(0, -1).join('.').toLowerCase();
    
    // Split by common separators
    const parts = nameWithoutExt.split(/[-_\s.]+/);
    
    // Add the full name without extension as a possible identifier
    const identifiers = [nameWithoutExt];
    
    // Add parts with at least 3 characters
    identifiers.push(...parts.filter(part => part.length >= 3));
    
    // Look for potential UPC or product codes (digits only)
    const digitOnlyParts = parts.filter(part => /^\d+$/.test(part) && part.length >= 5);
    identifiers.push(...digitOnlyParts);
    
    // Look for product codes (mix of letters and digits)
    const productCodes = parts.filter(part => 
      /^[a-z0-9]+$/.test(part) && 
      /\d/.test(part) && 
      /[a-z]/.test(part) && 
      part.length >= 4
    );
    identifiers.push(...productCodes);
    
    return [...new Set(identifiers)]; // Remove duplicates
  };
  
  // Function to find product index by identifier
  const findProductByIdentifier = (identifier: string): number => {
    // Try to match against supplier_no, upc, SKU, or name
    return data.findIndex((product: Product) => {
      // Skip if product is missing all identifiers
      if (!product.supplier_no && !product.upc && !product.sku && !product.name) {
        return false;
      }
      
      const supplierNo = String(product.supplier_no || '').toLowerCase();
      const upc = String(product.upc || '').toLowerCase();
      const sku = String(product.sku || '').toLowerCase();
      const name = String(product.name || '').toLowerCase();
      const model = String(product.model || '').toLowerCase();
      
      // For exact matches, prioritize certain fields
      if (
        (supplierNo && identifier === supplierNo) ||
        (upc && identifier === upc) ||
        (sku && identifier === sku)
      ) {
        return true;
      }
      
      // For partial matches, check if the identifier is contained within the field
      // or if the field is contained within the identifier
      return (
        (supplierNo && (supplierNo.includes(identifier) || identifier.includes(supplierNo))) ||
        (upc && (upc.includes(identifier) || identifier.includes(upc))) ||
        (sku && (sku.includes(identifier) || identifier.includes(sku))) ||
        (model && (model.includes(identifier) || identifier.includes(model))) ||
        (name && name.includes(identifier))
      );
    });
  };
  
  // Function to create preview URLs for files
  const createPreviewUrl = (file: File): string => {
    return URL.createObjectURL(file);
  };
  
  // Function to handle bulk image upload
  const handleBulkUpload = async (files: File[]) => {
    if (!files.length) return;

    setProcessingBulk(true);
    const unassigned: UnassignedImage[] = [];
    let totalUploaded = 0;
    let totalSkipped = 0;

    for (const file of files) {
      // Extract identifiers from filename
      const identifiers = extractIdentifiers(file.name);
      let assigned = false;

      // Try to match each identifier
      for (const identifier of identifiers) {
        const productIndex = findProductByIdentifier(identifier);

        if (productIndex !== -1) {
          // Found a match, upload to this product
          const result = await handleImageUpload([file], productIndex);
          totalUploaded += result.uploaded;
          totalSkipped += result.skipped;
          assigned = true;
          break;
        }
      }

      // If no match was found, add to unassigned
      if (!assigned) {
        unassigned.push({
          file,
          previewUrl: createPreviewUrl(file)
        });
      }
    }

    // Update unassigned images
    setUnassignedImages(prev => [...prev, ...unassigned]);
    setProcessingBulk(false);

    // Show summary toasts
    if (totalUploaded > 0) {
      toast.success(`Auto-assigned ${totalUploaded} ${totalUploaded === 1 ? 'image' : 'images'} to products`);
    }
    if (totalSkipped > 0) {
      toast.info(`Skipped ${totalSkipped} ${totalSkipped === 1 ? 'image' : 'images'} already uploaded for their products`);
    }
    if (unassigned.length > 0) {
      toast.warning(`Could not auto-assign ${unassigned.length} ${unassigned.length === 1 ? 'image' : 'images'}`);
      setShowUnassigned(true);
    }
  };
  
  // Function to manually assign an unassigned image
  const assignImageToProduct = async (imageIndex: number, productIndex: number) => {
    const image = unassignedImages[imageIndex];
    if (!image) return;
    
    // Upload the image to the selected product
    await handleImageUpload([image.file], productIndex);
    
    // Remove from unassigned list
    setUnassignedImages(prev => prev.filter((_, idx) => idx !== imageIndex));
    
    // Revoke the preview URL to free memory
    URL.revokeObjectURL(image.previewUrl);
    
    toast.success(`Image assigned to ${data[productIndex].name || `Product #${productIndex + 1}`}`);
  };
  
  // Function to remove an unassigned image
  const removeUnassignedImage = (index: number) => {
    const image = unassignedImages[index];
    if (!image) return;
    
    // Revoke the preview URL to free memory
    URL.revokeObjectURL(image.previewUrl);
    
    // Remove from state
    setUnassignedImages(prev => prev.filter((_, idx) => idx !== index));
  };
  
  // Cleanup function for preview URLs
  const cleanupPreviewUrls = () => {
    unassignedImages.forEach(image => {
      URL.revokeObjectURL(image.previewUrl);
    });
  };

  return {
    unassignedImages,
    setUnassignedImages,
    processingBulk,
    showUnassigned,
    setShowUnassigned,
    handleBulkUpload,
    assignImageToProduct,
    removeUnassignedImage,
    cleanupPreviewUrls
  };
}; 