import { interruptAllQueries } from '../../../infra/claude/query-manager.js';
import { StreamDisplay } from '../../../shared/ui/index.js';
import { sanitizeTerminalText } from '../../../shared/utils/text.js';
import { isDebugEnabled, isVerboseConsole } from '../../../shared/utils/debug.js';
import { notifyWarning, playWarningSound } from '../../../shared/utils/index.js';
import { detectStepType, isQuietMode } from './workflowExecutionBootstrap.js';
import { finalizeWorkflowAbort, finalizeWorkflowSuccess, reportStepFile, reportWorkflowAbort, reportWorkflowCompletion, updateUsageForStepCompletion, } from './workflowExecutionReporting.js';
function sourceSuffix(path, sources, showSource) {
    if (!showSource)
        return '';
    const source = sources?.[path];
    return source ? ` (source: ${source})` : '';
}
function emitProviderOptionLines(out, stepProvider, providerInfo, showSource) {
    const options = providerInfo.providerOptions;
    if (!options)
        return;
    const sources = providerInfo.providerOptionsSources;
    if (stepProvider === 'claude' || stepProvider === 'claude-sdk') {
        const effort = options.claude?.effort;
        if (effort !== undefined) {
            out.info(`Effort: ${effort}${sourceSuffix('claude.effort', sources, showSource)}`);
        }
    }
    else if (stepProvider === 'codex') {
        const effort = options.codex?.reasoningEffort;
        if (effort !== undefined) {
            out.info(`Reasoning effort: ${effort}${sourceSuffix('codex.reasoningEffort', sources, showSource)}`);
        }
    }
    else if (stepProvider === 'opencode') {
        const variant = options.opencode?.variant;
        if (variant !== undefined) {
            out.info(`Variant: ${variant}${sourceSuffix('opencode.variant', sources, showSource)}`);
        }
    }
    else if (stepProvider === 'copilot') {
        const effort = options.copilot?.effort;
        if (effort !== undefined) {
            out.info(`Effort: ${effort}${sourceSuffix('copilot.effort', sources, showSource)}`);
        }
    }
}
export function bindWorkflowExecutionEvents(deps) {
    const canReadResumePoint = () => typeof deps.engine.getResumePoint === 'function';
    const getResumePoint = () => {
        if (!canReadResumePoint()) {
            return undefined;
        }
        return deps.engine.getResumePoint();
    };
    const state = {
        currentIteration: 0,
        lastResumePoint: deps.initialResumePoint,
        sessionLog: deps.sessionLog,
    };
    const stepIterations = new Map();
    const syncLatestResumePoint = () => {
        if (!canReadResumePoint()) {
            return;
        }
        state.lastResumePoint = getResumePoint();
        deps.runMetaManager.updateResumePoint(state.lastResumePoint);
    };
    deps.engine.on('phase:start', (step, phase, phaseName, instruction, promptParts, phaseExecutionId, iteration) => {
        deps.runMetaManager.updatePhase(step.name, iteration, phase);
        deps.sessionLogger.onPhaseStart(step, phase, phaseName, instruction, promptParts, deps.getCurrentWorkflowStack(), phaseExecutionId, iteration);
    });
    deps.engine.on('phase:complete', (step, phase, phaseName, content, phaseStatus, phaseError, phaseExecutionId, iteration) => {
        deps.runMetaManager.updatePhase(step.name, iteration, phase);
        deps.sessionLogger.setIteration(state.currentIteration);
        deps.sessionLogger.onPhaseComplete(step, phase, phaseName, content, phaseStatus, phaseError, deps.getCurrentWorkflowStack(), phaseExecutionId, iteration);
    });
    deps.engine.on('phase:judge_stage', (step, phase, phaseName, entry, phaseExecutionId, iteration) => {
        deps.sessionLogger.onJudgeStage(step, phase, phaseName, entry, deps.getCurrentWorkflowStack(), phaseExecutionId, iteration);
    });
    deps.engine.on('step:start', (step, iteration, instruction, providerInfo) => {
        state.currentIteration = iteration;
        state.lastResumePoint = getResumePoint();
        deps.runMetaManager.updateStep(step.name, iteration, state.lastResumePoint);
        const stepIteration = (stepIterations.get(step.name) ?? 0) + 1;
        stepIterations.set(step.name, stepIteration);
        const safeStepName = sanitizeTerminalText(step.name);
        const safePersonaDisplayName = sanitizeTerminalText(step.personaDisplayName);
        deps.prefixWriter?.setStepContext({
            stepName: safeStepName,
            iteration,
            maxSteps: deps.workflowConfig.maxSteps,
            stepIteration,
        });
        deps.out.info(`[${iteration}/${deps.workflowConfig.maxSteps}] ${safeStepName} (${safePersonaDisplayName})`);
        const stepProvider = providerInfo.provider ?? deps.currentProvider;
        const stepModel = providerInfo.model ?? (stepProvider === deps.currentProvider ? deps.configuredModel : undefined) ?? '(default)';
        deps.providerEventLogger.setStep(step.name);
        deps.providerEventLogger.setProvider(stepProvider);
        deps.usageEventLogger.setStep(step.name, detectStepType(step));
        deps.usageEventLogger.setProvider(stepProvider, stepModel);
        const showSource = isDebugEnabled() || isVerboseConsole();
        const providerSourceSuffix = showSource && providerInfo.providerSource
            ? ` (source: ${providerInfo.providerSource})`
            : '';
        const modelSourceSuffix = showSource && providerInfo.modelSource
            ? ` (source: ${providerInfo.modelSource})`
            : '';
        deps.out.info(`Provider: ${stepProvider}${providerSourceSuffix}`);
        deps.out.info(`Model: ${stepModel}${modelSourceSuffix}`);
        emitProviderOptionLines(deps.out, stepProvider, providerInfo, showSource);
        deps.analyticsEmitter.updateProviderInfo(iteration, stepProvider, stepModel);
        if (!deps.prefixWriter) {
            const stepIndex = deps.workflowConfig.steps.findIndex((workflowStep) => workflowStep.name === step.name);
            deps.displayRef.current = new StreamDisplay(safePersonaDisplayName, isQuietMode(), {
                iteration,
                maxSteps: deps.workflowConfig.maxSteps,
                stepIndex: stepIndex >= 0 ? stepIndex : 0,
                totalSteps: deps.workflowConfig.steps.length,
            });
            deps.handlerRef.current = null;
        }
        deps.sessionLogger.onStepStart(step, iteration, instruction, state.lastResumePoint?.stack, providerInfo);
    });
    deps.engine.on('step:complete', (step, response, instruction) => {
        syncLatestResumePoint();
        state.lastStepContent = response.content;
        state.lastStepName = step.name;
        if (deps.displayRef.current) {
            deps.displayRef.current.flush();
            deps.displayRef.current = null;
        }
        deps.prefixWriter?.flush();
        deps.out.blankLine();
        if (response.matchedRuleIndex != null && step.rules) {
            const rule = step.rules[response.matchedRuleIndex];
            const methodLabel = response.matchedRuleMethod ? ` (${response.matchedRuleMethod})` : '';
            deps.out.status('Status', rule ? `${rule.condition}${methodLabel}` : response.status);
        }
        else {
            deps.out.status('Status', response.status);
        }
        if (response.error) {
            deps.out.error(`Error: ${response.error}`);
        }
        if (response.sessionId) {
            deps.out.status('Session', response.sessionId);
        }
        updateUsageForStepCompletion(deps.usageEventLogger, response);
        deps.sessionLogger.onStepComplete(step, response, instruction, deps.getCurrentWorkflowStack());
        deps.analyticsEmitter.onStepComplete(step, response);
        state.sessionLog = { ...state.sessionLog, iterations: state.sessionLog.iterations + 1 };
    });
    deps.engine.on('step:rate_limited', (step, response) => {
        if (deps.displayRef.current) {
            deps.displayRef.current.flush();
        }
        deps.prefixWriter?.flush();
        const message = response.error ?? `Step "${step.name}" hit a rate limit`;
        playWarningSound();
        notifyWarning('TAKT', message);
    });
    deps.engine.on('step:report', (_step, filePath, fileName) => {
        reportStepFile(filePath, fileName, deps.out);
        deps.analyticsEmitter.onStepReport(_step, filePath);
    });
    deps.engine.on('workflow:complete', (workflowState) => {
        syncLatestResumePoint();
        state.sessionLog = finalizeWorkflowSuccess(state.sessionLog, deps.task, deps.workflowConfig.name, state.lastStepContent, state.lastStepName, deps.projectCwd, deps.out.warn);
        deps.sessionLogger.onWorkflowComplete(workflowState);
        deps.runMetaManager.finalize('completed', workflowState.iteration);
        deps.writeTraceReportOnce({
            status: 'completed',
            iterations: workflowState.iteration,
            endTime: new Date().toISOString(),
        });
        reportWorkflowCompletion(deps.out, state.sessionLog, workflowState.iteration, deps.ndjsonLogPath, deps.shouldNotifyWorkflowComplete);
    });
    deps.engine.on('workflow:abort', (workflowState, reason) => {
        interruptAllQueries();
        syncLatestResumePoint();
        if (deps.displayRef.current) {
            deps.displayRef.current.flush();
            deps.displayRef.current = null;
        }
        deps.prefixWriter?.flush();
        state.abortReason = reason;
        state.sessionLog = finalizeWorkflowAbort(state.sessionLog, reason, deps.task, deps.workflowConfig.name, state.lastStepName, deps.projectCwd, deps.out.warn);
        deps.sessionLogger.onWorkflowAbort(workflowState, reason);
        deps.runMetaManager.finalize('aborted', workflowState.iteration);
        deps.writeTraceReportOnce({
            status: 'aborted',
            iterations: workflowState.iteration,
            reason,
            endTime: new Date().toISOString(),
        });
        reportWorkflowAbort(deps.out, state.sessionLog, workflowState.iteration, reason, deps.ndjsonLogPath, deps.shouldNotifyWorkflowAbort);
    });
    return {
        state,
        syncLatestResumePoint,
    };
}
//# sourceMappingURL=workflowExecutionEvents.js.map