"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.publishSpawnChildTransition = publishSpawnChildTransition;
exports.publishControllerChildNeedsHumanTransition = publishControllerChildNeedsHumanTransition;
exports.buildReuseSummary = buildReuseSummary;
exports.buildCreatedChildSummary = buildCreatedChildSummary;
exports.buildCreatedControllerChildrenSummary = buildCreatedControllerChildrenSummary;
exports.buildExistingControllerChildrenSummary = buildExistingControllerChildrenSummary;
exports.buildUpdatedControllerChildrenSummary = buildUpdatedControllerChildrenSummary;
exports.buildProgressedControllerChildrenSummary = buildProgressedControllerChildrenSummary;
exports.buildCreatedAndProgressedControllerChildrenSummary = buildCreatedAndProgressedControllerChildrenSummary;
exports.buildUpdatedAndProgressedControllerChildrenSummary = buildUpdatedAndProgressedControllerChildrenSummary;
exports.buildStartedControllerChildConflictSummary = buildStartedControllerChildConflictSummary;
const catalog_1 = require("../../../i18n/catalog");
const types_1 = require("../../../platform/ticket-tracker/types");
const types_2 = require("../../../platform/workflow-state/types");
const constants_1 = require("../../../worker/constants");
const publisher_shared_1 = require("../../../workflows/publisher-shared");
const publisher_events_1 = require("../../../workflows/publisher-events");
const visible_update_builders_1 = require("../../../workflows/visible-update-builders");
const constants_2 = require("../../constants");
const execution_ownership_1 = require("../../execution-ownership");
const log_text_1 = require("../../log-text");
const child_publication_1 = require("../child-publication");
const effects_state_support_1 = require("../effects-state-support");
const followup_recommendation_state_1 = require("../followup-recommendation-state");
const presentation_1 = require("../presentation");
const publisher_factory_1 = require("../publisher-factory");
const issue_branch_target_1 = require("../issue-branch-target");
const results_1 = require("../results");
const terminal_followup_1 = require("../terminal-followup");
const transition_presentation_1 = require("../transition-presentation");
const transitions_1 = require("../transitions");
const ai_run_accounting_1 = require("../ai-run-accounting");
const needs_human_1 = require("../needs-human");
const types_3 = require("../types");
async function publishSpawnChildTransition(input) {
    const transitionState = buildSpawnChildTransitionState({
        context: input.context,
        claimedIssue: input.claimedIssue,
        workerExecution: input.workerExecution,
        summary: input.summary,
        controllerTerminalCompletion: input.controllerTerminalCompletion ?? false,
    });
    const terminalSuccess = input.controllerTerminalCompletion === true ||
        (0, results_1.isTerminalWorkflowSuccessCandidate)({
            runMode: input.workerExecution.runMode,
            finalOutcome: constants_1.WORKER_OUTCOMES.proceed,
            recordsRunOutcome: input.workerExecution.recordsRunOutcome,
            continuation: input.workerExecution.continuation,
            workflowState: transitionState.workflowState,
        });
    const transitionInput = {
        context: input.context,
        claimedIssue: input.claimedIssue,
        transitionState,
        terminalSuccess,
        summary: input.summary,
        visibleUpdateKind: input.visibleUpdateKind,
        updateTrackerTitle: input.updateTrackerTitle ?? false,
        includeWorkerOutcome: input.includeWorkerOutcome ?? true,
        logger: input.logger,
        workflowLabels: input.workflowLabels,
    };
    if (input.dependencyChanges !== undefined) {
        transitionInput.dependencyChanges = input.dependencyChanges;
    }
    if (input.commentCursorPolicy !== undefined) {
        transitionInput.commentCursorPolicy = input.commentCursorPolicy;
    }
    if (input.visibleUpdateDedupeCursor !== undefined) {
        transitionInput.visibleUpdateDedupeCursor = input.visibleUpdateDedupeCursor;
    }
    return publishChildParentTransition(transitionInput);
}
async function publishControllerChildNeedsHumanTransition(input) {
    const transitionState = (0, transitions_1.buildWaitHumanTransitionState)({
        config: input.context.config,
        previousSnapshot: input.claimedIssue.aiRunningSnapshot,
        readySnapshot: input.claimedIssue.aiReadySnapshot,
        issue: input.workerExecution.issue,
        runMode: input.workerExecution.runMode,
        summary: input.summary,
        needsHumanReason: types_3.WORKER_NEEDS_HUMAN_REASONS.question,
        facts: input.workerExecution.facts,
        branchName: input.workerExecution.branchName,
        baseBranch: input.workerExecution.workflowState === null
            ? input.context.config.repositoryHost.baseBranch
            : (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.workerExecution.workflowState),
        pullRequestThreadId: input.workerExecution.facts.pullRequestThreadId,
        pullRequestUrl: input.workerExecution.pullRequestUrl,
        scannedInputCursor: null,
        cursorMode: "explicit_only",
        workflowTemplateName: input.workerExecution.workflowTemplateName,
        workflowState: input.workerExecution.workflowState === null
            ? null
            : {
                ...(0, execution_ownership_1.stripExecutionOwnership)(input.workerExecution.workflowState),
                totalAiRunHours: (0, ai_run_accounting_1.resolveWorkerExecutionTotalAiRunHours)(input.workerExecution),
            },
        consecutiveAiRuns: input.workerExecution.consecutiveAiRuns,
        totalAiRunHours: (0, ai_run_accounting_1.resolveWorkerExecutionTotalAiRunHours)(input.workerExecution),
        responseLanguage: input.workerExecution.responseLanguage,
    });
    return publishChildParentTransition({
        context: input.context,
        claimedIssue: input.claimedIssue,
        transitionState,
        terminalSuccess: false,
        summary: input.summary,
        visibleUpdateKind: child_publication_1.CHILD_ISSUE_VISIBLE_UPDATE_KINDS.controllerStartedConflict,
        includeWorkerOutcome: false,
        logger: input.logger,
        workflowLabels: input.workflowLabels,
    });
}
async function publishChildParentTransition(input) {
    await input.logger.appendSection((0, log_text_1.issueLogSection)("resolvedTransition"), (0, presentation_1.renderOutcomeTransitionSection)({
        workflowLabels: input.workflowLabels,
        from: input.claimedIssue.aiRunningSnapshot.status,
        to: input.transitionState.nextSnapshot.status,
        requestedOutcome: input.transitionState.requestedOutcome,
        finalOutcome: input.transitionState.finalOutcome,
        facts: input.transitionState.facts,
        locale: input.logger.locale,
    }));
    let workflowState = input.transitionState.workflowState;
    const visibleUpdate = buildSpawnChildVisibleUpdate({
        terminalSuccess: input.terminalSuccess,
        visibleUpdateKind: input.visibleUpdateKind,
        responseLanguage: input.transitionState.responseLanguage,
        summary: input.summary,
        includeWorkerOutcome: input.includeWorkerOutcome,
        workerOutcome: input.transitionState.presentation.commentOutcome,
        needsHumanReason: input.transitionState.needsHumanReason,
        completedSummary: input.transitionState.presentation.commentSummary,
        completedNext: input.transitionState.presentation.commentNext,
    });
    const visibleUpdateForPublication = shouldPublishChildParentVisibleUpdate({
        terminalSuccess: input.terminalSuccess,
        visibleUpdateKind: input.visibleUpdateKind,
        visibleUpdate,
    });
    const trackerTitle = input.terminalSuccess || input.updateTrackerTitle === true
        ? (0, effects_state_support_1.resolveRenderedTitleIfChanged)({
            issue: input.claimedIssue.originalIssue,
            workflowState,
            locale: input.transitionState.responseLanguage,
            surface: input.claimedIssue.originalIssue.kind ===
                types_1.TRACKER_ITEM_KINDS.pullRequest
                ? "pull_request"
                : "issue",
            enabled: input.context.config.ticketTracker.showStepProgressInTitles ===
                true,
        })
        : null;
    const publisher = (0, publisher_factory_1.createRunWorkflowPublisher)(input.context);
    const shouldCloseTerminalSuccess = shouldCloseChildParentTerminalSuccess(input.transitionState, input.terminalSuccess);
    if (shouldCloseTerminalSuccess) {
        await (0, terminal_followup_1.publishFollowupIssueIfNeeded)({
            context: input.context,
            workflowLabels: input.workflowLabels,
            transitionState: input.transitionState,
        });
        workflowState = input.transitionState.workflowState;
    }
    const publicationRequestInput = {
        issue: input.claimedIssue.originalIssue,
        workflowState,
        previousSnapshot: input.transitionState.previousSnapshot,
        nextSnapshot: input.transitionState.nextSnapshot,
        nextNeedsHumanReason: input.transitionState.needsHumanReason,
        labelProjection: input.transitionState.labelProjection,
        workflowLabels: input.workflowLabels,
        responseLanguage: input.transitionState.responseLanguage,
        visibleUpdate: visibleUpdateForPublication,
        trackerTitle,
        commentCursorPolicy: input.commentCursorPolicy ??
            resolveChildParentCommentCursorPolicy(input.transitionState.scannedInputCursor),
        terminalSuccess: shouldCloseTerminalSuccess,
    };
    if (input.visibleUpdateDedupeCursor !== undefined) {
        publicationRequestInput.visibleUpdateDedupeCursor =
            input.visibleUpdateDedupeCursor;
    }
    if (input.dependencyChanges !== undefined) {
        publicationRequestInput.dependencyChanges = input.dependencyChanges;
    }
    const publication = await publisher.publishWorkflow((0, child_publication_1.buildChildParentPublicationRequest)(buildSpawnChildParentPublicationRequestInput(publicationRequestInput)));
    input.transitionState.issue.workflowState =
        publication.targetWorkflowProjection ?? input.transitionState.nextSnapshot;
    const summary = (0, results_1.buildRunCliSummary)({
        issue: input.transitionState.issue,
        outcome: input.transitionState.finalOutcome === constants_1.WORKER_OUTCOMES.waitHuman
            ? constants_2.RUN_ISSUE_OUTCOMES.queuedHuman
            : constants_2.RUN_ISSUE_OUTCOMES.queuedAi,
        responseLanguage: input.transitionState.responseLanguage,
        summary: input.terminalSuccess
            ? input.transitionState.presentation.commentSummary
            : input.summary,
        commentUrl: (0, publisher_factory_1.resolveRunWorkflowPublicationCommentUrl)(publication),
        prUrl: input.transitionState.pullRequestUrl,
        nextStep: input.terminalSuccess
            ? input.transitionState.presentation.cliNext
            : visibleUpdate.next,
    });
    await input.logger.appendSection((0, log_text_1.issueLogSection)("finalSummary"), (0, presentation_1.renderCliSummary)(summary, input.logger.locale));
    await input.logger.appendSection((0, log_text_1.issueLogSection)("finalLabelsCloseResult"), (0, presentation_1.renderFinalWorkflowStateSection)(input.transitionState.nextSnapshot, shouldCloseChildParentTerminalSuccess(input.transitionState, input.terminalSuccess), input.workflowLabels, input.logger.locale));
    return summary;
}
function resolveChildParentCommentCursorPolicy(scannedInputCursor) {
    if (scannedInputCursor === null) {
        return { mode: publisher_shared_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.preserve };
    }
    return {
        mode: publisher_shared_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.advanceToScannedInput,
        scannedInputCursor,
    };
}
function buildReuseSummary(responseLanguage, targetIssueDisplayId) {
    return (0, catalog_1.translate)(responseLanguage, "run.spawnChild.reuseSummary", {
        targetIssueDisplayId,
    });
}
function buildCreatedChildSummary(responseLanguage, targetIssueDisplayId) {
    return (0, catalog_1.translate)(responseLanguage, "run.spawnChild.createdChildSummary", {
        targetIssueDisplayId,
    });
}
function buildCreatedControllerChildrenSummary(responseLanguage, childIssueDisplayIds) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.createdSummary", {
        childIssueDisplayIds: childIssueDisplayIds.join(", "),
    });
}
function buildExistingControllerChildrenSummary(responseLanguage, childIssueDisplayIds) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.existingSummary", {
        childIssueDisplayIds: childIssueDisplayIds.join(", "),
    });
}
function buildUpdatedControllerChildrenSummary(responseLanguage, childIssueDisplayIds) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.updatedSummary", {
        childIssueDisplayIds: childIssueDisplayIds.join(", "),
    });
}
function buildProgressedControllerChildrenSummary(responseLanguage, childIssueDisplayIds) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.progressedSummary", {
        childIssueDisplayIds: childIssueDisplayIds.join(", "),
    });
}
function buildCreatedAndProgressedControllerChildrenSummary(responseLanguage, createdChildIssueDisplayIds, reflectedChildIssueDisplayIds) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.createdProgressedSummary", {
        createdChildIssueDisplayIds: createdChildIssueDisplayIds.join(", "),
        reflectedChildIssueDisplayIds: reflectedChildIssueDisplayIds.join(", "),
    });
}
function buildUpdatedAndProgressedControllerChildrenSummary(responseLanguage, updatedChildIssueDisplayIds, reflectedChildIssueDisplayIds) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.updatedProgressedSummary", {
        updatedChildIssueDisplayIds: updatedChildIssueDisplayIds.join(", "),
        reflectedChildIssueDisplayIds: reflectedChildIssueDisplayIds.join(", "),
    });
}
function buildStartedControllerChildConflictSummary(responseLanguage, childIssueDisplayId) {
    return (0, catalog_1.translate)(responseLanguage, "run.controllerChildren.startedConflictSummary", {
        childIssueDisplayId,
    });
}
function buildSpawnChildTransitionState(input) {
    const recordsRunOutcome = input.workerExecution.recordsRunOutcome;
    const executedAt = new Date().toISOString();
    const workflowStateBase = input.workerExecution.workflowState === null
        ? null
        : {
            ...(0, execution_ownership_1.stripExecutionOwnership)((0, needs_human_1.applyWorkflowExecutionMetadata)(input.workerExecution.workflowState, {
                executedAt,
                finalOutcome: constants_1.WORKER_OUTCOMES.proceed,
                recordsRunOutcome,
                shouldClearPendingPlanningIntent: input.workerExecution.startedWithPlanningIntent !== null,
                pendingPlanningIntent: undefined,
                pendingPlanningReason: null,
                displayTimeZone: input.context.config.i18n.displayTimeZone,
            })),
            totalAiRunHours: (0, ai_run_accounting_1.resolveWorkerExecutionTotalAiRunHours)(input.workerExecution),
        };
    const terminalSuccess = input.controllerTerminalCompletion ||
        (0, results_1.isTerminalWorkflowSuccessCandidate)({
            runMode: input.workerExecution.runMode,
            finalOutcome: constants_1.WORKER_OUTCOMES.proceed,
            recordsRunOutcome,
            continuation: input.workerExecution.continuation,
            workflowState: workflowStateBase,
        });
    const workflowState = terminalSuccess
        ? (0, followup_recommendation_state_1.applyWorkflowClosingFollowupRecommendation)({
            workflowState: workflowStateBase,
            recommendation: input.workerExecution.followupRecommendation,
            recommendationSource: (0, followup_recommendation_state_1.buildWorkflowClosingFollowupRecommendationSource)({
                workerExecution: input.workerExecution,
            }),
        })
        : workflowStateBase;
    const nextSnapshot = {
        status: terminalSuccess
            ? types_2.WORKFLOW_STATUSES.aiRunning
            : types_2.WORKFLOW_STATUSES.aiReady,
        rules: [...input.claimedIssue.aiReadySnapshot.rules],
    };
    const state = {
        issue: input.workerExecution.issue,
        previousSnapshot: input.claimedIssue.aiRunningSnapshot,
        nextSnapshot,
        handoffPullRequestSnapshot: null,
        runMode: input.workerExecution.runMode,
        requestedOutcome: constants_1.WORKER_OUTCOMES.proceed,
        finalOutcome: constants_1.WORKER_OUTCOMES.proceed,
        summary: input.summary,
        comment: null,
        facts: input.workerExecution.facts,
        branchName: input.workerExecution.branchName,
        baseBranch: (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.workerExecution.workflowState),
        pullRequestThreadId: input.workerExecution.facts.pullRequestThreadId,
        pullRequestUrl: input.workerExecution.pullRequestUrl,
        scannedInputCursor: input.workerExecution.scannedInputCursor,
        workflowTemplateName: input.workerExecution.workflowTemplateName,
        workflowState,
        plannedIssueTitle: input.workerExecution.plannedIssueTitle,
        planningIntent: input.workerExecution.planningIntent,
        sameIssueReplanSource: null,
        completedPendingReplan: false,
        continuation: null,
        needsHumanReason: null,
        responseLanguage: input.workerExecution.responseLanguage,
        result: null,
        presentation: (0, transition_presentation_1.buildTransitionPresentation)({
            config: input.context.config,
            issue: input.workerExecution.issue,
            finalOutcome: constants_1.WORKER_OUTCOMES.proceed,
            facts: input.workerExecution.facts,
            summary: input.summary,
            comment: null,
            consecutiveAiRuns: input.workerExecution.consecutiveAiRuns,
            responseLanguage: input.workerExecution.responseLanguage,
            workflowState,
            terminalSuccess,
        }),
        incrementsConsecutiveAiRuns: input.workerExecution.incrementsConsecutiveAiRuns,
        recordsRunOutcome,
    };
    if (terminalSuccess) {
        state.labelProjection = { omitWorkflowLabels: true };
    }
    return state;
}
function shouldPublishChildParentVisibleUpdate(input) {
    if (input.terminalSuccess) {
        return input.visibleUpdate;
    }
    switch (input.visibleUpdateKind) {
        case child_publication_1.CHILD_ISSUE_VISIBLE_UPDATE_KINDS.controllerChildrenExisting:
            return null;
        default:
            return input.visibleUpdate;
    }
}
function shouldCloseChildParentTerminalSuccess(state, terminalSuccess) {
    return (terminalSuccess &&
        state.issue.kind === types_1.TRACKER_ITEM_KINDS.issue &&
        !state.facts.branchAheadOfBase &&
        !state.facts.openPullRequestExists);
}
function buildSpawnChildVisibleUpdate(input) {
    if (input.terminalSuccess) {
        return (0, visible_update_builders_1.buildWorkflowVisibleUpdate)({
            event: publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowCompleted,
            summary: input.completedSummary,
            next: input.completedNext,
            workerOutcome: input.workerOutcome,
        });
    }
    const visibleUpdateInput = {
        kind: input.visibleUpdateKind,
        responseLanguage: input.responseLanguage,
        summary: input.summary,
    };
    if (input.includeWorkerOutcome) {
        visibleUpdateInput.workerOutcome = input.workerOutcome;
    }
    if (input.needsHumanReason !== null) {
        visibleUpdateInput.needsHumanReason = input.needsHumanReason;
    }
    return (0, child_publication_1.buildChildIssueVisibleUpdate)(visibleUpdateInput);
}
function buildSpawnChildParentPublicationRequestInput(input) {
    const requestInput = {
        issue: input.issue,
        workflowState: input.workflowState,
        projection: {
            previous: input.previousSnapshot,
            next: input.nextSnapshot,
            previousNeedsHumanReason: null,
            nextNeedsHumanReason: input.nextNeedsHumanReason,
        },
        workflowLabels: input.workflowLabels,
        responseLanguage: input.responseLanguage,
        visibleUpdate: input.visibleUpdate,
        commentCursorPolicy: input.commentCursorPolicy,
    };
    if (input.labelProjection !== undefined) {
        requestInput.projection.labelProjection = input.labelProjection;
    }
    if (input.trackerTitle !== null) {
        requestInput.trackerTitle = input.trackerTitle;
    }
    if (input.visibleUpdateDedupeCursor !== undefined) {
        requestInput.visibleUpdateDedupeCursor = input.visibleUpdateDedupeCursor;
    }
    if (input.dependencyChanges !== undefined) {
        requestInput.dependencyChanges = input.dependencyChanges;
    }
    if (input.terminalSuccess) {
        requestInput.terminalAction = { kind: "close" };
    }
    return requestInput;
}
