import * as THREE from 'three';
import * as Constants from '../../../types/world/worldConstants';
import { useRef, useState, useEffect, useMemo } from 'react';
import { useSocketStore, useToolMode } from '../../../store/builder/store';
import { DragControls } from '@react-three/drei';
import { useThree } from '@react-three/fiber';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useSelectedPoints } from '../../../store/simulation/useSimulationStore';
import { usePointSnapping } from './helpers/usePointSnapping';
import { useParams } from 'react-router-dom';
import { useVersionContext } from '../version/versionContext';
import { useSceneContext } from '../../scene/sceneContext';

// import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
// import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
// import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
// import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
// import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
// import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';

import { getUserData } from '../../../functions/getUserData';
import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
import { calculateAssetTransformationOnWall } from '../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall';

function Point({ point }: { readonly point: Point }) {
    const materialRef = useRef<THREE.ShaderMaterial>(null);
    const { raycaster, camera, pointer } = useThree();
    const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
    const [isHovered, setIsHovered] = useState(false);
    const [isSelected, setIsSelected] = useState(false);
    const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
    const { socket } = useSocketStore();
    const { toolMode } = useToolMode();
    const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore } = useSceneContext();
    const { push2D } = undoRedo2DStore();
    const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
    const { setPosition: setWallPosition, removePoint: removeWallPoint, getWallsByPointId } = wallStore();
    const { setPosition: setFloorPosition, removePoint: removeFloorPoint, getFloorsByPointId } = floorStore();
    const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore();
    const { getWallAssetsByWall, updateWallAsset, removeWallAsset } = wallAssetStore();
    const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
    const { hoveredPoint, hoveredLine, setHoveredPoint } = useBuilderStore();
    const { selectedPoints } = useSelectedPoints();
    const { userId, organization } = getUserData();
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { projectId } = useParams();
    const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
    const colors = getColor(point);

    const [initialStates, setInitialStates] = useState<{
        aisles?: Aisle[],
        walls?: Wall[],
        floors?: Floor[],
        zones?: Zone[]
    }>({});

    useEffect(() => {
        handleCanvasCursors('default');
    }, [toolMode])

    function getColor(point: Point) {
        if (point.pointType === 'Aisle') {
            return {
                defaultInnerColor: Constants.pointConfig.defaultInnerColor,
                defaultOuterColor: Constants.pointConfig.aisleOuterColor,
                defaultDeleteColor: Constants.pointConfig.deleteColor,
            }
        } else if (point.pointType === 'Floor') {
            return {
                defaultInnerColor: Constants.pointConfig.defaultInnerColor,
                defaultOuterColor: Constants.pointConfig.floorOuterColor,
                defaultDeleteColor: Constants.pointConfig.deleteColor,
            }
        } else if (point.pointType === 'Wall') {
            return {
                defaultInnerColor: Constants.pointConfig.defaultInnerColor,
                defaultOuterColor: Constants.pointConfig.wallOuterColor,
                defaultDeleteColor: Constants.pointConfig.deleteColor,
            }
        } else if (point.pointType === 'Zone') {
            return {
                defaultInnerColor: Constants.pointConfig.defaultInnerColor,
                defaultOuterColor: Constants.pointConfig.zoneOuterColor,
                defaultDeleteColor: Constants.pointConfig.deleteColor,
            }
        } else {
            return {
                defaultInnerColor: Constants.pointConfig.defaultInnerColor,
                defaultOuterColor: Constants.pointConfig.defaultOuterColor,
                defaultDeleteColor: Constants.pointConfig.deleteColor,
            }
        }
    }

    useEffect(() => {
        if (materialRef.current && (toolMode === 'move' || toolMode === '2D-Delete')) {
            let innerColor;
            let outerColor;
            if (isHovered) {
                innerColor = toolMode === '2D-Delete' ? colors.defaultDeleteColor : colors.defaultOuterColor;
                outerColor = toolMode === '2D-Delete' ? colors.defaultDeleteColor : colors.defaultOuterColor;
            } else {
                innerColor = colors.defaultInnerColor;
                outerColor = colors.defaultOuterColor;
            }
            materialRef.current.uniforms.uInnerColor.value.set(innerColor);
            materialRef.current.uniforms.uOuterColor.value.set(outerColor);
            materialRef.current.uniformsNeedUpdate = true;
        } else if (materialRef.current && toolMode !== 'move') {
            materialRef.current.uniforms.uInnerColor.value.set(colors.defaultInnerColor);
            materialRef.current.uniforms.uOuterColor.value.set(colors.defaultOuterColor);
            materialRef.current.uniformsNeedUpdate = true;
        }
    }, [isHovered, colors.defaultInnerColor, colors.defaultOuterColor, colors.defaultDeleteColor, toolMode]);

    const uniforms = useMemo(() => ({
        uOuterColor: { value: new THREE.Color(colors.defaultOuterColor) },
        uInnerColor: { value: new THREE.Color(colors.defaultInnerColor) },
    }), [colors.defaultInnerColor, colors.defaultOuterColor]);

    const handleDrag = (point: Point) => {
        if (toolMode === 'move' && isHovered && dragOffset) {
            raycaster.setFromCamera(pointer, camera);
            const intersectionPoint = new THREE.Vector3();
            const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);

            if (hit) {
                handleCanvasCursors('grabbing');
                const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
                const newPosition: [number, number, number] = [positionWithOffset.x, positionWithOffset.y, positionWithOffset.z];

                if (point.pointType === 'Aisle') {
                    const aisleSnapped = snapAisleAngle(newPosition);
                    const finalSnapped = snapAislePoint(aisleSnapped.position);
                    setAislePosition(point.pointUuid, finalSnapped.position);
                } else if (point.pointType === 'Wall') {
                    const wallSnapped = snapWallAngle(newPosition);
                    const finalSnapped = snapWallPoint(wallSnapped.position);
                    setWallPosition(point.pointUuid, finalSnapped.position);
                } else if (point.pointType === 'Floor') {
                    const floorSnapped = snapFloorAngle(newPosition);
                    const finalSnapped = snapFloorPoint(floorSnapped.position);
                    setFloorPosition(point.pointUuid, finalSnapped.position);
                } else if (point.pointType === 'Zone') {
                    const zoneSnapped = snapZoneAngle(newPosition);
                    const finalSnapped = snapZonePoint(zoneSnapped.position);
                    setZonePosition(point.pointUuid, finalSnapped.position);
                }
            }
        }
    };

    const handleDragStart = (point: Point) => {
        raycaster.setFromCamera(pointer, camera);
        const intersectionPoint = new THREE.Vector3();
        const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);

        if (hit) {
            const currentPosition = new THREE.Vector3(...point.position);
            const offset = new THREE.Vector3().subVectors(currentPosition, hit);
            setDragOffset(offset);

            if (point.pointType === 'Aisle') {
                const aisles = getAislesByPointId(point.pointUuid);
                setInitialStates({ aisles });
            } else if (point.pointType === 'Wall') {
                const walls = getWallsByPointId(point.pointUuid);
                setInitialStates({ walls });
            } else if (point.pointType === 'Floor') {
                const floors = getFloorsByPointId(point.pointUuid);
                setInitialStates({ floors });
            } else if (point.pointType === 'Zone') {
                const zones = getZonesByPointId(point.pointUuid);
                setInitialStates({ zones });
            }
        }
    };

    const handleDragEnd = (point: Point) => {
        handleCanvasCursors('default');
        setDragOffset(null);
        if (toolMode !== 'move') return;

        if (point.pointType === 'Aisle') {
            const updatedAisles = getAislesByPointId(point.pointUuid);
            if (updatedAisles.length > 0 && projectId) {
                updatedAisles.forEach((updatedAisle) => {

                    // API

                    // upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');

                    // SOCKET 

                    socket.emit('v1:model-aisle:add', {
                        projectId: projectId,
                        versionId: selectedVersion?.versionId || '',
                        userId: userId,
                        organization: organization,
                        aisleUuid: updatedAisle.aisleUuid,
                        points: updatedAisle.points,
                        type: updatedAisle.type
                    })
                })

                if (initialStates.aisles && initialStates.aisles.length > 0) {
                    const updatedPoints = initialStates.aisles.map((aisle) => ({
                        type: "Aisle" as const,
                        lineData: aisle,
                        newData: updatedAisles.find(a => a.aisleUuid === aisle.aisleUuid),
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [{
                            actionType: 'Lines-Update',
                            points: updatedPoints,
                        }]
                    });
                }
            }
        } else if (point.pointType === 'Wall') {
            const updatedWalls = getWallsByPointId(point.pointUuid);
            if (updatedWalls && updatedWalls.length > 0 && projectId) {
                updatedWalls.forEach((updatedWall) => {

                    const initialWall = initialStates.walls?.find(w => w.wallUuid === updatedWall.wallUuid);

                    if (initialWall) {
                        const assetsOnWall = getWallAssetsByWall(updatedWall.wallUuid);

                        assetsOnWall.forEach(asset => {
                            const { position, rotation } = calculateAssetTransformationOnWall(asset, initialWall, updatedWall);

                            const updatedWallAsset = updateWallAsset(asset.modelUuid, {
                                position: [position[0], asset.position[1], position[2]],
                                rotation: rotation
                            });

                            if (projectId && updatedWallAsset) {
                                // API

                                // upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);

                                // SOCKET

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

                                socket.emit('v1:wall-asset:add', data);
                            }
                        });
                    }

                    // API

                    // upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);

                    // SOCKET 

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

                    socket.emit('v1:model-Wall:add', data);
                });
            }

            if (initialStates.walls && initialStates.walls.length > 0) {
                const updatedPoints = initialStates.walls.map((wall) => ({
                    type: "Wall" as const,
                    lineData: wall,
                    newData: updatedWalls.find(w => w.wallUuid === wall.wallUuid),
                    timeStamp: new Date().toISOString(),
                }));

                push2D({
                    type: 'Draw',
                    actions: [{
                        actionType: 'Lines-Update',
                        points: updatedPoints,
                    }]
                });
            }
        } else if (point.pointType === 'Floor') {
            const updatedFloors = getFloorsByPointId(point.pointUuid);
            if (updatedFloors && updatedFloors.length > 0 && projectId) {
                updatedFloors.forEach((updatedFloor) => {

                    // API

                    // upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);

                    // SOCKET

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

                    socket.emit('v1:model-Floor:add', data);
                });
            }

            if (initialStates.floors && initialStates.floors.length > 0) {
                const updatedPoints = initialStates.floors.map((floor) => ({
                    type: "Floor" as const,
                    lineData: floor,
                    newData: updatedFloors.find(f => f.floorUuid === floor.floorUuid),
                    timeStamp: new Date().toISOString(),
                }));

                push2D({
                    type: 'Draw',
                    actions: [{
                        actionType: 'Lines-Update',
                        points: updatedPoints,
                    }]
                });
            }
        } else if (point.pointType === 'Zone') {
            const updatedZones = getZonesByPointId(point.pointUuid);
            if (updatedZones && updatedZones.length > 0 && projectId) {
                updatedZones.forEach((updatedZone) => {

                    // API

                    // upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);

                    // SOCKET

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

                    socket.emit('v1:zone:add', data);
                });
            }

            if (initialStates.zones && initialStates.zones.length > 0) {
                const updatedPoints = initialStates.zones.map((zone) => ({
                    type: "Zone" as const,
                    lineData: zone,
                    newData: updatedZones.find(z => z.zoneUuid === zone.zoneUuid),
                    timeStamp: new Date().toISOString(),
                }));

                push2D({
                    type: 'Draw',
                    actions: [{
                        actionType: 'Lines-Update',
                        points: updatedPoints,
                    }]
                });
            }
        }

        setInitialStates({});
    }

    const handlePointClick = (point: Point) => {
        if (toolMode === '2D-Delete') {
            if (point.pointType === 'Aisle') {
                const removedAisles = removeAislePoint(point.pointUuid);
                setHoveredPoint(null);
                if (removedAisles.length > 0) {
                    removedAisles.forEach(aisle => {
                        if (projectId) {

                            // API

                            // deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');

                            // SOCKET

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

                            socket.emit('v1:model-aisle:delete', data);

                        }
                    });

                    const removedAislesData = removedAisles.map((aisle) => ({
                        type: "Aisle" as const,
                        lineData: aisle,
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [
                            {
                                actionType: 'Lines-Delete',
                                points: removedAislesData
                            }
                        ]
                    });
                }
            }
            if (point.pointType === 'Wall') {
                const removedWalls = removeWallPoint(point.pointUuid);
                if (removedWalls.length > 0) {
                    setHoveredPoint(null);
                    removedWalls.forEach(wall => {
                        const assetsOnWall = getWallAssetsByWall(wall.wallUuid);

                        assetsOnWall.forEach((asset) => {
                            if (projectId && asset) {

                                removeWallAsset(asset.modelUuid);

                                // API

                                // deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);

                                // SOCKET

                                const data = {
                                    projectId: projectId,
                                    versionId: selectedVersion?.versionId || '',
                                    userId: userId,
                                    organization: organization,
                                    modelUuid: asset.modelUuid,
                                    wallUuid: asset.wallUuid
                                }

                                socket.emit('v1:wall-asset:delete', data);

                            }
                        })

                        if (projectId) {

                            // API

                            // deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);

                            // SOCKET

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

                            socket.emit('v1:model-Wall:delete', data);
                        }
                    });

                    const removedWallsData = removedWalls.map((wall) => ({
                        type: "Wall" as const,
                        lineData: wall,
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [
                            {
                                actionType: 'Lines-Delete',
                                points: removedWallsData
                            }
                        ]
                    });
                }
            }
            if (point.pointType === 'Floor') {
                const Floors = getFloorsByPointId(point.pointUuid);
                const { removedFloors, updatedFloors } = removeFloorPoint(point.pointUuid);
                setHoveredPoint(null);
                if (removedFloors.length > 0) {
                    removedFloors.forEach(floor => {
                        if (projectId) {

                            // API

                            // deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);

                            // SOCKET

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

                            socket.emit('v1:model-Floor:delete', data);
                        }
                    });

                    const removedFloorsData = removedFloors.map((floor) => ({
                        type: "Floor" as const,
                        lineData: floor,
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [
                            {
                                actionType: 'Lines-Delete',
                                points: removedFloorsData
                            }
                        ]
                    });
                }
                if (updatedFloors.length > 0) {
                    updatedFloors.forEach(floor => {
                        if (projectId) {

                            // API

                            // upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);

                            // SOCKET

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

                            socket.emit('v1:model-Floor:add', data);
                        }
                    });

                    const updatedFloorsData = updatedFloors.map((floor) => ({
                        type: "Floor" as const,
                        lineData: Floors.find(f => f.floorUuid === floor.floorUuid) || floor,
                        newData: floor,
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [
                            {
                                actionType: 'Lines-Update',
                                points: updatedFloorsData
                            }
                        ]
                    });
                }
            }
            if (point.pointType === 'Zone') {
                const Zones = getZonesByPointId(point.pointUuid);
                const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
                setHoveredPoint(null);
                if (removedZones.length > 0) {
                    removedZones.forEach(zone => {
                        if (projectId) {

                            // API

                            // deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);

                            // SOCKET

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

                            socket.emit('v1:zone:delete', data);
                        }
                    });

                    const removedZonesData = removedZones.map((zone) => ({
                        type: "Zone" as const,
                        lineData: zone,
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [
                            {
                                actionType: 'Lines-Delete',
                                points: removedZonesData
                            }
                        ]
                    });
                }
                if (updatedZones.length > 0) {
                    updatedZones.forEach(zone => {
                        if (projectId) {

                            // API

                            // upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);

                            // SOCKET

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

                            socket.emit('v1:zone:add', data);
                        }
                    });

                    const updatedZonesData = updatedZones.map((zone) => ({
                        type: "Zone" as const,
                        lineData: Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone,
                        newData: zone,
                        timeStamp: new Date().toISOString(),
                    }));

                    push2D({
                        type: 'Draw',
                        actions: [
                            {
                                actionType: 'Lines-Update',
                                points: updatedZonesData
                            }
                        ]
                    });
                }
            }
            handleCanvasCursors('default');
        }
    }

    useEffect(() => {
        if (hoveredPoint && hoveredPoint.pointUuid !== point.pointUuid) {
            setIsHovered(false);
        }
    }, [hoveredPoint])

    useEffect(() => {
        if (selectedPoints.length > 0 && selectedPoints.some((selectedPoint) => (selectedPoint.userData.pointUuid && selectedPoint.userData.pointUuid === point.pointUuid))) {
            setIsSelected(true);
        } else {
            setIsSelected(false);
        }
    }, [selectedPoints])

    if (!point) {
        return null;
    }

    return (
        <>
            {!isSelected ?
                <DragControls
                    axisLock='y'
                    autoTransform={false}
                    onDragStart={() => handleDragStart(point)}
                    onDrag={() => handleDrag(point)}
                    onDragEnd={() => handleDragEnd(point)}
                >
                    <mesh
                        key={point.pointUuid}
                        uuid={point.pointUuid}
                        name={`${point.pointType}-Point`}
                        position={[...point.position]}
                        onClick={(e) => {
                            e.stopPropagation();
                            handlePointClick(point);
                        }}
                        onPointerOver={(e) => {
                            if (!hoveredPoint && selectedPoints.length === 0 && e.buttons === 0 && !e.ctrlKey) {
                                setHoveredPoint(point);
                                setIsHovered(true);
                                if (toolMode === 'move') {
                                    handleCanvasCursors('grab');
                                }
                            }
                        }}
                        onPointerOut={() => {
                            if (hoveredPoint) {
                                setHoveredPoint(null);
                                if (!hoveredLine) {
                                    handleCanvasCursors('default');
                                }
                            }
                            setIsHovered(false)
                        }}
                        userData={point}
                    >
                        <boxGeometry args={boxScale} />
                        <shaderMaterial
                            ref={materialRef}
                            uniforms={uniforms}
                            vertexShader={
                                `
                            varying vec2 vUv;

                            void main() {
                                vUv = uv;
                                gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                            }
                        `
                            }
                            fragmentShader={
                                `
                            varying vec2 vUv;
                            uniform vec3 uOuterColor;
                            uniform vec3 uInnerColor;
                            
                            void main() {
                                // Define the size of the white square as a proportion of the face
                                float borderThickness = 0.2; // Adjust this value for border thickness
                                if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
                                    gl_FragColor = vec4(uInnerColor, 1.0); // Inner square
                                } else {
                                        gl_FragColor = vec4(uOuterColor, 1.0); // Border
                                    }
                                }
                        `
                            }
                        />
                    </mesh>
                </DragControls>
                :
                <group
                    key={point.pointUuid}
                    uuid={point.pointUuid}
                    name={`${point.pointType}-Point`}
                    position={[point.position[0], 0.3, point.position[2]]}
                    userData={point}
                    rotation={[Math.PI / 2, 0, 0]}
                >
                    <mesh>
                        <torusGeometry args={[0.4, 0.1, 2, 16]} />
                        <meshBasicMaterial color="#6F42C1" />
                    </mesh>

                    <mesh position={[0, 0, 0]}>
                        <sphereGeometry args={[0.3, 8, 16]} />
                        <meshBasicMaterial color="white" />
                    </mesh>
                </group>
            }
        </>
    );
}

export default Point;