"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import type { AllGuidePositions, CanvasShapeConfig, GuidePosition } from "../types";

interface UseMagnifierOptions {
  canvasContainerRef: React.RefObject<HTMLDivElement | null>;
  canvasImageRef: React.RefObject<HTMLImageElement | null>;
  bleedGuideRef: React.RefObject<HTMLDivElement | null>;
  trimGuideRef: React.RefObject<HTMLDivElement | null>;
  safeGuideRef: React.RefObject<HTMLDivElement | null>;
  outerBoxRef: React.RefObject<HTMLDivElement | null>;
  side: number;
  designArr: Array<{ image: string }>;
  showGuides: boolean;
  showCut: boolean;
  loupeSize?: number;
  fixedZoom?: number;
  borderRadius?: string;
  shapeConfig?: CanvasShapeConfig;
}

export function useMagnifier({
  canvasContainerRef,
  canvasImageRef,
  bleedGuideRef,
  trimGuideRef,
  safeGuideRef,
  outerBoxRef,
  side,
  designArr,
  showGuides,
  showCut,
  loupeSize = 250,
  fixedZoom = 2,
  borderRadius,
  shapeConfig,
}: UseMagnifierOptions) {
  const [isZoomOpen, setIsZoomOpen] = useState(false);
  const [loupePos, setLoupePos] = useState({ x: 0, y: 0 });
  const [isDraggingLoupe, setIsDraggingLoupe] = useState(false);
  const [imageOffset, setImageOffset] = useState({ x: 0, y: 0 });

  const dragStartPos = useRef({ x: 0, y: 0 });
  const dragStartLoupePos = useRef({ x: 0, y: 0 });

  const [guidePositions, setGuidePositions] = useState<AllGuidePositions>({
    bleed: null,
    trim: null,
    safe: null,
  });

  const handleLoupeMouseDown = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDraggingLoupe(true);
    dragStartPos.current = { x: e.pageX, y: e.pageY };
    dragStartLoupePos.current = loupePos;
  };

  const handleWindowMouseMove = useCallback(
    (e: MouseEvent) => {
      if (!isDraggingLoupe || !canvasContainerRef.current) return;

      const dx = e.pageX - dragStartPos.current.x;
      const dy = e.pageY - dragStartPos.current.y;
      const containerRect = canvasContainerRef.current.getBoundingClientRect();

      let newX = dragStartLoupePos.current.x + dx;
      let newY = dragStartLoupePos.current.y + dy;

      newX = Math.max(0, Math.min(newX, containerRect.width - loupeSize));
      newY = Math.max(0, Math.min(newY, containerRect.height - loupeSize));

      setLoupePos({ x: newX, y: newY });
    },
    [isDraggingLoupe, loupeSize, canvasContainerRef]
  );

  const handleWindowMouseUp = useCallback(() => {
    setIsDraggingLoupe(false);
  }, []);

  useEffect(() => {
    if (isDraggingLoupe) {
      window.addEventListener("mousemove", handleWindowMouseMove);
      window.addEventListener("mouseup", handleWindowMouseUp);
    } else {
      window.removeEventListener("mousemove", handleWindowMouseMove);
      window.removeEventListener("mouseup", handleWindowMouseUp);
    }

    return () => {
      window.removeEventListener("mousemove", handleWindowMouseMove);
      window.removeEventListener("mouseup", handleWindowMouseUp);
    };
  }, [isDraggingLoupe, handleWindowMouseMove, handleWindowMouseUp]);

  // Close magnifier window when clicking any other control or outside
  useEffect(() => {
    if (!isZoomOpen) return;

    const handleDocumentClick = (e: MouseEvent) => {
      const target = e.target as HTMLElement | null;
      if (!target) return;

      if (target.closest("[data-magnifier-loupe]")) {
        return;
      }

      if (target.closest("[data-magnifier-toggle]")) {
        return;
      }

      setIsZoomOpen(false);
    };

    const timer = setTimeout(() => {
      document.addEventListener("click", handleDocumentClick);
    }, 50);

    return () => {
      clearTimeout(timer);
      document.removeEventListener("click", handleDocumentClick);
    };
  }, [isZoomOpen]);

  useEffect(() => {
    if (isZoomOpen && canvasContainerRef.current) {
      const targetImg = canvasImageRef.current;
      const containerRect = canvasContainerRef.current.getBoundingClientRect();

      if (targetImg) {
        const imgRect = targetImg.getBoundingClientRect();
        const offset = {
          x: imgRect.left - containerRect.left,
          y: imgRect.top - containerRect.top,
        };
        setImageOffset(offset);

        const getRelativePos = (
          guideRef: React.RefObject<HTMLDivElement | null>,
          defaultInset: number
        ): GuidePosition => {
          const el = guideRef.current;
          if (el) {
            const guideRect = el.getBoundingClientRect();
            return {
              x: guideRect.left - imgRect.left,
              y: guideRect.top - imgRect.top,
              width: guideRect.width,
              height: guideRect.height,
            };
          }
          return {
            x: defaultInset,
            y: defaultInset,
            width: Math.max(0, imgRect.width - defaultInset * 2),
            height: Math.max(0, imgRect.height - defaultInset * 2),
          };
        };

        setGuidePositions({
          bleed: getRelativePos(bleedGuideRef, 0),
          trim: getRelativePos(trimGuideRef, 10),
          safe: getRelativePos(safeGuideRef, 20),
        });
      }

      setLoupePos((prev) => {
        if (prev.x === 0 && prev.y === 0) {
          return {
            x: Math.max(0, (containerRect.width - loupeSize) / 2),
            y: Math.max(0, (containerRect.height - loupeSize) / 2),
          };
        }
        return prev;
      });
    }
  }, [
    isZoomOpen,
    side,
    showGuides,
    showCut,
    loupeSize,
    designArr,
    canvasContainerRef,
    canvasImageRef,
    bleedGuideRef,
    trimGuideRef,
    safeGuideRef,
  ]);

  const handleZoomToggle = () => {
    setIsZoomOpen((prev) => {
      const next = !prev;
      if (next && canvasContainerRef.current) {
        const containerRect = canvasContainerRef.current.getBoundingClientRect();
        const target = canvasImageRef.current;
        if (target) {
          const targetRect = target.getBoundingClientRect();
          const offsetX = targetRect.left - containerRect.left;
          const offsetY = targetRect.top - containerRect.top;
          setImageOffset({ x: offsetX, y: offsetY });
          setLoupePos({
            x: Math.max(0, offsetX + (targetRect.width - loupeSize) / 2),
            y: Math.max(0, offsetY + (targetRect.height - loupeSize) / 2),
          });

          const getPos = (
            ref: React.RefObject<HTMLDivElement | null>,
            defaultInset: number
          ): GuidePosition => {
            const el = ref.current;
            if (el) {
              const r = el.getBoundingClientRect();
              return {
                x: r.left - targetRect.left,
                y: r.top - targetRect.top,
                width: r.width,
                height: r.height,
              };
            }
            return {
              x: defaultInset,
              y: defaultInset,
              width: Math.max(0, targetRect.width - defaultInset * 2),
              height: Math.max(0, targetRect.height - defaultInset * 2),
            };
          };

          setGuidePositions({
            bleed: getPos(bleedGuideRef, 0),
            trim: getPos(trimGuideRef, 10),
            safe: getPos(safeGuideRef, 20),
          });
        } else {
          setLoupePos({
            x: Math.max(0, (containerRect.width - loupeSize) / 2),
            y: Math.max(0, (containerRect.height - loupeSize) / 2),
          });
        }
      }
      return next;
    });
  };

  const imgX = loupePos.x - imageOffset.x;
  const imgY = loupePos.y - imageOffset.y;
  const bgPosX = -imgX * fixedZoom;
  const bgPosY = -imgY * fixedZoom;

  const loupeImageSrc =
    designArr[side]?.image ||
    canvasImageRef.current?.src ||
    "/assets/images/transparentbg.png";

  const loupeBgWidth =
    (canvasImageRef.current?.offsetWidth ||
      outerBoxRef.current?.offsetWidth ||
      500) * fixedZoom;

  const loupeBgHeight =
    (canvasImageRef.current?.offsetHeight ||
      outerBoxRef.current?.offsetHeight ||
      300) * fixedZoom;

  useEffect(() => {
    const applyCut = (img: HTMLImageElement | null) => {
      const trim = trimGuideRef.current;
      if (!img || !trim) return;

      if (!showCut) {
        const trimRect = trim.getBoundingClientRect();
        const containerRect = img.parentElement?.getBoundingClientRect();
        if (!containerRect) return;

        const clipTop = Math.max(0, trimRect.top - containerRect.top);
        const clipLeft = Math.max(0, trimRect.left - containerRect.left);
        const clipBottom = Math.max(
          0,
          containerRect.height - (trimRect.bottom - containerRect.top)
        );
        const clipRight = Math.max(
          0,
          containerRect.width - (trimRect.right - containerRect.left)
        );

        const r = borderRadius || shapeConfig?.borderRadius;
        const roundPart = r && r !== "0px" && r !== "0" ? ` round ${r}` : "";

        img.style.clipPath = `inset(${clipTop}px ${clipRight}px ${clipBottom}px ${clipLeft}px${roundPart})`;
        img.style.transition = "clip-path 0.3s ease";
      } else {
        img.style.clipPath = "none";
      }
    };

    if (canvasImageRef.current) applyCut(canvasImageRef.current);
  }, [showCut, showGuides, side, designArr, canvasImageRef, trimGuideRef, borderRadius, shapeConfig]);

  return {
    isZoomOpen,
    setIsZoomOpen,
    handleZoomToggle,
    loupePos,
    handleLoupeMouseDown,
    bgPosX,
    bgPosY,
    loupeImageSrc,
    loupeBgWidth,
    loupeBgHeight,
    guidePositions,
    loupeSize,
    fixedZoom,
  };
}
