import React, { useState, useRef, useCallback } from "react";
import { X, Check, Move } from "lucide-react";
import { Button } from "../ui/button";

interface ImageEditorProps {
  isOpen: boolean;
  onClose: () => void;
  imageUrl: string;
  onSave: (editedImageBlob: Blob) => void;
}

interface CropArea {
  x: number;
  y: number;
  width: number;
  height: number;
}

export function ImageEditor({
  isOpen,
  onClose,
  imageUrl,
  onSave,
}: ImageEditorProps) {
  const [cropArea, setCropArea] = useState<CropArea>({
    x: 50,
    y: 50,
    width: 150,
    height: 150,
  });
  const [isDragging, setIsDragging] = useState(false);
  const [isResizing, setIsResizing] = useState(false);
  const [resizeDirection, setResizeDirection] = useState<
    "se" | "sw" | "ne" | "nw" | null
  >(null);
  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  // Helper function to get coordinates from mouse or touch event
  const getEventCoordinates = (e: MouseEvent | TouchEvent) => {
    if ("touches" in e && e.touches.length > 0) {
      return { x: e.touches[0].clientX, y: e.touches[0].clientY };
    }
    return { x: (e as MouseEvent).clientX, y: (e as MouseEvent).clientY };
  };

  const handlePointerDown = (
    e: React.MouseEvent | React.TouchEvent,
    action: "drag" | "resize",
    direction?: "se" | "sw" | "ne" | "nw"
  ) => {
    e.preventDefault();
    if (!containerRef.current) return;

    const coords = getEventCoordinates(
      e.nativeEvent as MouseEvent | TouchEvent
    );

    const rect = containerRef.current.getBoundingClientRect();
    const relativeX = coords.x - rect.left;
    const relativeY = coords.y - rect.top;

    if (action === "drag") {
      setIsDragging(true);
      setDragStart({
        x: relativeX - cropArea.x,
        y: relativeY - cropArea.y,
      });
    } else {
      setIsResizing(true);
      setResizeDirection(direction || "se");
      setDragStart({
        x: relativeX,
        y: relativeY,
      });
    }
  };

  const handlePointerMove = useCallback(
    (e: MouseEvent | TouchEvent) => {
      if (!containerRef.current) return;

      // Prevent default behavior for touch events to avoid scrolling
      if ("touches" in e) {
        e.preventDefault();
      }

      const coords = getEventCoordinates(e);
      const rect = containerRef.current.getBoundingClientRect();

      // Convert global coordinates to container-relative coordinates
      const relativeX = coords.x - rect.left;
      const relativeY = coords.y - rect.top;

      if (isDragging) {
        const newX = relativeX - dragStart.x;
        const newY = relativeY - dragStart.y;

        setCropArea((prev) => ({
          ...prev,
          x: Math.max(0, Math.min(rect.width - prev.width, newX)),
          y: Math.max(0, Math.min(rect.height - prev.height, newY)),
        }));
      } else if (isResizing && resizeDirection) {
        const deltaX = relativeX - dragStart.x;
        const deltaY = relativeY - dragStart.y;

        setCropArea((prev) => {
          let newX = prev.x;
          let newY = prev.y;
          let newWidth = prev.width;
          let newHeight = prev.height;

          switch (resizeDirection) {
            case "se": // Southeast (bottom-right)
              newWidth = Math.max(
                30,
                Math.min(rect.width - prev.x, prev.width + deltaX)
              );
              newHeight = Math.max(
                30,
                Math.min(rect.height - prev.y, prev.height + deltaY)
              );
              break;
            case "sw": // Southwest (bottom-left)
              newWidth = Math.max(30, prev.width - deltaX);
              newHeight = Math.max(
                30,
                Math.min(rect.height - prev.y, prev.height + deltaY)
              );
              newX = Math.max(
                0,
                Math.min(prev.x + prev.width - newWidth, prev.x + deltaX)
              );
              break;
            case "ne": // Northeast (top-right)
              newWidth = Math.max(
                30,
                Math.min(rect.width - prev.x, prev.width + deltaX)
              );
              newHeight = Math.max(30, prev.height - deltaY);
              newY = Math.max(
                0,
                Math.min(prev.y + prev.height - newHeight, prev.y + deltaY)
              );
              break;
            case "nw": // Northwest (top-left)
              newWidth = Math.max(30, prev.width - deltaX);
              newHeight = Math.max(30, prev.height - deltaY);
              newX = Math.max(
                0,
                Math.min(prev.x + prev.width - newWidth, prev.x + deltaX)
              );
              newY = Math.max(
                0,
                Math.min(prev.y + prev.height - newHeight, prev.y + deltaY)
              );
              break;
          }

          return {
            x: newX,
            y: newY,
            width: newWidth,
            height: newHeight,
          };
        });

        // Update drag start for continuous resizing - using relative coordinates
        setDragStart({ x: relativeX, y: relativeY });
      }
    },
    [isDragging, isResizing, resizeDirection, dragStart]
  );

  const handlePointerUp = useCallback(() => {
    setIsDragging(false);
    setIsResizing(false);
    setResizeDirection(null);
  }, []);

  // Add event listeners for both mouse and touch events
  React.useEffect(() => {
    if (isDragging || isResizing) {
      // Mouse events
      document.addEventListener("mousemove", handlePointerMove);
      document.addEventListener("mouseup", handlePointerUp);

      // Touch events with passive: false to allow preventDefault
      document.addEventListener("touchmove", handlePointerMove, {
        passive: false,
      });
      document.addEventListener("touchend", handlePointerUp);
      document.addEventListener("touchcancel", handlePointerUp);

      return () => {
        document.removeEventListener("mousemove", handlePointerMove);
        document.removeEventListener("mouseup", handlePointerUp);
        document.removeEventListener("touchmove", handlePointerMove);
        document.removeEventListener("touchend", handlePointerUp);
        document.removeEventListener("touchcancel", handlePointerUp);
      };
    }
  }, [isDragging, isResizing, handlePointerMove, handlePointerUp]);

  // Initialize crop area to center when component opens
  React.useEffect(() => {
    if (isOpen && containerRef.current && imageUrl) {
      const img = new Image();
      img.crossOrigin = "anonymous"; // Add this to handle CORS for external images
      img.onload = () => {
        const rect = containerRef.current?.getBoundingClientRect();
        if (!rect) return;

        // Calculate actual image display dimensions with object-contain
        const containerAspect = rect.width / rect.height;
        const imageAspect = img.width / img.height;

        let displayWidth, displayHeight, offsetX, offsetY;

        if (imageAspect > containerAspect) {
          // Image is wider - fit to container width
          displayWidth = rect.width;
          displayHeight = rect.width / imageAspect;
          offsetX = 0;
          offsetY = (rect.height - displayHeight) / 2;
        } else {
          // Image is taller - fit to container height
          displayWidth = rect.height * imageAspect;
          displayHeight = rect.height;
          offsetX = (rect.width - displayWidth) / 2;
          offsetY = 0;
        }

        // Set initial crop area to center of actual image display area
        const initialSize = Math.min(displayWidth, displayHeight) * 0.6;
        setCropArea({
          x: offsetX + (displayWidth - initialSize) / 2,
          y: offsetY + (displayHeight - initialSize) / 2,
          width: initialSize,
          height: initialSize,
        });
      };

      img.onerror = () => {
        console.error("Failed to load image for initial display");
        // Set a default crop area if image fails to load
        setCropArea({
          x: 50,
          y: 50,
          width: 150,
          height: 150,
        });
      };

      img.src = imageUrl;
    }
  }, [isOpen, imageUrl]);

  const applyCropAndRotation = useCallback(() => {
    if (!canvasRef.current || !containerRef.current) return;

    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    const img = new Image();
    img.crossOrigin = "anonymous"; // Add this to handle CORS for external images
    img.onload = () => {
      // Get container dimensions
      const containerRect = containerRef.current?.getBoundingClientRect();
      if (!containerRect) return;

      // Calculate actual image display dimensions with object-contain
      const containerAspect = containerRect.width / containerRect.height;
      const imageAspect = img.width / img.height;

      let displayWidth, displayHeight, offsetX, offsetY;

      if (imageAspect > containerAspect) {
        // Image is wider - fit to container width
        displayWidth = containerRect.width;
        displayHeight = containerRect.width / imageAspect;
        offsetX = 0;
        offsetY = (containerRect.height - displayHeight) / 2;
      } else {
        // Image is taller - fit to container height
        displayWidth = containerRect.height * imageAspect;
        displayHeight = containerRect.height;
        offsetX = (containerRect.width - displayWidth) / 2;
        offsetY = 0;
      }

      // Calculate scale factors based on actual displayed image size
      const scaleX = img.width / displayWidth;
      const scaleY = img.height / displayHeight;

      // Adjust crop coordinates to account for image offset
      const adjustedCropX = (cropArea.x - offsetX) * scaleX;
      const adjustedCropY = (cropArea.y - offsetY) * scaleY;
      const adjustedCropWidth = cropArea.width * scaleX;
      const adjustedCropHeight = cropArea.height * scaleY;

      // Crop rectangle expressed in the SOURCE image's native pixels
      // (adjusted* already scales the on-screen crop back up to the original).
      const srcX = Math.max(0, adjustedCropX);
      const srcY = Math.max(0, adjustedCropY);
      const srcWidth = Math.min(adjustedCropWidth, img.width - srcX);
      const srcHeight = Math.min(adjustedCropHeight, img.height - srcY);

      // Size the canvas to the full-resolution crop region, NOT the editor's
      // on-screen crop size. Using the display size here was downscaling phone
      // photos to a few hundred pixels, which is what made uploads blurry.
      // The backend still caps the final image to 1600px.
      canvas.width = Math.max(1, Math.round(srcWidth));
      canvas.height = Math.max(1, Math.round(srcHeight));

      // Clear canvas
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // Draw the cropped portion at native resolution
      ctx.drawImage(
        img,
        srcX,
        srcY,
        srcWidth,
        srcHeight,
        0,
        0,
        canvas.width,
        canvas.height
      );

      // Convert to blob and save
      canvas.toBlob(
        (blob) => {
          if (blob) {
            onSave(blob);
          }
          onClose();
        },
        "image/jpeg",
        0.92
      );
    };

    img.onerror = () => {
      console.error("Failed to load image for cropping");
      // Still close the editor on error
      onClose();
    };

    img.src = imageUrl;
  }, [cropArea, imageUrl, onSave, onClose]);

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 bg-BLACK bg-opacity-75 z-50 flex items-center justify-center p-4 touch-none">
      <div className="bg-WHITE rounded-lg w-full max-w-2xl max-h-[90vh] overflow-hidden">
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b">
          <h3 className="text-lg font-semibold">ویرایش تصویر</h3>
          <button onClick={onClose} className="p-1 hover:bg-WHITE3 rounded">
            <X size={20} />
          </button>
        </div>

        {/* Image Editor Area */}
        <div className="p-4">
          <div
            ref={containerRef}
            className="relative w-full h-64 sm:h-80 bg-BLACK rounded-lg overflow-hidden mb-4 touch-none"
          >
            {/* Background Image */}
            <img
              src={imageUrl}
              alt="Edit"
              className="w-full h-full object-contain select-none"
              style={{
                transition: "transform 0.2s ease",
              }}
              draggable={false}
            />

            {/* Crop Overlay */}
            <div
              className="absolute border-2 border-WHITE shadow-lg touch-none"
              style={{
                left: cropArea.x,
                top: cropArea.y,
                width: cropArea.width,
                height: cropArea.height,
                cursor: isDragging ? "grabbing" : "grab",
              }}
              role="button"
              tabIndex={0}
              onMouseDown={(e) => handlePointerDown(e, "drag")}
              onTouchStart={(e) => handlePointerDown(e, "drag")}
              onKeyDown={(e) => {
                if (e.key === "Enter" || e.key === " ") {
                  e.preventDefault();
                  // Handle keyboard interaction if needed
                }
              }}
            >
              {/* Crop area background */}
              <div className="w-full h-full bg-transparent relative">
                {/* Resize handles - all four corners */}
                {/* Top-left */}
                <div
                  className="absolute -top-1 -left-1 w-4 h-4 bg-WHITE border border-GRAY2 cursor-nw-resize touch-none"
                  role="button"
                  tabIndex={0}
                  onMouseDown={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "nw");
                  }}
                  onTouchStart={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "nw");
                  }}
                />
                {/* Top-right */}
                <div
                  className="absolute -top-1 -right-1 w-4 h-4 bg-WHITE border border-GRAY2 cursor-ne-resize touch-none"
                  role="button"
                  tabIndex={0}
                  onMouseDown={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "ne");
                  }}
                  onTouchStart={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "ne");
                  }}
                />
                {/* Bottom-left */}
                <div
                  className="absolute -bottom-1 -left-1 w-4 h-4 bg-WHITE border border-GRAY2 cursor-sw-resize touch-none"
                  role="button"
                  tabIndex={0}
                  onMouseDown={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "sw");
                  }}
                  onTouchStart={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "sw");
                  }}
                />
                {/* Bottom-right */}
                <div
                  className="absolute -bottom-1 -right-1 w-4 h-4 bg-WHITE border border-GRAY2 cursor-se-resize touch-none"
                  role="button"
                  tabIndex={0}
                  onMouseDown={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "se");
                  }}
                  onTouchStart={(e) => {
                    e.stopPropagation();
                    handlePointerDown(e, "resize", "se");
                  }}
                />
                {/* Move icon */}
                <div className="absolute top-1 left-1 text-WHITE opacity-75">
                  <Move size={14} />
                </div>
              </div>
            </div>

            {/* Dark overlay outside crop area */}
            <div
              className="absolute inset-0 bg-BLACK bg-opacity-50 pointer-events-none"
              style={{
                clipPath: `polygon(0% 0%, 0% 100%, ${cropArea.x}px 100%, ${cropArea.x}px ${cropArea.y}px, ${cropArea.x + cropArea.width}px ${cropArea.y}px, ${cropArea.x + cropArea.width}px ${cropArea.y + cropArea.height}px, ${cropArea.x}px ${cropArea.y + cropArea.height}px, ${cropArea.x}px 100%, 100% 100%, 100% 0%)`,
              }}
            />
          </div>
        </div>

        {/* Footer */}
        <div className="flex gap-3 p-4 border-t">
          <Button
            size="lg"
            className="w-full flex-1"
            variant="primary"
            onClick={onClose}
          >
            لغو
          </Button>
          <Button
            size="lg"
            className="w-full flex-2"
            variant="dark"
            onClick={applyCropAndRotation}
          >
            <Check size={16} className="ml-2" />
            اعمال تغییرات
          </Button>
        </div>
      </div>

      {/* Hidden canvas for processing */}
      <canvas ref={canvasRef} className="hidden" />
    </div>
  );
}
