import React, { useRef, useState, useEffect, useCallback } from "react";
import { formatAspectRatio } from "@/app/utils/campaigns/campaignHelpers";

interface ImageCropperProps {
  imageSrc: string;
  selectedBooster: any; // Add selectedBooster prop
  onCropComplete: (cropped: string) => void;
  onCancel: () => void;
  translations?: {
    title?: string;
    your_image_label?: string;
    required_dimensions_label?: string;
    aspect_ratio_label?: string;
    booster_mode_text?: string;
    standard_mode_text?: string;
    cancel_button?: string;
    apply_button?: string;
  };
}

export default function ImageCropperEventHub({
  imageSrc,
  selectedBooster,
  onCropComplete,
  onCancel,
  translations,
}: ImageCropperProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const imageRef = useRef<HTMLImageElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const cropBoxRef = useRef<HTMLDivElement>(null);
  const blurOverlayRef = useRef<HTMLDivElement>(null);

  /** IMAGE STATE */
  const [scale, setScale] = useState(1);

  /** CROP BOX STATE */
const aspect = selectedBooster === "booster" ? 18 / 10 : 6 / 5;
const requiredDimensions = {
  width: selectedBooster === "booster" ? 1800 : 1200, 
  height: selectedBooster === "booster" ? 1000 : 1000, 
};

  const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });

  // Use ref for real-time updates, state for final values
  const cropBoxRefCurrent = useRef({
    x: 0,
    y: 0,
    width: 0,
    height: 0,
  });

  const [cropBox, setCropBox] = useState({
    x: 0,
    y: 0,
    width: 0,
    height: 0,
  });

  const [draggingCrop, setDraggingCrop] = useState(false);
  const [resizing, setResizing] = useState<string | null>(null);
  const [startPos, setStartPos] = useState({ x: 0, y: 0 });
  const [startBox, setStartBox] = useState(cropBox);
  const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
  const [imagePosition, setImagePosition] = useState({
    x: 0,
    y: 0,
    width: 0,
    height: 0,
  });

  // Update blur overlay directly without React state
  const updateBlurOverlay = useCallback(
    (cropBox: { x: number; y: number; width: number; height: number }) => {
      if (
        !blurOverlayRef.current ||
        !containerSize.width ||
        !containerSize.height
      )
        return;

      const { x, y, width, height } = cropBox;

      // Get all blur area elements
      const topBlur = blurOverlayRef.current.querySelector(
        ".top-blur"
      ) as HTMLElement;
      const bottomBlur = blurOverlayRef.current.querySelector(
        ".bottom-blur"
      ) as HTMLElement;
      const leftBlur = blurOverlayRef.current.querySelector(
        ".left-blur"
      ) as HTMLElement;
      const rightBlur = blurOverlayRef.current.querySelector(
        ".right-blur"
      ) as HTMLElement;

      if (topBlur) {
        topBlur.style.height = `${y}px`;
      }

      if (bottomBlur) {
        bottomBlur.style.top = `${y + height}px`;
        bottomBlur.style.height = `${containerSize.height - (y + height)}px`;
      }

      if (leftBlur) {
        leftBlur.style.width = `${x}px`;
        leftBlur.style.top = `${y}px`;
        leftBlur.style.height = `${height}px`;
      }

      if (rightBlur) {
        rightBlur.style.left = `${x + width}px`;
        rightBlur.style.width = `${containerSize.width - (x + width)}px`;
        rightBlur.style.top = `${y}px`;
        rightBlur.style.height = `${height}px`;
      }
    },
    [containerSize]
  );

  // Update crop box position directly without React state
  const updateCropBoxPosition = useCallback(
    (x: number, y: number, width: number, height: number) => {
      if (cropBoxRef.current) {
        cropBoxRef.current.style.left = `${x}px`;
        cropBoxRef.current.style.top = `${y}px`;
        cropBoxRef.current.style.width = `${width}px`;
        cropBoxRef.current.style.height = `${height}px`;

        // Update ref for current values
        cropBoxRefCurrent.current = { x, y, width, height };

        // Update blur overlay in the same frame
        updateBlurOverlay({ x, y, width, height });
      }
    },
    [updateBlurOverlay]
  );

  // Initialize container and crop box
  useEffect(() => {
    const img = new Image();
    img.onload = () => {
      setImageSize({ width: img.width, height: img.height });

      setTimeout(() => {
        if (containerRef.current) {
          const containerRect = containerRef.current.getBoundingClientRect();
          setContainerSize({
            width: containerRect.width,
            height: containerRect.height,
          });

          initializeCropBox(containerRect.width, containerRect.height, aspect);
          autoFitImageToContainer(
            img.width,
            img.height,
            containerRect.width,
            containerRect.height
          );
        }
      }, 100);
    };
    img.src = imageSrc;
  }, [imageSrc, aspect]);

  const autoFitImageToContainer = (
    imgWidth: number,
    imgHeight: number,
    containerWidth: number,
    containerHeight: number
  ) => {
    const scaleX = containerWidth / imgWidth;
    const scaleY = containerHeight / imgHeight;
    const minScale = Math.min(scaleX, scaleY);
    setScale(minScale);

    const displayWidth = imgWidth * minScale;
    const displayHeight = imgHeight * minScale;
    const x = (containerWidth - displayWidth) / 2;
    const y = (containerHeight - displayHeight) / 2;

    setImagePosition({
      x,
      y,
      width: displayWidth,
      height: displayHeight,
    });
  };

  const initializeCropBox = (
    containerWidth: number,
    containerHeight: number,
    aspectRatio: number
  ) => {
    let cropWidth, cropHeight;

    if (containerWidth / containerHeight > aspectRatio) {
      cropHeight = containerHeight * 0.7;
      cropWidth = cropHeight * aspectRatio;
    } else {
      cropWidth = containerWidth * 0.7;
      cropHeight = cropWidth / aspectRatio;
    }

    cropWidth = Math.max(cropWidth, 100);
    cropHeight = Math.max(cropHeight, 100);

    const x = (containerWidth - cropWidth) / 2;
    const y = (containerHeight - cropHeight) / 2;

    const newCropBox = { x, y, width: cropWidth, height: cropHeight };
    setCropBox(newCropBox);
    cropBoxRefCurrent.current = newCropBox;
    setStartBox(newCropBox);

    // Update DOM directly
    if (cropBoxRef.current) {
      updateCropBoxPosition(x, y, cropWidth, cropHeight);
    }
  };

  // Constrain crop box to image boundaries
  const constrainCropBoxToImage = (newCropBox: typeof cropBox) => {
    const imageLeft = imagePosition.x;
    const imageTop = imagePosition.y;
    const imageRight = imagePosition.x + imagePosition.width;
    const imageBottom = imagePosition.y + imagePosition.height;

    let { x, y, width, height } = newCropBox;

    // Constrain within image horizontal boundaries
    if (x < imageLeft) {
      width -= imageLeft - x;
      x = imageLeft;
    }
    if (x + width > imageRight) {
      width = imageRight - x;
    }

    // Constrain within image vertical boundaries
    if (y < imageTop) {
      height -= imageTop - y;
      y = imageTop;
    }
    if (y + height > imageBottom) {
      height = imageBottom - y;
    }

    // Maintain aspect ratio after constraining
    if (width / height > aspect) {
      height = width / aspect;
      if (y + height > imageBottom) {
        height = imageBottom - y;
        width = height * aspect;
      }
    } else {
      width = height * aspect;
      if (x + width > imageRight) {
        width = imageRight - x;
        height = width / aspect;
      }
    }

    width = Math.max(width, 50);
    height = Math.max(height, 50);

    return { x, y, width, height };
  };

  // Handle wheel for zoom
  const handleWheel = (e: React.WheelEvent) => {
    e.preventDefault();
    const delta = e.deltaY > 0 ? -0.05 : 0.05;
    const newScale = Math.max(0.3, Math.min(scale + delta, 3));
    setScale(newScale);

    if (imageRef.current && containerRef.current) {
      const containerRect = containerRef.current.getBoundingClientRect();
      const displayWidth = imageSize.width * newScale;
      const displayHeight = imageSize.height * newScale;
      const x = (containerRect.width - displayWidth) / 2;
      const y = (containerRect.height - displayHeight) / 2;

      setImagePosition({
        x,
        y,
        width: displayWidth,
        height: displayHeight,
      });

      // Update crop box position directly
      const constrainedBox = constrainCropBoxToImage(cropBoxRefCurrent.current);
      updateCropBoxPosition(
        constrainedBox.x,
        constrainedBox.y,
        constrainedBox.width,
        constrainedBox.height
      );
    }
  };

  // Start move crop box
  const startMoveCropBox = (e: React.MouseEvent) => {
    setDraggingCrop(true);
    setStartPos({ x: e.clientX, y: e.clientY });
    setStartBox(cropBoxRefCurrent.current);
  };

  // Start resize
  const startResize = (e: React.MouseEvent, direction: string) => {
    e.stopPropagation();
    setResizing(direction);
    setStartPos({ x: e.clientX, y: e.clientY });
    setStartBox(cropBoxRefCurrent.current);
  };

  // Dragging or resizing crop box - OPTIMIZED
  const onMouseMove = (e: React.MouseEvent) => {
    if (!draggingCrop && !resizing) return;

    const dx = e.clientX - startPos.x;
    const dy = e.clientY - startPos.y;

    if (draggingCrop) {
      let newX = startBox.x + dx;
      let newY = startBox.y + dy;

      // Constrain dragging within image boundaries
      newX = Math.max(
        imagePosition.x,
        Math.min(newX, imagePosition.x + imagePosition.width - startBox.width)
      );
      newY = Math.max(
        imagePosition.y,
        Math.min(newY, imagePosition.y + imagePosition.height - startBox.height)
      );

      // Update DOM directly for smooth movement
      updateCropBoxPosition(newX, newY, startBox.width, startBox.height);
      return;
    }

    // Resize logic
    let newWidth = startBox.width;
    let newHeight = startBox.height;
    let newX = startBox.x;
    let newY = startBox.y;

    if (resizing?.includes("w")) {
      newWidth = Math.max(50, startBox.width - dx);
      newHeight = newWidth / aspect;
      newX = startBox.x + (startBox.width - newWidth);
    }

    if (resizing?.includes("e")) {
      newWidth = Math.max(50, startBox.width + dx);
      newHeight = newWidth / aspect;
      newX = startBox.x;
    }

    if (resizing?.includes("n")) {
      newHeight = Math.max(50, startBox.height - dy);
      newWidth = newHeight * aspect;
      newY = startBox.y + (startBox.height - newHeight);
    }

    if (resizing?.includes("s")) {
      newHeight = Math.max(50, startBox.height + dy);
      newWidth = newHeight * aspect;
      newY = startBox.y;
    }

    // Constrain within image boundaries and update DOM directly
    const constrainedBox = constrainCropBoxToImage({
      x: newX,
      y: newY,
      width: newWidth,
      height: newHeight,
    });

    updateCropBoxPosition(
      constrainedBox.x,
      constrainedBox.y,
      constrainedBox.width,
      constrainedBox.height
    );
  };

  // Stop action - update React state only when done
  const stopAction = () => {
    if (draggingCrop || resizing) {
      // Update React state with final values from ref
      setCropBox(cropBoxRefCurrent.current);
    }
    setDraggingCrop(false);
    setResizing(null);
  };

  // Apply crop
  const cropImage = () => {
    if (!imageRef.current || !canvasRef.current || !containerRef.current)
      return;

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

    if (!ctx) return;

    canvas.width = requiredDimensions.width;
    canvas.height = requiredDimensions.height;

    // Fill with white background
    ctx.fillStyle = "#FFFFFF";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Use current values from ref
    const currentCropBox = cropBoxRefCurrent.current;

    // Calculate the scale factor between displayed image and natural image
    const scaleFactor = img.naturalWidth / imagePosition.width;

    // Convert crop box coordinates to image natural coordinates
    const sourceX = (currentCropBox.x - imagePosition.x) * scaleFactor;
    const sourceY = (currentCropBox.y - imagePosition.y) * scaleFactor;
    const sourceWidth = currentCropBox.width * scaleFactor;
    const sourceHeight = currentCropBox.height * scaleFactor;

    // Ensure within bounds
    const safeX = Math.max(0, sourceX);
    const safeY = Math.max(0, sourceY);
    const safeWidth = Math.min(sourceWidth, img.naturalWidth - safeX);
    const safeHeight = Math.min(sourceHeight, img.naturalHeight - safeY);

    ctx.drawImage(
      img,
      safeX,
      safeY,
      safeWidth,
      safeHeight,
      0,
      0,
      canvas.width,
      canvas.height
    );

    onCropComplete(canvas.toDataURL("image/jpeg"));
  };

  // Get aspect ratio display text
  const aspectRatioText = selectedBooster === "booster" ? "18:10" : "6:5";

  return (
    <div className="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center p-4 z-50">
      <div className="bg-white rounded-xl w-full lg:w-[35%] max-w-[467px] p-4">
        <h2 className="text-xl font-semibold mb-2">
          {translations?.title || "Adjust your photo"}
        </h2>
        <div className="text-sm mb-3">
          <p className="mb-1">
            <span className="font-medium">
              {translations?.your_image_label || "Your image:"}
            </span>{" "}
            {imageSize.width} × {imageSize.height}px
          </p>
          <p>
            <span className="font-medium">
              {translations?.required_dimensions_label ||
                "Required dimensions:"}
            </span>{" "}
            {requiredDimensions.width} × {requiredDimensions.height}px
            <span className="ml-2 text-gray-600">
              {translations?.aspect_ratio_label || "Aspect ratio:"}{" "}
              {aspectRatioText}
            </span>
          </p>
          <p className="text-xs text-gray-500 mt-1">
            {selectedBooster === "booster"
              ? translations?.booster_mode_text ||
                "Booster mode requires 18:10 aspect ratio"
              : translations?.standard_mode_text ||
                "Standard mode requires 6:5 aspect ratio"}
          </p>
        </div>

        <div
          ref={containerRef}
          onMouseMove={onMouseMove}
          onMouseUp={stopAction}
          onMouseLeave={stopAction}
          onWheel={handleWheel}
          className="relative overflow-hidden rounded-lg border-2 border-gray-300 bg-gray-100"
          style={{ width: "100%", height: 350 }}
        >
          {/* IMAGE - Centered and scaled to fit container */}
          <img
            ref={imageRef}
            src={imageSrc}
            className="absolute select-none"
            style={{
              left: imagePosition.x,
              top: imagePosition.y,
              width: imagePosition.width,
              height: imagePosition.height,
            }}
            alt="crop"
            draggable={false}
          />

          {/* BLUR OVERLAY - Outside crop area - Now using direct DOM updates */}
          <div ref={blurOverlayRef} className="absolute inset-0">
            {/* Top blur area */}
            <div
              className="top-blur absolute top-0 left-0 right-0 bg-white bg-opacity-60 backdrop-blur-sm"
              style={{ height: cropBox.y }}
            />
            {/* Bottom blur area */}
            <div
              className="bottom-blur absolute left-0 right-0 bg-white bg-opacity-60 backdrop-blur-sm"
              style={{
                top: cropBox.y + cropBox.height,
                height: containerSize.height - (cropBox.y + cropBox.height),
              }}
            />
            {/* Left blur area */}
            <div
              className="left-blur absolute bg-white bg-opacity-60 backdrop-blur-sm"
              style={{
                width: cropBox.x,
                top: cropBox.y,
                height: cropBox.height,
              }}
            />
            {/* Right blur area */}
            <div
              className="right-blur absolute bg-white bg-opacity-60 backdrop-blur-sm"
              style={{
                left: cropBox.x + cropBox.width,
                width: containerSize.width - (cropBox.x + cropBox.width),
                top: cropBox.y,
                height: cropBox.height,
              }}
            />
          </div>

          {/* CROP BOX */}
          {cropBox.width > 0 && cropBox.height > 0 && (
            <div
              ref={cropBoxRef}
              className="absolute border-2 border-white shadow-lg"
              style={{
                left: cropBox.x,
                top: cropBox.y,
                width: cropBox.width,
                height: cropBox.height,
              }}
              onMouseDown={startMoveCropBox}
            >
              {/* 8 RESIZE HANDLES */}
              {["nw", "n", "ne", "e", "se", "s", "sw", "w"].map((dir) => (
                <div
                  key={dir}
                  onMouseDown={(e) => startResize(e, dir)}
                  className="absolute bg-white border-2 border-blue-500 shadow-md"
                  style={{
                    width: 10,
                    height: 10,
                    borderRadius: "50%",
                    cursor: `${dir}-resize`,
                    ...(dir === "nw" && { top: -5, left: -5 }),
                    ...(dir === "n" && {
                      top: -5,
                      left: "50%",
                      transform: "translateX(-50%)",
                    }),
                    ...(dir === "ne" && { top: -5, right: -5 }),
                    ...(dir === "e" && {
                      top: "50%",
                      right: -5,
                      transform: "translateY(-50%)",
                    }),
                    ...(dir === "se" && { bottom: -5, right: -5 }),
                    ...(dir === "s" && {
                      bottom: -5,
                      left: "50%",
                      transform: "translateX(-50%)",
                    }),
                    ...(dir === "sw" && { bottom: -5, left: -5 }),
                    ...(dir === "w" && {
                      top: "50%",
                      left: -5,
                      transform: "translateY(-50%)",
                    }),
                  }}
                />
              ))}
            </div>
          )}
        </div>

        <div className="flex justify-end gap-3 mt-3">
          <button
            className="px-4 py-1.5 rounded-lg border text-sm"
            onClick={onCancel}
          >
            {translations?.cancel_button || "Cancel"}
          </button>
          <button
            className="px-4 py-1.5 rounded-lg bg-blue-600 text-white text-sm"
            onClick={cropImage}
          >
            {translations?.apply_button || "Apply"}
          </button>
        </div>

        <canvas ref={canvasRef} className="hidden" />
      </div>
    </div>
  );
}
