import { useCallback, useState, useRef, useEffect, createRef, useContext } 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";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { AuthContext } from "@/contexts/AuthContext";
import { useImportAutosave } from "@/hooks/useImportAutosave";
import { useImportSession } from "@/contexts/ImportSessionContext";
import { SaveSessionButton } from "../../components/SaveSessionDialog";
import type { SubmitOptions } from "../../types";
import type { ImportSessionData } from "@/types/importSession";

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

export const ImageUploadStep = ({ 
  data, 
  file, 
  onBack, 
  onSubmit 
}: Props) => {
  useRsi();
  const [isSubmitting, setIsSubmitting] = useState(false);
  const fileInputRefs = useRef<{ [key: number]: React.RefObject<HTMLInputElement> }>({});
  const { user } = useContext(AuthContext);
  const hasDebugPermission = Boolean(user?.is_admin || user?.permissions?.includes("admin:debug"));
  const [targetEnvironment, setTargetEnvironment] = useState<SubmitOptions["targetEnvironment"]>("prod");
  const [useTestDataSource, setUseTestDataSource] = useState<boolean>(false);
  const [skipApiSubmission, setSkipApiSubmission] = useState<boolean>(false);
  const [showNewProduct, setShowNewProduct] = useState<boolean>(false);
  const [showConfirmDialog, setShowConfirmDialog] = useState<boolean>(false);

  // Import session context for cleanup on submit and global selections
  const { deleteSession: deleteImportSession, getGlobalSelections } = useImportSession();

  // 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
  });

  // Autosave hook for session persistence
  const { markDirty } = useImportAutosave({
    enabled: true,
    step: 'imageUpload',
    getSessionData: useCallback((): ImportSessionData => {
      return {
        current_step: 'imageUpload',
        data: data as any[], // Product data
        product_images: productImages,
        global_selections: getGlobalSelections(),
      };
    }, [data, productImages, getGlobalSelections]),
  });

  // Mark dirty when images change (use ref to avoid depending on markDirty identity)
  const markDirtyRef = useRef(markDirty);
  markDirtyRef.current = markDirty;
  const prevProductImagesRef = useRef(productImages);
  useEffect(() => {
    if (prevProductImagesRef.current !== productImages) {
      prevProductImagesRef.current = productImages;
      markDirtyRef.current();
    }
  }, [productImages]);

  // 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(','),
          // Add show_new_product flag if enabled
          ...(showNewProduct && { show_new_product: true })
        };
      });

      const submitOptions: SubmitOptions = {
        targetEnvironment,
        useTestDataSource,
        skipApiSubmission,
        showNewProduct,
      };

      const success = await onSubmit(updatedData, file, submitOptions);

      // Only delete the import session after a successful submit response
      if (success) {
        try {
          await deleteImportSession();
        } catch (err) {
          // Non-critical - log but don't fail the submission
          console.warn('Failed to delete import session:', err);
        }
      }
    } 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, targetEnvironment, useTestDataSource, skipApiSubmission, showNewProduct, deleteImportSession]);

  return (
    <div className="flex flex-col h-[calc(100vh-9.5rem)] overflow-hidden relative">
      {/* Full-screen loading overlay during submit */}
      {isSubmitting && (
        <div className="absolute inset-0 bg-background/80 backdrop-blur-sm z-50 flex flex-col items-center justify-center gap-4">
          <Loader2 className="h-12 w-12 animate-spin text-primary" />
          <div className="text-lg font-medium">Submitting products...</div>
          <div className="text-sm text-muted-foreground">Please wait while your import is being processed</div>
        </div>
      )}

      {/* Header - fixed at top */}
      <div className="px-8 py-6 bg-background shrink-0">
        <div className="flex items-center justify-between">
          <div>
            <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>
          <SaveSessionButton />
        </div>
      </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={async (files: FileList | File[]) => {
                      const { skipped } = await handleImageUpload(files, index);
                      if (skipped > 0) {
                        const label = product.name || `Product #${index + 1}`;
                        toast.info(`Skipped ${skipped} duplicate ${skipped === 1 ? 'image' : 'images'} for ${label}`);
                      }
                    }}
                    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 flex-wrap items-center justify-between gap-4 border-t bg-muted px-8 py-4 mt-1 shrink-0">
        {onBack && (
          <Button variant="outline" onClick={onBack}>
            Back
          </Button>
        )}
        <div className="flex flex-1 flex-wrap items-center justify-end gap-6">
          <div className="flex items-center gap-1">
            <Switch
              id="product-import-show-new-product"
              checked={showNewProduct}
              onCheckedChange={(checked) => {
                if (checked) {
                  setShowConfirmDialog(true);
                } else {
                  setShowNewProduct(false);
                }
              }}
            />
            <div>
              <Label htmlFor="product-import-show-new-product" className="text-sm font-medium">
                Show these products immediately
              </Label>
            </div>
          </div>
          {hasDebugPermission && (
            <div className="flex gap-4 text-sm">
              {!skipApiSubmission && (
                <>
                  <div className="flex items-center gap-1">
                    <Switch
                      id="product-import-api-environment"
                      checked={targetEnvironment === "dev"}
                      onCheckedChange={(checked) => setTargetEnvironment(checked ? "dev" : "prod")}
                    />
                    <div>
                      <Label htmlFor="product-import-api-environment" className="text-sm font-medium">
                        Use test API
                      </Label>
                    </div>
                  </div>
                  <div className="flex items-center gap-1">
                    <Switch
                      id="product-import-api-test-data"
                      checked={useTestDataSource}
                      onCheckedChange={(checked) => setUseTestDataSource(checked)}
                    />
                    <div>
                      <Label htmlFor="product-import-api-test-data" className="text-sm font-medium">
                        Use test database
                      </Label>
                    </div>
                  </div>
                </>
              )}
              <div className="flex items-center gap-1">
                <Switch
                  id="product-import-skip-api"
                  checked={skipApiSubmission}
                  onCheckedChange={(checked) => setSkipApiSubmission(checked)}
                />
                <div>
                  <Label htmlFor="product-import-skip-api" className="text-sm font-medium text-amber-600">
                    Skip API (Debug)
                  </Label>
                </div>
              </div>
            </div>
          )}
          <Button 
            className="min-w-[140px]"
            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>

      <AlertDialog open={showConfirmDialog} onOpenChange={setShowConfirmDialog}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Show products immediately?</AlertDialogTitle>
            <AlertDialogDescription>
              This will create all of these products with the "hide" option NOT set, so they will be immediately visible on the site when received or put on pre-order. Do NOT use this option for products we're not allowed to show yet.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onClick={() => setShowConfirmDialog(false)}>
              Cancel
            </AlertDialogCancel>
            <AlertDialogAction
              onClick={() => {
                setShowNewProduct(true);
                setShowConfirmDialog(false);
              }}
            >
              Yes, show immediately
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}; 
