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

interface CanvasComponentProps {
  penColor: string;
  penSize: number;
  isEraserMode: boolean;
  dataURLToLoad?: string | null;
  onDrawEnd: (dataURL: string) => void;
  canvasPhysicalWidth: number;
  canvasPhysicalHeight: number;
  zoomLevel: number; // New prop
}

const CanvasComponent: React.FC<CanvasComponentProps> = ({
  penColor,
  penSize,
  isEraserMode,
  dataURLToLoad,
  onDrawEnd,
  canvasPhysicalWidth,
  canvasPhysicalHeight,
  zoomLevel, // Use zoomLevel
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [isDrawing, setIsDrawing] = useState(false);
  const lastPositionRef = useRef<{ x: number; y: number } | null>(null);

  const getCanvasContext = useCallback((): CanvasRenderingContext2D | null => {
    const canvas = canvasRef.current;
    return canvas ? canvas.getContext('2d') : null;
  }, []);
  
  useEffect(() => {
    const canvas = canvasRef.current;
    const context = getCanvasContext();
    if (canvas && context) {
      if (dataURLToLoad) {
        const img = new Image();
        img.onload = () => {
          context.fillStyle = '#FFFFFF';
          context.fillRect(0, 0, canvas.width, canvas.height);
          context.drawImage(img, 0, 0); 
        };
        img.onerror = () => { 
            console.error("Failed to load image from dataURL for canvas. Displaying a blank canvas.");
            context.fillStyle = '#FFFFFF';
            context.fillRect(0, 0, canvas.width, canvas.height);
        }
        img.src = dataURLToLoad;
      } else {
        context.fillStyle = '#FFFFFF';
        context.fillRect(0, 0, canvas.width, canvas.height);
      }
    }
  }, [dataURLToLoad, getCanvasContext, canvasPhysicalWidth, canvasPhysicalHeight]);

  const getRelativePosition = useCallback((event: MouseEvent | TouchEvent): { x: number; y: number } | null => {
    const canvas = canvasRef.current;
    if (!canvas) return null;

    const rect = canvas.getBoundingClientRect(); // This rect is of the visually scaled canvas
    let clientX, clientY;

    if (event instanceof TouchEvent) { 
        if (event.touches.length === 0) return null; 
        clientX = event.touches[0].clientX;
        clientY = event.touches[0].clientY;
    } else { 
        clientX = event.clientX;
        clientY = event.clientY;
    }
    
    // Adjust coordinates based on zoom level
    // (clientX - rect.left) gives position relative to the scaled canvas's top-left on screen
    // Divide by zoomLevel to get position relative to the unscaled canvas's internal coordinates
    return {
      x: (clientX - rect.left) / zoomLevel,
      y: (clientY - rect.top) / zoomLevel,
    };
  }, [zoomLevel]); // Add zoomLevel to dependencies

  const startDrawing = useCallback((event: MouseEvent | TouchEvent) => {
    event.preventDefault(); 
    const pos = getRelativePosition(event);
    if (!pos) return;
    
    const context = getCanvasContext();
    if(!context) return;

    setIsDrawing(true);
    lastPositionRef.current = pos;

    context.lineCap = 'round';
    context.lineJoin = 'round';
    
    if (isEraserMode) {
        context.globalCompositeOperation = 'destination-out';
        context.strokeStyle = "rgba(0,0,0,1)"; 
        context.fillStyle = "rgba(0,0,0,1)"; 
    } else {
        context.globalCompositeOperation = 'source-over';
        context.strokeStyle = penColor;
        context.fillStyle = penColor; 
    }
    
    context.beginPath();
    // For single click dots, use arc. For lines, it's just the start point.
    // The actual drawing of the dot happens here.
    context.arc(pos.x, pos.y, penSize / (2 * zoomLevel), 0, Math.PI * 2); // Scale dot size with zoom for visual consistency
    context.lineWidth = penSize / zoomLevel; // Scale line width for visual consistency
    context.fill();


  }, [getCanvasContext, penColor, penSize, isEraserMode, getRelativePosition, zoomLevel]);

  const draw = useCallback((event: MouseEvent | TouchEvent) => {
    if (!isDrawing) return;
    event.preventDefault();
    const pos = getRelativePosition(event);
    if (!pos || !lastPositionRef.current) return;

    const context = getCanvasContext();
    if (context) {
      context.lineWidth = penSize / zoomLevel; // Scale line width
      context.lineCap = 'round';
      context.lineJoin = 'round';

      if (isEraserMode) {
        context.globalCompositeOperation = 'destination-out';
        context.strokeStyle = "rgba(0,0,0,1)"; 
      } else {
        context.globalCompositeOperation = 'source-over';
        context.strokeStyle = penColor;
      }
      
      context.beginPath();
      context.moveTo(lastPositionRef.current.x, lastPositionRef.current.y);
      context.lineTo(pos.x, pos.y);
      context.stroke();
      lastPositionRef.current = pos;
    }
  }, [isDrawing, getCanvasContext, penColor, penSize, isEraserMode, getRelativePosition, zoomLevel]);

  const endDrawing = useCallback(() => {
    if (!isDrawing) return; 
    setIsDrawing(false);
    
    const canvas = canvasRef.current;
    if (canvas) {
      const context = getCanvasContext();
      if (context) { 
          context.globalCompositeOperation = 'source-over'; // Reset composite operation
      }
      onDrawEnd(canvas.toDataURL('image/png'));
    }
    lastPositionRef.current = null;
  }, [isDrawing, onDrawEnd, getCanvasContext]);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    // Passive false is important for preventDefault() to work on touch events and prevent scrolling page.
    const eventOptions = { passive: false };

    canvas.addEventListener('mousedown', startDrawing, eventOptions);
    canvas.addEventListener('mousemove', draw, eventOptions);
    canvas.addEventListener('mouseup', endDrawing, eventOptions);
    canvas.addEventListener('mouseleave', endDrawing, eventOptions); 

    canvas.addEventListener('touchstart', startDrawing, eventOptions);
    canvas.addEventListener('touchmove', draw, eventOptions);
    canvas.addEventListener('touchend', endDrawing, eventOptions);
    canvas.addEventListener('touchcancel', endDrawing, eventOptions);

    return () => {
      canvas.removeEventListener('mousedown', startDrawing);
      canvas.removeEventListener('mousemove', draw);
      canvas.removeEventListener('mouseup', endDrawing);
      canvas.removeEventListener('mouseleave', endDrawing);
      canvas.removeEventListener('touchstart', startDrawing);
      canvas.removeEventListener('touchmove', draw);
      canvas.removeEventListener('touchend', endDrawing);
      canvas.removeEventListener('touchcancel', endDrawing);
    };
  }, [startDrawing, draw, endDrawing]); // Re-bind if these handlers change (e.g. due to zoomLevel)

  return (
    <canvas
      ref={canvasRef}
      width={canvasPhysicalWidth}
      height={canvasPhysicalHeight}
      className="border-2 border-slate-400 rounded-lg shadow-2xl touch-none bg-white cursor-crosshair"
      // Style for imageRendering is good for pixel art, ensure it doesn't conflict with scaling needs.
      // Visual scaling is handled by the parent div's transform.
      style={{ imageRendering: 'pixelated' }} 
      aria-label="Drawing canvas"
    />
  );
};

export default CanvasComponent;
