import { MathUtils } from "three";
import { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import { useParams } from "react-router-dom";
import { useSocketStore } from "../../../../store/socket/useSocketStore";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { useSceneContext } from "../../../scene/sceneContext";
import useModuleStore from "../../../../store/ui/useModuleStore";
import useWallResponseHandler from "../../../collaboration/responseHandler/useWallResponseHandler";

import { getUserData } from "../../../../functions/getUserData";

import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";

function DecalCreator() {
    const { wallStore, floorStore, versionStore } = useSceneContext();
    const { peekAddDecal: peekAddDecalOnWall, getWallById } = wallStore();
    const { addDecal: addDecalOnFloor, getFloorById } = floorStore();
    const { updateWallInScene } = useWallResponseHandler();
    const { droppedDecal, setDroppedDecal } = useBuilderStore();
    const { activeModule } = useModuleStore();
    const { userId, organization } = getUserData();
    const { selectedVersion } = versionStore();
    const { projectId } = useParams();
    const { builderSocket } = useSocketStore();
    const { controls, gl, pointer, camera, raycaster, scene } = useThree();

    useEffect(() => {
        const canvasElement = gl.domElement;

        const onDrop = (event: DragEvent) => {
            if (droppedDecal) {
                setDroppedDecal(null);
                pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
                pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
                raycaster.setFromCamera(pointer, camera);
                const intersects = raycaster.intersectObjects(scene.children, true);
                const wallIntersect = intersects.find((i) => i.object.userData.wallUuid);
                const floorIntersect = intersects.find((i) => i.object.userData.floorUuid);

                if (wallIntersect) {
                    const wall = getWallById(wallIntersect.object.userData.wallUuid);
                    if (!wall) return;

                    const point = wallIntersect.object.worldToLocal(wallIntersect.point.clone());

                    const decal: Decal = {
                        decalUuid: MathUtils.generateUUID(),
                        decalName: droppedDecal.decalName,
                        decalId: droppedDecal.decalId,
                        decalType: {
                            type: "Wall",
                            wallUuid: wallIntersect.object.userData.wallUuid,
                        },
                        decalPosition: [point.x, point.y, (wall.wallThickness / 2 + 0.001) * (wallIntersect.normal?.z || 1)],
                        decalRotation: 0,
                        decalOpacity: 1,
                        decalScale: 0.5,
                    };

                    const updatedWall = peekAddDecalOnWall(wallIntersect.object.userData.wallUuid, decal);
                    if (updatedWall) {
                        if (projectId) {
                            if (!builderSocket?.connected) {
                                // API

                                upsertWallApi(projectId, selectedVersion?.versionId || "", updatedWall)
                                    .then((data) => {
                                        if (!data.message || !data.data) {
                                            echo.error(`Error adding decal`);
                                            return;
                                        }
                                        if (data.message === "Wall Updated Successfully") {
                                            updateWallInScene(updatedWall, () => {
                                                echo.log(`Decal Added`);
                                            });
                                        } else {
                                            echo.error(`Error adding decal`);
                                        }
                                    })
                                    .catch(() => {
                                        echo.error(`Error adding decal`);
                                    });
                            } else {
                                // SOCKET

                                const data = {
                                    wallData: updatedWall,
                                    projectId: projectId,
                                    versionId: selectedVersion?.versionId || "",
                                    userId: userId,
                                    organization: organization,
                                };

                                builderSocket.emit("v1:model-Wall:add", data);
                            }
                        }
                    }
                } else if (floorIntersect) {
                    const floor = getFloorById(floorIntersect.object.userData.floorUuid);
                    if (!floor) return;

                    const point = floorIntersect.object.worldToLocal(floorIntersect.point.clone());

                    const decal: Decal = {
                        decalUuid: MathUtils.generateUUID(),
                        decalName: droppedDecal.decalName,
                        decalId: droppedDecal.decalId,
                        decalType: {
                            type: "Floor",
                            floorUuid: floorIntersect.object.userData.floorUuid,
                        },
                        decalPosition: [point.x, point.y, -0.001],
                        decalRotation: 0,
                        decalOpacity: 1,
                        decalScale: 0.5,
                    };

                    addDecalOnFloor(floorIntersect.object.userData.floorUuid, decal);

                    setTimeout(() => {
                        const updatedFloor = getFloorById(floorIntersect.object.userData.floorUuid);
                        if (projectId && updatedFloor) {
                            if (!builderSocket?.connected) {
                                // API

                                upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedFloor);
                            } else {
                                // SOCKET

                                const data = {
                                    floorData: updatedFloor,
                                    projectId: projectId,
                                    versionId: selectedVersion?.versionId || "",
                                    userId: userId,
                                    organization: organization,
                                };

                                builderSocket.emit("v1:model-Floor:add", data);
                            }
                        }
                    }, 0);
                }
            }
        };

        const onDragOver = (event: any) => {
            event.preventDefault();
        };

        if (activeModule === "builder") {
            canvasElement.addEventListener("drop", onDrop);
            canvasElement.addEventListener("dragover", onDragOver);
        }

        return () => {
            canvasElement.removeEventListener("drop", onDrop);
            canvasElement.removeEventListener("dragover", onDragOver);
        };
    }, [droppedDecal, camera, activeModule, controls]);

    return <></>;
}

export default DecalCreator;
