import { MathUtils } from 'three';
import { useEffect } from 'react';
import { useThree } from '@react-three/fiber';
import { useParams } from 'react-router-dom';
import { useDroppedDecal, useSocketStore } from '../../../../store/builder/store';
import useModuleStore from '../../../../store/useModuleStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useVersionContext } from '../../version/versionContext';

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

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

function DecalCreator() {
    const { wallStore, floorStore } = useSceneContext();
    const { addDecal: addDecalOnWall, getWallById } = wallStore();
    const { addDecal: addDecalOnFloor, getFloorById } = floorStore();
    const { droppedDecal, setDroppedDecal } = useDroppedDecal();
    const { activeModule } = useModuleStore();
    const { userId, organization } = getUserData();
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { projectId } = useParams();
    const { socket } = 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 && i.object.userData.wallUuid);
                const floorIntersect = intersects.find(i => i.object.userData && 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,
                    }

                    addDecalOnWall(wallIntersect.object.userData.wallUuid, decal);

                    setTimeout(() => {
                        const updatedWall = getWallById(wallIntersect.object.userData.wallUuid);
                        if (updatedWall) {
                            if (projectId) {
                                if (!socket?.active) {
                                    // API

                                    upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
                                } else {

                                    // SOCKET 

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

                                    socket.emit('v1:model-Wall:add', data);
                                }
                            }
                        }
                    }, 0)
                } 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 (!socket?.active) {
                                // API

                                upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
                            } else {

                                // SOCKET

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

                                socket.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