import { useCallback, useState, useRef, useEffect, createRef } from "react";
import { useRsi } from "../../hooks/useRsi";
import { Button } from "@/components/ui/button";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import {
  DndContext, 
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragOverlay
} from '@dnd-kit/core';
import {
  sortableKeyboardCoordinates} from '@dnd-kit/sortable';
import { Product } from "./types";
import { GenericDropzone } from "./components/GenericDropzone";
import { UnassignedImagesSection } from "./components/UnassignedImagesSection";
import { ProductCard } from "./components/ProductCard/ProductCard";
import { useDragAndDrop } from "./hooks/useDragAndDrop";
import { useProductImagesInit } from "./hooks/useProductImagesInit";
import { useProductImageOperations } from "./hooks/useProductImageOperations";
import { useBulkImageUpload } from "./hooks/useBulkImageUpload";
import { useUrlImageUpload } from "./hooks/useUrlImageUpload";

interface Props {
  data: Product[];
  file: File;
  onBack?: () => void;
  onSubmit: (data: Product[], file: File) => void | Promise<any>;
}

export const ImageUploadStep = ({ 
  data, 
  file, 
  onBack, 
  onSubmit 
}: Props) => {
  useRsi();
  const [isSubmitting, setIsSubmitting] = useState(false);
  const fileInputRefs = useRef<{ [key: number]: React.RefObject<HTMLInputElement> }>({});
  
  // Use our hook for product images initialization
  const { productImages, setProductImages, getFullImageUrl } = useProductImagesInit(data);

  // Use our hook for product image operations
  const { 
    addImageToProduct, 
    handleImageUpload, 
    removeImage 
  } = useProductImageOperations({
    data,
    productImages,
    setProductImages
  });

  // Use our hook for URL image uploads
  const {
    urlInputs,
    processingUrls,
    handleAddImageFromUrl,
    updateUrlInput
  } = useUrlImageUpload({
    data,
    setProductImages,
    addImageToProduct
  });

  // Use our hook for bulk image uploads
  const {
    unassignedImages,
    processingBulk,
    showUnassigned,
    setShowUnassigned,
    handleBulkUpload,
    assignImageToProduct,
    removeUnassignedImage,
    cleanupPreviewUrls
  } = useBulkImageUpload({
    data,
    handleImageUpload
  });
  
  // Set up sensors for drag and drop with enhanced configuration
  const sensors = useSensors(
    useSensor(PointerSensor, {
      // Make it responsive with less restrictive constraints
      activationConstraint: {
        distance: 1, // Reduced distance for more responsive drag
        delay: 0, // No delay
        tolerance: 5
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

  // Use the drag and drop hook
  const {
    activeId,
    activeImage,
    activeDroppableId,
    customCollisionDetection,
    findContainer,
    getProductContainerClasses,
    handleDragStart,
    handleDragOver,
    handleDragEnd
  } = useDragAndDrop({
    productImages,
    setProductImages,
    data
  });

  // Initialize refs for each product
  useEffect(() => {
    // Create refs for each product's file input
    data.forEach((_: Product, index: number) => {
      if (!fileInputRefs.current[index]) {
        fileInputRefs.current[index] = createRef<HTMLInputElement>();
      }
    });
  }, [data]);

  // Add this CSS for preventing browser drag behavior
  useEffect(() => {
    // Add a custom style element to the document head
    const styleEl = document.createElement('style');
    styleEl.textContent = `
      .no-native-drag {
        -webkit-user-drag: none;
        user-select: none;
      }
      .no-native-drag img {
        -webkit-user-drag: none;
      }
    `;
    document.head.appendChild(styleEl);
    
    return () => {
      // Clean up on unmount
      document.head.removeChild(styleEl);
      // Clean up preview URLs
      cleanupPreviewUrls();
    };
  }, []);
  
  // Handle calling onSubmit with the current data
  const handleSubmit = useCallback(async () => {
    setIsSubmitting(true);
    try {
      // First, we need to ensure product_images is properly formatted for each product
      const updatedData = [...data].map((product, index) => {
        // Get all images for this product
        const images = productImages
          .filter(img => img.productIndex === index)
          .map(img => img.imageUrl)
          .filter(Boolean);
        
        // Update the product with the formatted image URLs
        return {
          ...product,
          // Store as comma-separated string to ensure compatibility
          product_images: images.join(',')
        };
      });
      
      await onSubmit(updatedData, file);
    } catch (error) {
      console.error('Submit error:', error);
      toast.error(`Failed to submit: ${error instanceof Error ? error.message : 'Unknown error'}`);
    } finally {
      setIsSubmitting(false);
    }
  }, [data, file, onSubmit, productImages]);

  return (
    <div className="flex flex-col h-[calc(100vh-9.5rem)] overflow-hidden">
      {/* Header - fixed at top */}
      <div className="px-8 py-6 bg-background shrink-0">
        <h2 className="text-2xl font-semibold">Add Product Images</h2>
        <p className="text-sm text-muted-foreground mt-1">
          Drag images to reorder them or move them between products.
        </p>
      </div>
      
      {/* Content area - only this part scrolls */}
      <div className="flex-1 overflow-hidden">
        <div className="h-full flex flex-col overflow-auto">
          <div className="px-8 py-4 shrink-0">
            <GenericDropzone 
              processingBulk={processingBulk}
              unassignedImages={unassignedImages}
              showUnassigned={showUnassigned}
              onDrop={handleBulkUpload}
              onShowUnassigned={() => setShowUnassigned(true)}
            />
          </div>
          
          <div className="px-8 py-2 shrink-0">
            <UnassignedImagesSection 
              showUnassigned={showUnassigned}
              unassignedImages={unassignedImages}
              data={data}
              onHide={() => setShowUnassigned(false)}
              onAssign={assignImageToProduct}
              onRemove={removeUnassignedImage}
            />
          </div>
          
          {/* Scrollable product cards */}
          <div className="px-8 py-2 flex-1">
            <DndContext
              sensors={sensors}
              collisionDetection={customCollisionDetection}
              onDragStart={handleDragStart}
              onDragOver={handleDragOver}
              onDragEnd={handleDragEnd}
              autoScroll={{
                threshold: {
                  x: 0,
                  y: 0.2,
                }
              }}
            >
              <div className="space-y-2">
                {data.map((product: Product, index: number) => (
                  <ProductCard
                    key={index}
                    product={product}
                    index={index}
                    urlInput={urlInputs[index] || ''}
                    processingUrl={processingUrls[index] || false}
                    activeDroppableId={activeDroppableId}
                    activeId={activeId}
                    productImages={productImages}
                    fileInputRef={fileInputRefs.current[index] || createRef()}
                    onUrlInputChange={(value: string) => updateUrlInput(index, value)}
                    onUrlSubmit={(e: React.FormEvent) => {
                      e.preventDefault();
                      if (urlInputs[index]) {
                        handleAddImageFromUrl(index, urlInputs[index]);
                      }
                    }}
                    onImageUpload={(files: FileList | File[]) => handleImageUpload(files, index)}
                    onDragOver={(e: React.DragEvent) => {
                      e.preventDefault();
                      e.stopPropagation();
                    }}
                    onRemoveImage={(imageId: string) => 
                      removeImage(productImages.findIndex(img => img.id === imageId))
                    }
                    getProductContainerClasses={() => getProductContainerClasses(index)}
                    findContainer={findContainer}
                    handleAddImageFromUrl={handleAddImageFromUrl}
                  />
                ))}
              </div>
              
              <DragOverlay>
                {activeImage && (
                  <div className="relative border rounded-md overflow-hidden shadow-md bg-white">
                    <img 
                      src={getFullImageUrl(activeImage.imageUrl)} 
                      alt={activeImage.fileName}
                      className="w-24 h-24 object-contain "
                    />
                  </div>
                )}
              </DragOverlay>
            </DndContext>
          </div>
        </div>
      </div>
      
      {/* Footer - fixed at bottom */}
      <div className="flex items-center justify-between border-t bg-muted px-8 py-4 mt-1 shrink-0">
        {onBack && (
          <Button variant="outline" onClick={onBack}>
            Back
          </Button>
        )}
        <Button 
          className="ml-auto"
          onClick={handleSubmit} 
          disabled={isSubmitting || unassignedImages.length > 0}
        >
          {isSubmitting && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
          {unassignedImages.length > 0 ? 'Assign all images first' : 'Submit'}
        </Button>
      </div>
    </div>
  );
}; 