import { useEffect, useMemo, useState } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";

const IKAnimationController = ({
    ikSolver,
    process,
    selectedTrigger,
    targetBoneName,
}: {
    ikSolver: any;
    process: {
        trigger: string;
        start: THREE.Vector3;
        end: THREE.Vector3;
        speed: number;
    }[];
    selectedTrigger: string;
    targetBoneName: string;
}) => {
    const [progress, setProgress] = useState(0);
    const restSpeed = 0.1;

    useEffect(() => {
        setProgress(0);
    }, [selectedTrigger]);

    const processedCurves = useMemo(() => {
        const restPosition = new THREE.Vector3(0.2, 2.3, 1.6);
        return process.map((p) => {
            const mid = new THREE.Vector3(
                (p.start.x + p.end.x) / 1,
                Math.max(p.start.y, p.end.y) + 0.8,
                (p.start.z + p.end.z) / 0.9
            );
            const points = [
                restPosition.clone(),
                p.start.clone(),
                mid.clone(),
                p.end.clone(),
                restPosition.clone(),
            ];
            const curve = new THREE.CatmullRomCurve3(points);
            const restToStartDist = points[0].distanceTo(points[1]);
            const startToEndDist = points[1].distanceTo(points[3]);
            const endToRestDist = points[3].distanceTo(points[4]);

            const totalDist = restToStartDist + startToEndDist + endToRestDist;
            const restToStartRange = [0, restToStartDist / totalDist];
            const startToEndRange = [
                restToStartRange[1],
                restToStartRange[1] + startToEndDist / totalDist,
            ];
            const endToRestRange = [startToEndRange[1], 1];

            return {
                trigger: p.trigger,
                curve,
                speed: p.speed,
                restToStartRange,
                startToEndRange,
                endToRestRange,
            };
        });
    }, [process]);

    const activeCurve = useMemo(() => {
        return processedCurves.find((c) => c.trigger === selectedTrigger);
    }, [processedCurves, selectedTrigger]);

    useFrame((_, delta) => {
        if (!ikSolver || !activeCurve) return;

        const { curve, speed, startToEndRange } = activeCurve;
        const targetBone = ikSolver.mesh.skeleton.bones.find(
            (b: any) => b.name === targetBoneName
        );
        if (!targetBone) return;

        let currentSpeed = restSpeed;
        if (progress >= startToEndRange[0] && progress < startToEndRange[1]) {
            currentSpeed = speed;
        }

        setProgress((prev) => {
            const next = prev + delta * currentSpeed;
            if (next >= 1) {
                targetBone.position.copy(curve.getPoint(1));
                return 1;
            }
            targetBone.position.copy(curve.getPoint(next));
            return next;
        });

        ikSolver.update();
    });

    return null;
};

export default IKAnimationController;