import { useCallback } from 'react';
import * as THREE from 'three';
import { useAisleStore } from '../../../../store/builder/useAisleStore';

const SNAP_DISTANCE_THRESHOLD = 0.5;  // Distance threshold for snapping in meters

const CAN_SNAP = true; // Whether snapping is enabled or not

export function useAislePointSnapping(point: Point) {
    const { getConnectedPoints } = useAisleStore();

    const snapPosition = useCallback((newPosition: [number, number, number]): {
        position: [number, number, number],
        isSnapped: boolean,
        snapSources: THREE.Vector3[]
    } => {
        if (!CAN_SNAP) return { position: newPosition, isSnapped: false, snapSources: [] };

        const connectedPoints = getConnectedPoints(point.pointUuid);
        if (connectedPoints.length === 0) {
            return {
                position: newPosition,
                isSnapped: false,
                snapSources: []
            };
        }

        const newPos = new THREE.Vector3(...newPosition);
        let closestX: { pos: THREE.Vector3, dist: number } | null = null;
        let closestZ: { pos: THREE.Vector3, dist: number } | null = null;

        for (const connectedPoint of connectedPoints) {
            const cPos = new THREE.Vector3(...connectedPoint.position);

            const xDist = Math.abs(newPos.x - cPos.x);
            const zDist = Math.abs(newPos.z - cPos.z);

            if (xDist < SNAP_DISTANCE_THRESHOLD) {
                if (!closestX || xDist < closestX.dist) {
                    closestX = { pos: cPos, dist: xDist };
                }
            }

            if (zDist < SNAP_DISTANCE_THRESHOLD) {
                if (!closestZ || zDist < closestZ.dist) {
                    closestZ = { pos: cPos, dist: zDist };
                }
            }
        }

        const snappedPos = newPos.clone();
        const snapSources: THREE.Vector3[] = [];

        if (closestX) {
            snappedPos.x = closestX.pos.x;
            snapSources.push(closestX.pos.clone());
        }

        if (closestZ) {
            snappedPos.z = closestZ.pos.z;
            snapSources.push(closestZ.pos.clone());
        }

        const isSnapped = snapSources.length > 0;

        return {
            position: [snappedPos.x, snappedPos.y, snappedPos.z],
            isSnapped,
            snapSources
        };
    }, [point.pointUuid, getConnectedPoints]);

    return { snapPosition };
}
