import { useSceneContext } from "../../../scene/sceneContext";
import { extractTriggersFromPoint } from "./extractTriggersFromPoint";

export function getRoboticArmSequencesInProduct(
    product: {
        productName: string;
        productUuid: string;
        eventDatas: EventsSchema[];
    }
): EventsSchema[][][] {
    // Get all machine sequences for this product
    const machineSequences = determineExecutionMachineSequences([product]);

    const allRoboticArmSequences: EventsSchema[][][] = [];

    // Process each machine sequence separately
    for (const machineSequence of machineSequences) {
        const roboticArmSequencesForThisMachineSequence: EventsSchema[][] = [];
        let currentRoboticArmSequence: EventsSchema[] = [];

        for (const event of machineSequence) {
            if (event.type === 'roboticArm') {
                // Add robotic arm to current sequence
                currentRoboticArmSequence.push(event);
            } else if (event.type === 'vehicle') {
                // Vehicle encountered - split the sequence
                if (currentRoboticArmSequence.length > 0) {
                    roboticArmSequencesForThisMachineSequence.push([...currentRoboticArmSequence]);
                    currentRoboticArmSequence = [];
                }
            }
            // Other machine types continue the current sequence
        }

        // Add any remaining robotic arms in the current sequence
        if (currentRoboticArmSequence.length > 0) {
            roboticArmSequencesForThisMachineSequence.push([...currentRoboticArmSequence]);
        }

        if (roboticArmSequencesForThisMachineSequence.length > 0) {
            allRoboticArmSequences.push(roboticArmSequencesForThisMachineSequence);
        }
    }

    return allRoboticArmSequences;
}

export function findRoboticArmSubsequence(
    product: {
        productName: string;
        productUuid: string;
        eventDatas: EventsSchema[];
    },
    roboticArmModelUuid: string
): {
    allSequences: EventsSchema[][][];
    parentSequence: EventsSchema[][];
    currentSubSequence: EventsSchema[];
} | null {
    const allSequences = getRoboticArmSequencesInProduct(product);

    for (const parentSequence of allSequences) {
        for (const currentSubSequence of parentSequence) {
            const hasTargetRoboticArm = currentSubSequence.some(
                event => event.type === 'roboticArm' && event.modelUuid === roboticArmModelUuid
            );

            if (hasTargetRoboticArm) {
                return {
                    allSequences,
                    parentSequence,
                    currentSubSequence
                };
            }
        }
    }

    return null;
}

// React component/hook that uses the pure functions
export function useCheckActiveRoboticArmsInSubsequence() {
    const {armBotStore} = useSceneContext();
    const { getArmBotById } = armBotStore();

    return function (product: {
        productName: string;
        productUuid: string;
        eventDatas: EventsSchema[];
    }, roboticArmModelUuid: string) {
        const result = findRoboticArmSubsequence(product, roboticArmModelUuid);

        if (!result) return null;

        const hasActiveRoboticArm = result.currentSubSequence.some(event => {
            if (event.type === 'roboticArm' && event.modelUuid !== roboticArmModelUuid) {
                const armBot = getArmBotById(event.modelUuid);
                return armBot?.isActive;
            }
            return false;
        });

        return {
            ...result,
            hasActiveRoboticArm
        };
    };
}

// Helper function to get machine sequences (simplified from your example)
function determineExecutionMachineSequences(products: productsSchema): EventsSchema[][] {
    const pointToEventMap = new Map<string, EventsSchema>();
    const allPoints: PointsScheme[] = [];

    // First pass: map points to their corresponding events
    products.forEach(product => {
        product.eventDatas.forEach(event => {
            if (event.type === 'transfer') {
                event.points.forEach(point => {
                    pointToEventMap.set(point.uuid, event);
                    allPoints.push(point);
                });
            } else if (
                event.type === 'vehicle' ||
                event.type === 'machine' ||
                event.type === 'storageUnit' ||
                event.type === 'roboticArm' ||
                event.type === 'human'
            ) {
                pointToEventMap.set(event.point.uuid, event);
                allPoints.push(event.point);
            }
        });
    });

    // Build dependency graph
    const dependencyGraph = new Map<string, string[]>();
    const triggeredPoints = new Set<string>();

    allPoints.forEach(point => {
        const triggers = extractTriggersFromPoint(point);
        const dependencies: string[] = [];

        triggers.forEach(trigger => {
            const targetUuid = trigger.triggeredAsset?.triggeredPoint?.pointUuid;
            if (targetUuid && pointToEventMap.has(targetUuid)) {
                dependencies.push(targetUuid);
                triggeredPoints.add(targetUuid);
            }
        });

        dependencyGraph.set(point.uuid, dependencies);
    });

    // Find root points (points that aren't triggered by others)
    const rootPoints = allPoints.filter(point =>
        !triggeredPoints.has(point.uuid) &&
        dependencyGraph.get(point.uuid)?.length
    );

    const executionSequences: EventsSchema[][] = [];

    function buildSequence(startUuid: string): EventsSchema[] {
        const sequence: EventsSchema[] = [];
        const visited = new Set<string>();

        function traverse(uuid: string) {
            if (visited.has(uuid)) return;
            visited.add(uuid);

            const event = pointToEventMap.get(uuid);
            if (event && !sequence.includes(event)) {
                sequence.push(event);
            }

            const nextPoints = dependencyGraph.get(uuid) || [];
            nextPoints.forEach(nextUuid => traverse(nextUuid));
        }

        traverse(startUuid);
        return sequence;
    }

    // Build sequences from root points
    rootPoints.forEach(root => {
        executionSequences.push(buildSequence(root.uuid));
    });

    return executionSequences;
}