/**
 * Phase: processes
 *
 * Detects execution flows (processes) and creates Process nodes +
 * STEP_IN_PROCESS edges. Also links Route/Tool nodes to processes.
 *
 * @deps    communities, routes, tools
 * @reads   graph (all nodes and relationships), communityResult, routeRegistry, toolDefs
 * @writes  graph (Process nodes, STEP_IN_PROCESS edges, ENTRY_POINT_OF edges)
 */
import { getPhaseOutput } from './types.js';
import { processProcesses } from '../process-processor.js';
import { generateId } from '../../../lib/utils.js';
import { isDev } from '../utils/env.js';
import { logger } from '../../logger.js';
export const processesPhase = {
    name: 'processes',
    // `structure` supplies `totalFiles` (progress counter) without the spurious
    // structural data dependency on `parse`.
    deps: ['communities', 'routes', 'tools', 'structure'],
    async execute(ctx, deps) {
        const { totalFiles } = getPhaseOutput(deps, 'structure');
        const { communityResult } = getPhaseOutput(deps, 'communities');
        const { routeRegistry } = getPhaseOutput(deps, 'routes');
        const { toolDefs } = getPhaseOutput(deps, 'tools');
        ctx.onProgress({
            phase: 'processes',
            percent: 99,
            message: 'Detecting execution flows...',
            stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: ctx.graph.nodeCount },
        });
        let symbolCount = 0;
        ctx.graph.forEachNode((n) => {
            if (n.label !== 'File')
                symbolCount++;
        });
        const dynamicMaxProcesses = Math.max(20, Math.min(300, Math.round(symbolCount / 10)));
        const processResult = await processProcesses(ctx.graph, communityResult.memberships, (message, progress) => {
            const processProgress = 99 + progress * 0.01;
            ctx.onProgress({
                phase: 'processes',
                percent: Math.round(processProgress),
                message,
                stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: ctx.graph.nodeCount },
            });
        }, { maxProcesses: dynamicMaxProcesses, minSteps: 3 });
        if (isDev) {
            logger.info(`🔄 Process detection: ${processResult.stats.totalProcesses} processes found (${processResult.stats.crossCommunityCount} cross-community)`);
        }
        processResult.processes.forEach((proc) => {
            ctx.graph.addNode({
                id: proc.id,
                label: 'Process',
                properties: {
                    name: proc.label,
                    filePath: '',
                    heuristicLabel: proc.heuristicLabel,
                    processType: proc.processType,
                    stepCount: proc.stepCount,
                    communities: proc.communities,
                    entryPointId: proc.entryPointId,
                    terminalId: proc.terminalId,
                },
            });
        });
        processResult.steps.forEach((step) => {
            ctx.graph.addRelationship({
                id: `${step.nodeId}_step_${step.step}_${step.processId}`,
                type: 'STEP_IN_PROCESS',
                sourceId: step.nodeId,
                targetId: step.processId,
                confidence: 1.0,
                reason: 'trace-detection',
                step: step.step,
            });
        });
        // Link Route and Tool nodes to Processes
        if (routeRegistry.size > 0 || toolDefs.length > 0) {
            const routesByFile = new Map();
            for (const [url, entry] of routeRegistry) {
                let list = routesByFile.get(entry.filePath);
                if (!list) {
                    list = [];
                    routesByFile.set(entry.filePath, list);
                }
                list.push(url);
            }
            const toolsByHandlerId = new Map();
            const toolsWithoutHandlerByFile = new Map();
            for (const td of toolDefs) {
                const key = td.handlerNodeId ?? td.filePath;
                const targetMap = td.handlerNodeId ? toolsByHandlerId : toolsWithoutHandlerByFile;
                let list = targetMap.get(key);
                if (!list) {
                    list = [];
                    targetMap.set(key, list);
                }
                list.push(td.name);
            }
            let linked = 0;
            for (const proc of processResult.processes) {
                if (!proc.entryPointId)
                    continue;
                const entryNode = ctx.graph.getNode(proc.entryPointId);
                if (!entryNode)
                    continue;
                const entryFile = entryNode.properties.filePath;
                if (!entryFile)
                    continue;
                const routeURLs = routesByFile.get(entryFile);
                if (routeURLs) {
                    for (const routeURL of routeURLs) {
                        const routeNodeId = generateId('Route', routeURL);
                        ctx.graph.addRelationship({
                            id: generateId('ENTRY_POINT_OF', `${routeNodeId}->${proc.id}`),
                            sourceId: routeNodeId,
                            targetId: proc.id,
                            type: 'ENTRY_POINT_OF',
                            confidence: 0.85,
                            reason: 'route-handler-entry-point',
                        });
                        linked++;
                    }
                }
                const exactToolNames = toolsByHandlerId.get(proc.entryPointId);
                const fallbackToolNames = toolsWithoutHandlerByFile.get(entryFile);
                const toolNames = exactToolNames ?? fallbackToolNames;
                if (toolNames) {
                    for (const toolName of toolNames) {
                        const toolNodeId = generateId('Tool', toolName);
                        ctx.graph.addRelationship({
                            id: generateId('ENTRY_POINT_OF', `${toolNodeId}->${proc.id}`),
                            sourceId: toolNodeId,
                            targetId: proc.id,
                            type: 'ENTRY_POINT_OF',
                            confidence: 0.85,
                            reason: 'tool-handler-entry-point',
                        });
                        linked++;
                    }
                }
            }
            if (isDev && linked > 0) {
                logger.info(`🔗 Linked ${linked} Route/Tool nodes to execution flows`);
            }
        }
        return { processResult };
    },
};
