import * as THREE from 'three';
import { useMemo, useRef } from 'react';
import { Extrude } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store';
import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore';

function JunctionAisle({ aisle }: { readonly aisle: Aisle }) {
    const aisleRef = useRef<THREE.Group>(null);
    const { toolMode } = useToolMode();
    const { setSelectedAisle, hoveredPoint } = useBuilderStore();

    const arrows = useMemo(() => {
        if (aisle.points.length < 2 || aisle.type.aisleType !== 'junction-aisle') return null;

        const start = new THREE.Vector3(...aisle.points[0].position);
        const end = new THREE.Vector3(...aisle.points[1].position);
        const width = aisle.type.aisleWidth || 0.1;
        const isFlipped = aisle.type.isFlipped || false;

        const direction = new THREE.Vector3().subVectors(end, start);
        const length = direction.length();
        direction.normalize();

        const mainShape = new THREE.Shape();
        const arrowHeadLength = width * 2;
        const shaftLength = length - arrowHeadLength;

        if (shaftLength > 0) {
            mainShape.moveTo(0, 0);
            mainShape.lineTo(width, -arrowHeadLength);
            mainShape.lineTo(width / 2, -arrowHeadLength);
            mainShape.lineTo(width / 2, -length);
            mainShape.lineTo(-width / 2, -length);
            mainShape.lineTo(-width / 2, -arrowHeadLength);
            mainShape.lineTo(-width, -arrowHeadLength);
            mainShape.lineTo(0, 0);
        } else {
            mainShape.moveTo(0, 0);
            mainShape.lineTo(width, -length);
            mainShape.lineTo(-width, -length);
            mainShape.lineTo(0, 0);
        }
        mainShape.closePath();

        const secondaryLength = length / 4;
        const secondaryShape = new THREE.Shape();
        const secondaryHeadLength = width * 2;
        const secondaryShaftLength = secondaryLength - secondaryHeadLength;

        if (secondaryShaftLength > 0) {
            secondaryShape.moveTo(0, 0);
            secondaryShape.lineTo(width / 2, 0);
            secondaryShape.lineTo(width / 2, secondaryShaftLength);
            secondaryShape.lineTo(width, secondaryShaftLength);
            secondaryShape.lineTo(0, secondaryLength);
            secondaryShape.lineTo(-width, secondaryShaftLength);
            secondaryShape.lineTo(-width / 2, secondaryShaftLength);
            secondaryShape.lineTo(-width / 2, 0);
            secondaryShape.lineTo(0, 0);
        } else {
            secondaryShape.moveTo(0, 0);
            secondaryShape.lineTo(width, 0);
            secondaryShape.lineTo(0, secondaryLength);
            secondaryShape.lineTo(-width, 0);
            secondaryShape.lineTo(0, 0);
        }
        secondaryShape.closePath();

        const mainPosition = end;
        const mainAngle = Math.atan2(direction.x, direction.z);

        const perpendicularDirection = isFlipped
            ? new THREE.Vector3(direction.z, 0, -direction.x).normalize()
            : new THREE.Vector3(-direction.z, 0, direction.x).normalize();

        const secondaryAngle = Math.atan2(perpendicularDirection.x, perpendicularDirection.z);

        const secondaryPosition = new THREE.Vector3().lerpVectors(start, end, 0.75);

        return [
            { shape: mainShape, position: mainPosition, rotationY: mainAngle },
            { shape: secondaryShape, position: secondaryPosition, rotationY: secondaryAngle + Math.PI }
        ];
    }, [aisle]);

    const handleClick = () => {
        if (toolMode === 'move' && !hoveredPoint) {
            setSelectedAisle(aisleRef.current);
        }
    }

    if (!arrows) return null;

    return (
        <group
            name='Junction-Aisle'
            uuid={aisle.aisleUuid}
            ref={aisleRef}
            position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]}
            rotation={[Math.PI / 2, 0, 0]}
            userData={aisle}
            onDoubleClick={handleClick}
            onPointerMissed={() => {
                setSelectedAisle(null);
            }}
        >
            {arrows.map((arrow, index) => (
                <group key={index} position={[arrow.position.x, arrow.position.z, 0]} rotation={[0, 0, -arrow.rotationY]}>
                    <Extrude
                        args={[arrow.shape, { depth: 0.01, bevelEnabled: false }]}
                        receiveShadow
                        castShadow
                    >
                        <meshStandardMaterial
                            color={aisle.type.aisleColor || '#ffffff'}
                            side={THREE.DoubleSide}
                        />
                    </Extrude>
                </group>
            ))}
        </group>
    );
}

export default JunctionAisle;