import { createInitialState, markStep, findFirstIncomplete } from '../../../modules/setup-wizard/entities/setupState/setupState.js';
import { isFinalSuccess, isBlocking, blocked } from '../../../modules/setup-wizard/entities/stepOutcome/stepOutcome.js';
import { AwaitingInputClosedError, NonInteractiveInputError, } from '../../../modules/setup-wizard/entities/promptInputError/promptInputError.js';
export class OrchestrateSetupUseCase {
    async runStep(step, context) {
        try {
            return await step.execute(context);
        }
        catch (error) {
            if (error instanceof AwaitingInputClosedError) {
                return blocked(error.message, 'Fournissez une réponse sur stdin ou relancez sans --json');
            }
            if (error instanceof NonInteractiveInputError) {
                return blocked(error.message, 'Relancez sans -y pour répondre interactivement');
            }
            throw error;
        }
    }
    async execute(input) {
        const { context, steps } = input;
        const loadResult = context.gateways.setupState.load();
        const stateWasCorrupted = loadResult.corrupted;
        if (loadResult.corrupted) {
            context.emitter.emitWarning("Fichier d'état corrompu, démarrage à zéro");
        }
        let state = loadResult.state ?? createInitialState(context.now);
        context.state = state;
        const stepIds = steps.map((step) => step.id);
        const firstIncomplete = findFirstIncomplete(state, stepIds);
        const resumedFromStepId = firstIncomplete !== null && Object.keys(state.steps).length > 0
            ? firstIncomplete
            : null;
        if (resumedFromStepId !== null) {
            const position = stepIds.indexOf(resumedFromStepId) + 1;
            context.emitter.emitResumeBanner(resumedFromStepId, position, steps.length);
        }
        let exitCode = 0;
        let counterBlocked = 0;
        for (const step of steps) {
            const existing = state.steps[step.id];
            if (existing && isFinalSuccess(existing)) {
                const detected = await step.detect(context);
                if (detected && isFinalSuccess(detected)) {
                    state = markStep(state, step.id, detected, context.now);
                    context.state = state;
                    context.gateways.setupState.save(state);
                    continue;
                }
            }
            context.currentStepId = step.id;
            context.emitter.emitStepStarted(step.id, step.title);
            const detected = await step.detect(context);
            let outcome;
            if (detected && isFinalSuccess(detected)) {
                outcome = detected;
            }
            else if (detected && isBlocking(detected)) {
                outcome = detected;
            }
            else {
                outcome = await this.runStep(step, context);
            }
            context.emitter.emitStepCompleted(step.id, outcome);
            state = markStep(state, step.id, outcome, context.now);
            if (context.state && context.project) {
                state = { ...state, project: context.project };
            }
            context.state = state;
            context.gateways.setupState.save(state);
            if (isBlocking(outcome)) {
                counterBlocked++;
                if (context.flags.yes) {
                    exitCode = 2;
                }
                else {
                    exitCode = 1;
                }
                break;
            }
        }
        context.emitter.emitDone({
            totalSteps: steps.length,
            blocked: counterBlocked,
            project: context.project,
        });
        return {
            finalState: state,
            exitCode,
            resumedFromStepId,
            stateWasCorrupted,
        };
    }
}
//# sourceMappingURL=orchestrateSetup.usecase.js.map