import { useState, useRef, useCallback, useEffect } from 'react';

interface UseImageCropperProps {
  requiredDimensions: { width: number; height: number };
  containerWidth?: number;
  containerHeight?: number;
}

interface CropperState {
  scale: number;
  position: { x: number; y: number };
  isDragging: boolean;
  dragStart: { x: number; y: number };
}

export const useImageCropper = ({
  requiredDimensions,
  containerWidth = 500,
  containerHeight = 400
}: UseImageCropperProps) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const imageRef = useRef<HTMLImageElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  
  const [state, setState] = useState<CropperState>({
    scale: 1,
    position: { x: 0, y: 0 },
    isDragging: false,
    dragStart: { x: 0, y: 0 }
  });

  const targetRatio = requiredDimensions.width / requiredDimensions.height;

  // Initialize image and calculate initial scale and position
  const initializeImage = useCallback((img: HTMLImageElement) => {
    const actualContainerWidth = containerRef.current?.clientWidth || containerWidth;
    const actualContainerHeight = containerHeight;

    const imgRatio = img.width / img.height;
    
    let displayWidth, displayHeight;
    
    // Calculate initial scale to fit image within container while maintaining aspect ratio
    if (imgRatio > targetRatio) {
      // Image is wider than target ratio
      displayWidth = Math.min(actualContainerWidth, img.width);
      displayHeight = displayWidth / imgRatio;
    } else {
      // Image is taller than target ratio
      displayHeight = Math.min(actualContainerHeight, img.height);
      displayWidth = displayHeight * imgRatio;
    }
    
    const initialScale = displayWidth / img.width;
    
    setState(prev => ({
      ...prev,
      scale: initialScale,
      position: {
        x: (actualContainerWidth - img.width * initialScale) / 2,
        y: (actualContainerHeight - img.height * initialScale) / 2
      }
    }));
  }, [targetRatio, containerWidth, containerHeight]);

  // Handle mouse/touch events
  const handleMouseDown = useCallback((e: React.MouseEvent | React.TouchEvent) => {
    e.preventDefault();
    const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
    const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;

    setState(prev => ({
      ...prev,
      isDragging: true,
      dragStart: {
        x: clientX - prev.position.x,
        y: clientY - prev.position.y
      }
    }));
  }, []);

  const handleMouseMove = useCallback((e: React.MouseEvent | React.TouchEvent) => {
    if (!state.isDragging) return;
    e.preventDefault();

    const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
    const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;

    if (imageRef.current && containerRef.current) {
      const container = containerRef.current;
      const scaledWidth = imageRef.current.width * state.scale;
      const scaledHeight = imageRef.current.height * state.scale;
      
      // Calculate bounds to prevent dragging outside container
      const maxX = Math.max(0, (scaledWidth - container.clientWidth) / 2);
      const maxY = Math.max(0, (scaledHeight - container.clientHeight) / 2);
      
      const newX = Math.max(-maxX, Math.min(maxX, clientX - state.dragStart.x));
      const newY = Math.max(-maxY, Math.min(maxY, clientY - state.dragStart.y));

      setState(prev => ({
        ...prev,
        position: { x: newX, y: newY }
      }));
    }
  }, [state.isDragging, state.scale, state.dragStart]);

  const handleMouseUp = useCallback(() => {
    setState(prev => ({ ...prev, isDragging: false }));
  }, []);

  // Enhanced zoom functionality with wheel support
  const handleZoom = useCallback((delta: number, centerX?: number, centerY?: number) => {
    setState(prev => {
      const newScale = Math.max(0.1, Math.min(5, prev.scale + delta));
      
      if (centerX !== undefined && centerY !== undefined && imageRef.current) {
        // Zoom towards mouse position
        const scaleChange = newScale - prev.scale;
        const img = imageRef.current;
        
        const newX = prev.position.x - (centerX - prev.position.x) * (scaleChange / prev.scale);
        const newY = prev.position.y - (centerY - prev.position.y) * (scaleChange / prev.scale);
        
        return { 
          ...prev, 
          scale: newScale,
          position: { x: newX, y: newY }
        };
      }
      
      return { ...prev, scale: newScale };
    });
  }, []);

  // Reset cropper
  const resetCropper = useCallback((img?: HTMLImageElement) => {
    if (img) {
      initializeImage(img);
    } else if (imageRef.current) {
      initializeImage(imageRef.current);
    }
  }, [initializeImage]);

  // Enhanced crop function with proper background handling
  const cropImage = useCallback((): string | null => {
    if (!canvasRef.current || !imageRef.current) return null;

    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    const img = imageRef.current;

    if (!ctx) return null;

    // Set canvas size to required dimensions
    canvas.width = requiredDimensions.width;
    canvas.height = requiredDimensions.height;

    // Fill background with white (instead of black)
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Calculate the source rectangle from the original image
    const scale = state.scale;
    const container = containerRef.current;
    
    if (!container) return null;

    // Calculate visible area in container coordinates
    const containerRect = container.getBoundingClientRect();
    const cropAreaWidth = container.clientWidth;
    const cropAreaHeight = container.clientHeight;
    
    // Convert container coordinates to image coordinates
    const sourceX = (-state.position.x) / scale;
    const sourceY = (-state.position.y) / scale;
    const sourceWidth = cropAreaWidth / scale;
    const sourceHeight = cropAreaHeight / scale;

    // Draw the cropped portion with proper scaling to fit required dimensions
    ctx.drawImage(
      img,
      sourceX, sourceY, sourceWidth, sourceHeight, // source rectangle
      0, 0, canvas.width, canvas.height // destination rectangle
    );

    return canvas.toDataURL('image/jpeg', 0.92);
  }, [requiredDimensions, state.scale, state.position]);

  // Wheel event for zooming
  const handleWheel = useCallback((e: React.WheelEvent) => {
    e.preventDefault();
    const delta = -e.deltaY * 0.001;
    const rect = e.currentTarget.getBoundingClientRect();
    const centerX = e.clientX - rect.left;
    const centerY = e.clientY - rect.top;
    
    handleZoom(delta, centerX, centerY);
  }, [handleZoom]);

  return {
    // Refs
    canvasRef,
    imageRef,
    containerRef,
    
    // State
    scale: state.scale,
    position: state.position,
    isDragging: state.isDragging,
    
    // Actions
    initializeImage,
    handleMouseDown,
    handleMouseMove,
    handleMouseUp,
    handleZoom,
    handleWheel,
    resetCropper,
    cropImage,
    
    // Event handlers for easy use in components
    eventHandlers: {
      onMouseDown: handleMouseDown,
      onMouseMove: handleMouseMove,
      onMouseUp: handleMouseUp,
      onTouchStart: handleMouseDown,
      onTouchMove: handleMouseMove,
      onTouchEnd: handleMouseUp,
      onWheel: handleWheel,
    }
  };
};