/**
 * Parallel execution state management.
 * @task T4784
 */
import { ExitCode } from '@cleocode/contracts';
import { CleoError } from '../errors.js';
import { getAccessor } from '../store/data-accessor.js';
import { computeWaves } from './waves.js';
const PARALLEL_STATE_KEY = 'parallel_state';
async function readParallelState(accessor) {
    const state = await accessor.getMetaValue(PARALLEL_STATE_KEY);
    return state ?? { active: false };
}
async function writeParallelState(state, accessor) {
    await accessor.setMetaValue(PARALLEL_STATE_KEY, state);
}
/** Start parallel execution for a wave. */
export async function startParallelExecution(epicId, wave, cwd, accessor) {
    const acc = accessor ?? (await getAccessor(cwd));
    const currentState = await readParallelState(acc);
    if (currentState.active) {
        throw new CleoError(ExitCode.GENERAL_ERROR, `Parallel execution already active for epic ${currentState.epicId}, wave ${currentState.wave}`);
    }
    const epic = await acc.loadSingleTask(epicId);
    if (!epic) {
        throw new CleoError(ExitCode.NOT_FOUND, `Epic ${epicId} not found`);
    }
    const children = await acc.getChildren(epicId);
    const waves = computeWaves(children);
    const targetWave = waves.find((w) => w.waveNumber === wave);
    if (!targetWave) {
        throw new CleoError(ExitCode.INVALID_INPUT, `Wave ${wave} not found for epic ${epicId}`);
    }
    const startedAt = new Date().toISOString();
    const state = {
        active: true,
        epicId,
        wave,
        startedAt,
        tasks: targetWave.tasks,
    };
    await writeParallelState(state, acc);
    return {
        epicId,
        wave,
        tasks: targetWave.tasks,
        taskCount: targetWave.tasks.length,
        startedAt,
    };
}
/** End parallel execution for a wave. */
export async function endParallelExecution(epicId, wave, cwd, accessor) {
    const acc = accessor ?? (await getAccessor(cwd));
    const currentState = await readParallelState(acc);
    if (!currentState.active) {
        return {
            epicId,
            wave,
            tasks: [],
            taskCount: 0,
            startedAt: null,
            endedAt: new Date().toISOString(),
            durationMs: 0,
            alreadyEnded: true,
        };
    }
    if (currentState.epicId !== epicId || currentState.wave !== wave) {
        throw new CleoError(ExitCode.INVALID_INPUT, `Active parallel is for epic ${currentState.epicId} wave ${currentState.wave}, not epic ${epicId} wave ${wave}`);
    }
    const duration = currentState.startedAt
        ? Date.now() - new Date(currentState.startedAt).getTime()
        : 0;
    await writeParallelState({ active: false }, acc);
    return {
        epicId,
        wave,
        tasks: currentState.tasks || [],
        taskCount: currentState.tasks?.length || 0,
        startedAt: currentState.startedAt || null,
        endedAt: new Date().toISOString(),
        durationMs: duration,
    };
}
/** Get current parallel execution state. */
export async function getParallelStatus(cwd, accessor) {
    const acc = accessor ?? (await getAccessor(cwd));
    return readParallelState(acc);
}
//# sourceMappingURL=parallel.js.map