import { useEffect, useContext, useState, useRef, useCallback } from "react";
import { AspectRatio } from "@/components/ui/aspect-ratio";
import OpenContext from "../Context/openContext/OpenContext";
import CanvasContext from "../Context/canvasContext/CanvasContext";
import { Card, CardContent } from "../ui/card";
import ActiveObjectContext from "../Context/activeObject/ObjectContext";
import { Slider } from "@/components/ui/slider";

export default function Canvas() {
  const {
    setLeftPanelOpen,
    setRightPanelOpen,
    setOpenSetting,
    setOpenObjectPanel,
    rightPanelOpen,
  } = useContext(OpenContext);

  const {
    canvasRef,
    canvas,
    setCanvas,
    fabricCanvasRef,
    canvasRatio,
    setCanvasHeight,
    setCanvasWidth,
    setScreenWidth,
  } = useContext(CanvasContext);

  const { setActiveObject } = useContext(ActiveObjectContext);
  const [zoomLevel, setZoomLevel] = useState(100);
  const containerRef = useRef(null);

  const handleZoom = useCallback(
    (newZoom) => {
      const zoom = Math.min(Math.max(newZoom, 0), 100);
      setZoomLevel(zoom);

      if (canvasRef.current && canvas) {
        const scale = zoom / 100;

        // Update canvas dimensions
        const newWidth = canvasRef.current.offsetWidth * scale;
        const newHeight = canvasRef.current.offsetHeight * scale;

        canvas.setWidth(newWidth);
        canvas.setHeight(newHeight);
        setCanvasWidth(newWidth);
        setCanvasHeight(newHeight);

        canvas.renderAll();
      }
    },
    [canvas, canvasRef, setCanvasHeight, setCanvasWidth]
  );

  useEffect(() => {
    if (!canvas) return;

    const handleMouseDown = (event) => {
      const target = event.target;
      const activeObject = canvas.getActiveObject();

      if (target) {
        if (target.type === "group") {
          setActiveObject(activeObject);
        } else {
          setActiveObject(activeObject);
        }
      } else {
        setActiveObject(activeObject);
      }
    };

    const handleWheel = (event) => {
      if (event.ctrlKey || event.metaKey) {
        event.preventDefault();
        const delta = event.deltaY > 0 ? -1 : 1;
        handleZoom(zoomLevel + delta);
        event.stopPropagation();
      }
    };

    const handleKeyboard = (event) => {
      if (
        (event.ctrlKey || event.metaKey) &&
        (event.key === "=" || event.key === "-")
      ) {
        event.preventDefault();
        const delta = event.key === "=" ? 1 : -1;
        handleZoom(zoomLevel + delta);
      }
    };

    let lastDistance = 0;
    const handleTouchStart = (event) => {
      if (event.touches.length === 2) {
        const touch1 = event.touches[0];
        const touch2 = event.touches[1];
        lastDistance = Math.hypot(
          touch2.clientX - touch1.clientX,
          touch2.clientY - touch1.clientY
        );
      }
    };

    const handleTouchMove = (event) => {
      if (event.touches.length === 2) {
        event.preventDefault();
        const touch1 = event.touches[0];
        const touch2 = event.touches[1];
        const distance = Math.hypot(
          touch2.clientX - touch1.clientX,
          touch2.clientY - touch1.clientY
        );

        if (lastDistance > 0) {
          const delta = distance - lastDistance;
          const zoomDelta = delta > 0 ? 1 : -1;
          handleZoom(zoomLevel + zoomDelta);
        }
        lastDistance = distance;
      }
    };

    const handleTouchEnd = () => {
      lastDistance = 0;
    };

    const handleResize = () => {
      handleZoom(zoomLevel);
    };

    canvas.on("mouse:down", handleMouseDown);
    const canvasContainer = document.getElementById("canvas-ref");

    if (canvasContainer) {
      canvasContainer.addEventListener("wheel", handleWheel, {
        passive: false,
      });
      canvasContainer.addEventListener("touchstart", handleTouchStart);
      canvasContainer.addEventListener("touchmove", handleTouchMove, {
        passive: false,
      });
      canvasContainer.addEventListener("touchend", handleTouchEnd);
      window.addEventListener("keydown", handleKeyboard);
      window.addEventListener("resize", handleResize);
    }

    return () => {
      canvas.off("mouse:down", handleMouseDown);
      if (canvasContainer) {
        canvasContainer.removeEventListener("wheel", handleWheel);
        canvasContainer.removeEventListener("touchstart", handleTouchStart);
        canvasContainer.removeEventListener("touchmove", handleTouchMove);
        canvasContainer.removeEventListener("touchend", handleTouchEnd);
        window.removeEventListener("keydown", handleKeyboard);
        window.removeEventListener("resize", handleResize);
      }
    };
  }, [canvas, setActiveObject, zoomLevel, handleZoom]);

  useEffect(() => {
    import("fabric").then((fabricModule) => {
      window.fabric = fabricModule.fabric;
    });
  }, [canvasRef, fabricCanvasRef, setCanvas]);

  const getRatioValue = (ratio) => {
    const [width, height] = ratio.split(":").map(Number);
    return width / height;
  };

  useEffect(() => {
    const updateCanvasSize = () => {
      if (canvasRef.current && canvas) {
        const newWidth = canvasRef.current.offsetWidth;
        const newHeight = canvasRef.current.offsetHeight;

        canvas.setWidth(newWidth);
        canvas.setHeight(newHeight);
        setCanvasWidth(newWidth);
        setCanvasHeight(newHeight);

        const bgImage = canvas.backgroundImage;
        if (bgImage) {
          const scaleX = newWidth / bgImage.width;
          const scaleY = newHeight / bgImage.height;
          const scale = Math.max(scaleX, scaleY);

          bgImage.scaleX = scale;
          bgImage.scaleY = scale;
          bgImage.left = 0;
          bgImage.top = 0;

          canvas.setBackgroundImage(bgImage, canvas.renderAll.bind(canvas));
        } else {
          canvas.renderAll();
        }
      }

      setScreenWidth(document.getElementById("root").offsetWidth);

      if (document.getElementById("root").offsetWidth <= 640) {
        setLeftPanelOpen(false);
        setRightPanelOpen(false);
      }
      if (document.getElementById("root").offsetWidth > 640) {
        setOpenObjectPanel(false);
        setOpenSetting(false);
      }
    };

    updateCanvasSize();
    window.addEventListener("resize", updateCanvasSize);
    return () => window.removeEventListener("resize", updateCanvasSize);
  }, [
    setCanvasWidth,
    setCanvasHeight,
    canvasRatio,
    canvasRef,
    canvas,
    setLeftPanelOpen,
    setOpenObjectPanel,
    setRightPanelOpen,
    rightPanelOpen,
    setScreenWidth,
    setOpenSetting,
  ]);

  useEffect(() => {
    if (window.fabric) {
      if (fabricCanvasRef?.current) {
        fabricCanvasRef.current.dispose();
      }

      const canvasElement = document.getElementById("fabric-canvas");
      if (canvasElement) {
        canvasElement.classList.add("fabric-canvas-container");
      }

      fabricCanvasRef.current = new window.fabric.Canvas("fabric-canvas", {
        width: canvasRef?.current?.offsetWidth,
        height: canvasRef?.current?.offsetWidth,
        backgroundColor: "#ffffff",
        allowTouchScrolling: true,
        selection: true,
        preserveObjectStacking: true,
      });

      setCanvas(fabricCanvasRef.current);
    }
  }, [canvasRef, fabricCanvasRef, setCanvas]);

  return (
    <>
      {/* Zoom Controls */}
      <div className="fixed bottom-4 right-4 flex items-center gap-4 bg-white p-3 rounded-lg shadow-lg z-50">
        <span className="text-sm font-medium min-w-[45px]">{zoomLevel}%</span>
        <Slider
          value={[zoomLevel]}
          onValueChange={(value) => handleZoom(value[0])}
          min={0}
          max={100}
          step={1}
          className="w-32"
        />
      </div>

      {/* Canvas Container */}
      <div className="w-full max-w-4xl mx-auto p-4">
        <Card
          className={`w-full p-2 rounded-none flex-1 flex flex-col 
          mx-auto pl-5 pb-5 pt-5 border-0 shadow-none bg-transparent mt-20
          ${zoomLevel < 100 ? "overflow-hidden" : ""}`}
        >
          <CardContent
            className="p-0 h-full bg-transparent shadow-none"
            ref={containerRef}
          >
            <AspectRatio
              ratio={getRatioValue(canvasRatio)}
              className="rounded-lg border-0 border-primary/10 transition-all duration-300 ease-in-out"
            >
              <div
                ref={canvasRef}
                className="w-full h-full flex items-start justify-center rounded-md shadow-none touch-none"
                id="canvas-ref"
                style={{
                  touchAction: "none",
                  transform: `scale(${zoomLevel / 100})`,
                  transformOrigin: "50% 0",
                  transition: "transform 0.1s ease-out",
                }}
              >
                <canvas id="fabric-canvas" />
              </div>
            </AspectRatio>
          </CardContent>
        </Card>
      </div>
    </>
  );
}
