"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveLinkedIssueApprovalContext = resolveLinkedIssueApprovalContext;
exports.buildApproveFeedbackMessage = buildApproveFeedbackMessage;
exports.buildStartFeedbackMessage = buildStartFeedbackMessage;
exports.resolveBlockingForeignApprovalComment = resolveBlockingForeignApprovalComment;
exports.applyAcceptedSchedule = applyAcceptedSchedule;
exports.resolveAcceptedWorkflowStateForCommand = resolveAcceptedWorkflowStateForCommand;
exports.applyAcceptedIssueCompletionAutoMergeState = applyAcceptedIssueCompletionAutoMergeState;
exports.resolveNextSnapshotAfterCommand = resolveNextSnapshotAfterCommand;
exports.buildAcceptedMessage = buildAcceptedMessage;
exports.buildInvalidCommandMessage = buildInvalidCommandMessage;
exports.buildInvalidWorkflowCommandProjection = buildInvalidWorkflowCommandProjection;
const control_plane_config_1 = require("../../config/control-plane-config");
const issue_completion_1 = require("../../config/issue-completion");
const catalog_1 = require("../../i18n/catalog");
const display_time_1 = require("../../i18n/display-time");
const types_1 = require("../../platform/ticket-tracker/types");
const types_2 = require("../../platform/workflow-state/types");
const run_limit_policy_1 = require("../../run/run-once-cycle/run-limit-policy");
const shared_1 = require("../../run/run-once-cycle/shared");
const workflow_surface_1 = require("../../run/run-once-cycle/workflow-surface");
const assignee_resolution_1 = require("../../workflows/assignee-resolution");
const command_apply_1 = require("../../workflows/command-apply");
const display_labels_1 = require("../../workflows/display-labels");
const foreign_input_approval_1 = require("../../workflows/foreign-input-approval");
const followup_policy_1 = require("../../workflows/followup-policy");
const auto_merge_state_1 = require("../../workflows/auto-merge-state");
const optional_text_1 = require("../../workflows/optional-text");
const pre_plan_state_1 = require("../../workflows/pre-plan-state");
const publisher_events_1 = require("../../workflows/publisher-events");
const recurring_1 = require("../../workflows/recurring");
const run_context_summaries_1 = require("../../workflows/run-context-summaries");
const scheduled_run_1 = require("../../workflows/scheduled-run");
const start_approval_support_1 = require("../../workflows/start-approval-support");
const template_bindings_1 = require("../../workflows/template-bindings");
const template_registry_1 = require("../../workflows/template-registry");
const types_3 = require("../../workflows/types");
const validation_format_1 = require("../../workflows/validation-format");
const workflow_projection_support_1 = require("../../workflows/workflow-projection-support");
const workflow_template_selection_validation_1 = require("../../workflows/workflow-template-selection-validation");
const workflow_timeline_scan_1 = require("../../workflows/workflow-timeline-scan");
const config_publish_spec_support_1 = require("./config-publish-spec-support");
async function resolveLinkedIssueApprovalContext(input) {
    if (input.issue.kind !== "pull_request") {
        return null;
    }
    const linkedIssueId = await (0, shared_1.resolveLinkedIssueIdFromPullRequestTimeline)(input.ticketTracker, input.issue);
    if (linkedIssueId === null) {
        return null;
    }
    try {
        const linkedIssue = await input.ticketTracker.getIssue(linkedIssueId);
        if (linkedIssue.kind !== "issue") {
            return null;
        }
        return {
            issue: linkedIssue,
            comments: (0, workflow_timeline_scan_1.sortTimelineComments)(await input.ticketTracker.listComments(linkedIssue.id, {
                timeline: "issue-only",
            })),
        };
    }
    catch {
        return null;
    }
}
function buildApproveFeedbackMessage(language, reason) {
    const keyByReason = {
        "single-assignee-required": "serviceRuntimeConfigApproval.feedback.approve.singleAssigneeRequired",
        "assignee-only": "serviceRuntimeConfigApproval.feedback.approve.assigneeOnly",
        "not-foreign-approval": "serviceRuntimeConfigApproval.feedback.approve.notForeignApproval",
        "start-approval-context": "serviceRuntimeConfigApproval.feedback.approve.startApprovalContext",
    };
    return (0, catalog_1.translate)(language, keyByReason[reason]);
}
function buildStartFeedbackMessage(language, reason) {
    const keyByReason = {
        "single-assignee-required": "serviceRuntimeConfigApproval.feedback.start.singleAssigneeRequired",
        "assignee-only": "serviceRuntimeConfigApproval.feedback.start.assigneeOnly",
        "not-start-approval": "serviceRuntimeConfigApproval.feedback.start.notStartApproval",
        "invalid-workflow-state": "serviceRuntimeConfigApproval.feedback.start.invalidWorkflowState",
    };
    return (0, catalog_1.translate)(language, keyByReason[reason], {
        targetLabel: (0, catalog_1.translate)(language, "serviceRuntimeConfigApproval.feedback.start.targetLabel"),
    });
}
async function resolveBlockingForeignApprovalComment(input) {
    if (input.issue.workflowState.rules.includes(types_2.WORKFLOW_RULES.aiDisabled)) {
        return { required: false, triggerComment: null };
    }
    const assigneeGate = (0, assignee_resolution_1.resolveWorkflowAssigneeGate)({
        assignees: input.issue.assignees,
    });
    if (assigneeGate.kind !== "ok") {
        return { required: false, triggerComment: null };
    }
    const currentAssignee = assigneeGate.assignee;
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, input.stickyState);
    const approvalRequirement = await (0, foreign_input_approval_1.resolveForeignApprovalRequirement)(buildServiceRuntimeForeignApprovalRequirementInput({
        ticketTracker: input.ticketTracker,
        config: effectiveConfig,
        issue: input.issue,
        comments: input.comments,
        scanStartCursor: input.stickyState?.lastScannedCommentCursor ?? null,
        throughCursor: input.throughCursor,
        approvalState: input.stickyState?.foreignInputApproval,
        currentAssignee,
    }));
    return approvalRequirement.required
        ? {
            required: true,
            triggerComment: approvalRequirement.triggerComment,
        }
        : { required: false, triggerComment: null };
}
function applyAcceptedSchedule(workflowState, acceptedAt, commandSchedule, firstRun, displayTimeZone) {
    const schedule = commandSchedule ??
        workflowState.schedule ??
        (0, types_3.createOffWorkflowScheduleState)();
    if (commandSchedule === undefined && firstRun === undefined) {
        return {
            kind: "ok",
            workflowState: {
                ...workflowState,
                schedule,
            },
        };
    }
    const nextRunAt = (0, recurring_1.resolveInitialRecurringNextRunAt)({
        schedule,
        firstRun,
        acceptedAt,
        displayTimeZone,
    });
    if (schedule.mode !== "off" && nextRunAt === null) {
        return { kind: "invalid" };
    }
    return {
        kind: "ok",
        workflowState: {
            ...workflowState,
            schedule,
            nextRunAt,
        },
    };
}
async function resolveAcceptedWorkflowStateForCommand(input) {
    if (input.command.workflowSelection === undefined) {
        return resolveAcceptedWorkflowStateWithoutWorkflowSelection(input);
    }
    const resolvedWorkflowState = await resolveAcceptedWorkflowSelectionState({
        repoRoot: input.repoRoot,
        locale: input.locale,
        config: input.config,
        issue: input.issue,
        stickyState: input.stickyState,
        command: input.command,
        maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
    });
    if (resolvedWorkflowState.kind === "handoff") {
        return resolvedWorkflowState;
    }
    return {
        kind: "continue",
        workflowState: finalizeAcceptedWorkflowStateForCommand({
            config: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, resolvedWorkflowState.workflowState),
            issue: input.issue,
            workflowState: resolvedWorkflowState.workflowState,
            stickyState: input.stickyState,
            comments: input.comments,
            scannedInputCursor: input.scannedInputCursor,
            selectionPendingPlanningIntent: input.command.workflowSelection === undefined ||
                input.stickyState === null
                ? undefined
                : (0, start_approval_support_1.hasActiveWorkflowStartApproval)({
                    config: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, resolvedWorkflowState.workflowState),
                    issue: input.issue,
                    workflowState: resolvedWorkflowState.workflowState,
                })
                    ? "revise_plan"
                    : "replan",
            commandBodyAfterCommand: input.command.bodyAfterCommand,
        }),
    };
}
async function resolveAcceptedWorkflowStateWithoutWorkflowSelection(input) {
    const applied = (0, command_apply_1.applyWorkflowCommandToStickyState)({
        stickyState: input.stickyState,
        command: input.command,
        baseBranchDefault: input.config.repositoryHost.baseBranch,
        workflowSurface: input.stickyState?.workflowSurface ?? (0, workflow_surface_1.resolveWorkflowSurface)(input.issue),
        workflowTemplateDefaults: input.config.workflowTemplateDefaults,
    });
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, {
        baseBranch: applied.baseBranch,
        ...(applied.configOverrides !== undefined
            ? { configOverrides: applied.configOverrides }
            : {}),
    });
    let catalog;
    try {
        catalog = await (0, template_registry_1.loadWorkflowTemplates)((0, template_registry_1.getWorkflowTemplatesDirectoryPath)(input.repoRoot), input.locale);
    }
    catch (error) {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildWorkflowCatalogErrorSummary)(error, input.locale),
        };
    }
    const workflowSurface = input.stickyState?.workflowSurface ?? (0, workflow_surface_1.resolveWorkflowSurface)(input.issue);
    const workflowTemplateSelectors = buildAppliedWorkflowTemplateSelectorMap({
        workflowTemplates: input.stickyState?.workflowTemplates,
        workflowSurface,
        activeSelector: applied.selection,
        applied,
        defaultSelectors: resolveWorkflowTemplateDefaultsForAppliedCommand({
            config: input.config,
            applied,
        }),
    });
    const sideWorkflowValidation = validateAcceptedWorkflowTemplateSelectors({
        catalog,
        selectors: workflowTemplateSelectors,
        workflowSurface,
        command: input.command,
        locale: input.locale,
        maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
    });
    if (sideWorkflowValidation !== null) {
        return sideWorkflowValidation;
    }
    const workflowTemplates = (0, template_bindings_1.resolveWorkflowTemplateBindings)({
        catalog,
        selectors: workflowTemplateSelectors,
    });
    const workflowState = input.stickyState === null
        ? (0, pre_plan_state_1.buildSelectionTransitionWorkflowState)({
            previousState: null,
            workflowSurface,
            workflowTemplates,
            baseBranch: applied.baseBranch,
            schedule: applied.schedule,
            ...(applied.didUpdateSchedule ? { scheduledRun: null } : {}),
            configOverrides: applied.configOverrides,
            followup: (0, followup_policy_1.resolveWorkflowFollowupState)({
                currentStateExists: false,
                config: effectiveConfig.followup,
            }),
        })
        : {
            ...(0, command_apply_1.applyAppliedWorkflowCommandToPersistedState)(input.stickyState, applied),
            workflowTemplates,
        };
    const refreshedWorkflowState = refreshFollowupProposalStateForCommand({
        workflowState,
        command: input.command,
        effectiveConfig: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, workflowState),
    });
    const preferredWorkflowValidation = validateAcceptedFollowupPreferredWorkflowTemplates({
        catalog,
        preferredWorkflowTemplates: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, refreshedWorkflowState).followup.preferredWorkflowTemplates,
        locale: input.locale,
        maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
    });
    if (preferredWorkflowValidation !== null) {
        return preferredWorkflowValidation;
    }
    return {
        kind: "continue",
        workflowState: finalizeAcceptedWorkflowStateForCommand({
            config: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, refreshedWorkflowState),
            issue: input.issue,
            workflowState: refreshedWorkflowState,
            stickyState: input.stickyState,
            comments: input.comments,
            scannedInputCursor: input.scannedInputCursor,
            selectionPendingPlanningIntent: undefined,
            commandBodyAfterCommand: input.command.bodyAfterCommand,
        }),
    };
}
async function resolveAcceptedWorkflowSelectionState(input) {
    const workflowSurface = input.stickyState?.workflowSurface ?? (0, workflow_surface_1.resolveWorkflowSurface)(input.issue);
    let catalog;
    try {
        catalog = await (0, template_registry_1.loadWorkflowTemplates)((0, template_registry_1.getWorkflowTemplatesDirectoryPath)(input.repoRoot), input.locale);
    }
    catch (error) {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildWorkflowCatalogErrorSummary)(error, input.locale),
        };
    }
    const resolution = (0, template_registry_1.resolveWorkflowTemplateBindingSelection)({
        catalog,
        workflowSurface,
        stickySelection: input.stickyState === null
            ? null
            : ((0, template_bindings_1.getActiveWorkflowTemplateBinding)({
                workflowTemplates: input.stickyState.workflowTemplates,
                workflowSurface,
            })?.selector ?? null),
        defaultSelection: (0, template_bindings_1.isWorkflowTemplateBindingSurface)(workflowSurface)
            ? (0, control_plane_config_1.resolveWorkflowTemplateDefaultsWithFollowup)(input.config)[workflowSurface]
            : null,
        command: input.command,
    }, input.locale);
    if (resolution.kind === "invalid-command") {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildInvalidWorkflowCommandSummary)(resolution, input.locale),
        };
    }
    if (resolution.kind === "missing-template") {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildMissingWorkflowTemplateSummary)(resolution, input.locale),
        };
    }
    if (resolution.template !== null) {
        const validation = (0, workflow_template_selection_validation_1.validateWorkflowTemplateSelection)({
            catalog,
            templatePath: resolution.template.templatePath,
            workflowSurface,
            maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
        });
        if (validation.kind === "invalid-tree") {
            return {
                kind: "handoff",
                summary: (0, validation_format_1.formatWorkflowTemplateValidationSummary)({
                    locale: input.locale,
                    diagnostics: validation.diagnostics,
                    templatePath: validation.template.templatePath,
                }),
            };
        }
    }
    const applied = (0, command_apply_1.applyWorkflowCommandToStickyState)({
        stickyState: input.stickyState,
        command: input.command,
        baseBranchDefault: input.config.repositoryHost.baseBranch,
        workflowSurface,
        workflowTemplateDefaults: input.config.workflowTemplateDefaults,
    });
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, {
        baseBranch: applied.baseBranch,
        ...(applied.configOverrides !== undefined
            ? { configOverrides: applied.configOverrides }
            : {}),
    });
    const workflowTemplateSelectors = buildAppliedWorkflowTemplateSelectorMap({
        workflowTemplates: input.stickyState?.workflowTemplates,
        workflowSurface,
        activeSelector: resolution.binding.selector,
        applied,
        defaultSelectors: resolveWorkflowTemplateDefaultsForAppliedCommand({
            config: input.config,
            applied,
        }),
    });
    const sideWorkflowValidation = validateAcceptedWorkflowTemplateSelectors({
        catalog,
        selectors: workflowTemplateSelectors,
        workflowSurface,
        command: input.command,
        locale: input.locale,
        maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
    });
    if (sideWorkflowValidation !== null) {
        return sideWorkflowValidation;
    }
    const workflowState = (0, pre_plan_state_1.buildSelectionTransitionWorkflowState)({
        previousState: input.stickyState,
        workflowSurface,
        workflowTemplates: (0, template_bindings_1.resolveWorkflowTemplateBindings)({
            catalog,
            selectors: workflowTemplateSelectors,
        }),
        baseBranch: applied.baseBranch,
        schedule: applied.schedule,
        ...(applied.didUpdateSchedule ? { scheduledRun: null } : {}),
        configOverrides: applied.configOverrides,
        followup: (0, followup_policy_1.resolveWorkflowFollowupState)({
            currentFollowup: input.stickyState?.followup,
            currentStateExists: input.stickyState !== null,
            config: effectiveConfig.followup,
            refreshPolicy: hasFollowupProposalConfigOverride(input.command),
        }),
    });
    const preferredWorkflowValidation = validateAcceptedFollowupPreferredWorkflowTemplates({
        catalog,
        preferredWorkflowTemplates: (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, workflowState).followup.preferredWorkflowTemplates,
        locale: input.locale,
        maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
    });
    if (preferredWorkflowValidation !== null) {
        return preferredWorkflowValidation;
    }
    return {
        kind: "continue",
        workflowState,
    };
}
function resolveEffectiveConfigForAppliedCommand(input) {
    return (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, {
        baseBranch: input.applied.baseBranch,
        ...(input.applied.configOverrides !== undefined
            ? { configOverrides: input.applied.configOverrides }
            : {}),
    });
}
function refreshFollowupProposalStateForCommand(input) {
    if (!hasFollowupProposalConfigOverride(input.command)) {
        return input.workflowState;
    }
    return {
        ...input.workflowState,
        followup: (0, followup_policy_1.resolveWorkflowFollowupState)({
            currentFollowup: input.workflowState.followup,
            currentStateExists: true,
            config: input.effectiveConfig.followup,
            refreshPolicy: true,
        }),
    };
}
function hasFollowupProposalConfigOverride(command) {
    return (command.configOverridePatch?.entries.some((entry) => entry.path === "followup.proposalPolicy" ||
        entry.path === "followup.proposalApproval") ?? false);
}
function resolveWorkflowTemplateDefaultsForAppliedCommand(input) {
    return (0, control_plane_config_1.resolveWorkflowTemplateDefaultsWithFollowup)(resolveEffectiveConfigForAppliedCommand(input));
}
function buildAppliedWorkflowTemplateSelectorMap(input) {
    return (0, template_bindings_1.addWorkflowTemplateSelectors)({
        selectors: (0, template_bindings_1.createWorkflowTemplateSelectorMap)({
            workflowTemplates: input.workflowTemplates,
            defaultSelectors: input.defaultSelectors,
            selectors: {
                [input.workflowSurface]: input.activeSelector,
            },
        }),
        updates: input.applied.workflowTemplateSelectors,
    });
}
function validateAcceptedWorkflowTemplateSelectors(input) {
    if ((0, template_bindings_1.isWorkflowTemplateBindingSurface)(input.workflowSurface)) {
        const selector = input.selectors[input.workflowSurface];
        if (selector?.mode === "no_template") {
            const validation = validateAcceptedWorkflowTemplatePath({
                catalog: input.catalog,
                selector,
                templatePath: (0, workflow_template_selection_validation_1.resolveSelectedWorkflowTemplatePath)(selector, input.workflowSurface),
                workflowSurface: input.workflowSurface,
                locale: input.locale,
                maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
            });
            if (validation !== null) {
                return validation;
            }
        }
    }
    for (const surface of template_bindings_1.SIDE_WORKFLOW_TEMPLATE_SURFACES) {
        const selector = input.selectors[surface];
        const validation = validateAcceptedWorkflowTemplatePath({
            catalog: input.catalog,
            selector,
            templatePath: (0, workflow_template_selection_validation_1.resolveSelectedWorkflowTemplatePath)(selector, surface),
            workflowSurface: surface,
            locale: input.locale,
            maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
        });
        if (validation !== null) {
            return validation;
        }
    }
    return null;
}
function validateAcceptedFollowupPreferredWorkflowTemplates(input) {
    for (const candidate of input.preferredWorkflowTemplates) {
        const selector = (0, types_3.parseFollowupWorkflowTemplateCandidateSelector)(candidate);
        if (selector === null) {
            continue;
        }
        const validation = validateAcceptedWorkflowTemplatePath({
            catalog: input.catalog,
            selector,
            templatePath: (0, workflow_template_selection_validation_1.resolveSelectedWorkflowTemplatePath)(selector, "followup"),
            workflowSurface: "followup",
            locale: input.locale,
            maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
        });
        if (validation !== null) {
            return validation;
        }
    }
    return null;
}
function validateAcceptedWorkflowTemplatePath(input) {
    const validation = (0, workflow_template_selection_validation_1.validateWorkflowTemplateSelection)({
        catalog: input.catalog,
        templatePath: input.templatePath,
        workflowSurface: input.workflowSurface,
        maxNestedWorkflowDepth: input.maxNestedWorkflowDepth,
    });
    switch (validation.kind) {
        case "ok":
            return null;
        case "missing-template":
            return {
                kind: "handoff",
                summary: (0, run_context_summaries_1.buildMissingWorkflowTemplateSummary)({
                    kind: "missing-template",
                    source: "command",
                    selection: input.selector ??
                        {
                            mode: "template",
                            templatePath: validation.templatePath,
                        },
                    missingTemplatePath: validation.templatePath,
                    availableTemplatePaths: validation.availableTemplatePaths,
                    suggestions: [],
                }, input.locale),
            };
        case "invalid-tree":
            return {
                kind: "handoff",
                summary: (0, validation_format_1.formatWorkflowTemplateValidationSummary)({
                    locale: input.locale,
                    diagnostics: validation.diagnostics,
                    templatePath: validation.template.templatePath,
                }),
            };
        case "invalid-surface":
            return {
                kind: "handoff",
                summary: (0, catalog_1.translate)(input.locale, "workflow.runContext.invalidTemplateSurface", {
                    templatePath: validation.template.templatePath,
                    surface: input.workflowSurface,
                }),
            };
    }
}
function finalizeAcceptedWorkflowStateForCommand(input) {
    const normalizedWorkflowState = (0, start_approval_support_1.normalizeWorkflowStartApprovalState)({
        config: input.config,
        issue: input.issue,
        workflowState: input.workflowState,
    });
    const hasStartApproval = (0, start_approval_support_1.hasActiveWorkflowStartApproval)({
        config: input.config,
        issue: input.issue,
        workflowState: normalizedWorkflowState,
    });
    const commandPendingPlanningReason = (0, optional_text_1.normalizeOptionalText)(input.commandBodyAfterCommand);
    const commandPendingPlanningIntent = commandPendingPlanningReason === null
        ? undefined
        : hasStartApproval
            ? "revise_plan"
            : "replan";
    const stickyPendingPlanningIntent = input.stickyState?.pendingPlanningIntent === "revise_plan" &&
        !hasStartApproval
        ? undefined
        : input.stickyState?.pendingPlanningIntent;
    const pendingPlanningIntent = commandPendingPlanningIntent ??
        stickyPendingPlanningIntent ??
        input.selectionPendingPlanningIntent;
    const isPlanningContinuation = pendingPlanningIntent !== undefined;
    const nextState = {
        ...normalizedWorkflowState,
        consecutiveAiRuns: resolveAcceptedConsecutiveAiRuns({
            stickyState: input.stickyState,
            comments: input.comments,
            isPlanningContinuation,
        }),
        totalAiRunHours: resolveAcceptedTotalAiRunHours({
            stickyState: input.stickyState,
            comments: input.comments,
            isPlanningContinuation,
        }),
        lastScannedCommentCursor: input.scannedInputCursor,
        lastRunAt: normalizedWorkflowState.lastRunAt ?? null,
        lastOutcome: normalizedWorkflowState.lastOutcome ?? null,
        finalResult: null,
    };
    if (pendingPlanningIntent !== undefined) {
        nextState.pendingPlanningIntent = pendingPlanningIntent;
        nextState.pendingPlanningReason =
            commandPendingPlanningReason ??
                input.stickyState?.pendingPlanningReason ??
                null;
        if (commandPendingPlanningReason !== null) {
            delete nextState.pendingPlanningSource;
        }
    }
    else {
        delete nextState.pendingPlanningIntent;
        delete nextState.pendingPlanningReason;
    }
    return nextState;
}
function applyAcceptedIssueCompletionAutoMergeState(input) {
    if (input.issue.kind !== types_1.TRACKER_ITEM_KINDS.pullRequest ||
        input.nextSnapshot.status !== types_2.WORKFLOW_STATUSES.aiReady ||
        !(0, issue_completion_1.shouldSkipPullRequestReview)(input.config.issueCompletion) ||
        !(0, issue_completion_1.isPullRequestAutoMergePolicyEnabled)(input.config.issueCompletion) ||
        input.workflowState.autoMergeState !== undefined) {
        return input.workflowState;
    }
    const workflowState = {
        ...input.workflowState,
        autoMergeState: auto_merge_state_1.WORKFLOW_AUTO_MERGE_STATES.pending,
    };
    delete workflowState.needsHumanReason;
    return workflowState;
}
function resolveAcceptedConsecutiveAiRuns(input) {
    if (!input.isPlanningContinuation) {
        return 0;
    }
    if (input.stickyState === null) {
        return 0;
    }
    return (0, workflow_timeline_scan_1.hasActionableWorkflowCommentAfterCursor)(input.comments, input.stickyState.lastScannedCommentCursor ?? null)
        ? 0
        : input.stickyState.consecutiveAiRuns;
}
function resolveAcceptedTotalAiRunHours(input) {
    if (!input.isPlanningContinuation) {
        return 0;
    }
    if (input.stickyState === null) {
        return 0;
    }
    return (0, workflow_timeline_scan_1.hasActionableWorkflowCommentAfterCursor)(input.comments, input.stickyState.lastScannedCommentCursor ?? null)
        ? 0
        : input.stickyState.totalAiRunHours;
}
function resolveNextSnapshotAfterCommand(input) {
    return resolveBaseSnapshotAfterAcceptedCommand(input).then((baseSnapshot) => (0, scheduled_run_1.resolveScheduledRunProjection)({
        workflowState: input.workflowState,
        snapshot: (0, recurring_1.resolveRecurringProjection)({
            snapshot: baseSnapshot,
            workflowState: input.workflowState,
        }).snapshot,
    }));
}
async function resolveBaseSnapshotAfterAcceptedCommand(input) {
    if (input.promotesReady ||
        (input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiScheduled &&
            !(0, scheduled_run_1.hasActiveScheduledRun)(input.workflowState)) ||
        (await isThreadRunnableAfterEffectiveConfig(input))) {
        return {
            status: types_2.WORKFLOW_STATUSES.aiReady,
            rules: [...input.issue.workflowState.rules],
        };
    }
    return {
        status: input.issue.workflowState.status,
        rules: [...input.issue.workflowState.rules],
    };
}
async function isThreadRunnableAfterEffectiveConfig(input) {
    if (input.issue.workflowState.status !== types_2.WORKFLOW_STATUSES.aiNeedsHuman) {
        return false;
    }
    if (await isAssigneeResolutionStillRequired(input)) {
        return false;
    }
    if ((0, start_approval_support_1.hasActiveWorkflowStartApproval)({
        config: input.effectiveConfig,
        issue: input.issue,
        workflowState: input.workflowState,
    })) {
        return false;
    }
    const foreignApprovalReleased = await resolveForeignApprovalRelease(input);
    if (foreignApprovalReleased !== null) {
        return foreignApprovalReleased;
    }
    if (input.currentNeedsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.startApproval) {
        return true;
    }
    if (input.currentNeedsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.question) {
        return false;
    }
    if (input.currentNeedsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.reviewReady) {
        return isReviewReadyReleasedByIssueCompletionChange(input);
    }
    if (input.currentNeedsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.runLimit) {
        const previousRunLimit = (0, run_limit_policy_1.resolveAiRunLimitPolicy)({
            config: input.previousEffectiveConfig,
            consecutiveAiRuns: input.previousConsecutiveAiRuns,
            totalAiRunHours: input.workflowState.totalAiRunHours,
        });
        const nextRunLimit = (0, run_limit_policy_1.resolveAiRunLimitPolicy)({
            config: input.effectiveConfig,
            consecutiveAiRuns: input.previousConsecutiveAiRuns,
            totalAiRunHours: input.workflowState.totalAiRunHours,
        });
        return previousRunLimit.reached && !nextRunLimit.reached;
    }
    return (input.issue.kind === "pull_request" &&
        !isIssueCompletionPolicyRunnableOnReviewReady(input.previousEffectiveConfig) &&
        isIssueCompletionPolicyRunnableOnReviewReady(input.effectiveConfig));
}
function isReviewReadyReleasedByIssueCompletionChange(input) {
    const previousIssueCompletion = input.previousEffectiveConfig.issueCompletion;
    const nextIssueCompletion = input.effectiveConfig.issueCompletion;
    if (input.issue.kind === "issue") {
        return (previousIssueCompletion.target === "pause_on_issue" &&
            nextIssueCompletion.target !== "pause_on_issue");
    }
    if (input.issue.kind !== "pull_request") {
        return false;
    }
    return (!areIssueCompletionPoliciesEqual(previousIssueCompletion, nextIssueCompletion) && isIssueCompletionPolicyRunnableOnReviewReady(input.effectiveConfig));
}
function isIssueCompletionPolicyRunnableOnReviewReady(config) {
    return (0, issue_completion_1.shouldReleaseReviewReadyPullRequest)(config.issueCompletion);
}
function areIssueCompletionPoliciesEqual(left, right) {
    return (left.target === right.target &&
        left.pullRequest.reviewPolicy === right.pullRequest.reviewPolicy &&
        left.pullRequest.mergePolicy === right.pullRequest.mergePolicy);
}
async function isAssigneeResolutionStillRequired(input) {
    const assigneeGate = (0, assignee_resolution_1.resolveWorkflowAssigneeGate)({
        assignees: input.issue.assignees,
    });
    if (assigneeGate.kind === "ok") {
        return false;
    }
    if ((0, start_approval_support_1.hasActiveWorkflowStartApproval)({
        config: input.effectiveConfig,
        issue: input.issue,
        workflowState: input.workflowState,
    })) {
        return true;
    }
    const approvalRequirement = await (0, foreign_input_approval_1.resolveForeignApprovalRequirement)({
        ...buildServiceRuntimeForeignApprovalRequirementInput({
            ticketTracker: input.ticketTracker,
            config: input.effectiveConfig,
            issue: input.issue,
            comments: input.comments,
            scanStartCursor: input.workflowState.lastScannedCommentCursor,
            approvalState: input.workflowState.foreignInputApproval,
            currentAssignee: null,
        }),
    });
    return approvalRequirement.required;
}
async function resolveForeignApprovalRelease(input) {
    const currentAssignee = input.issue.assignees.length === 1
        ? (input.issue.assignees[0] ?? null)
        : null;
    if (currentAssignee === null) {
        return null;
    }
    const previouslyRequired = await (0, foreign_input_approval_1.resolveForeignApprovalRequirement)(buildServiceRuntimeForeignApprovalRequirementInput({
        ticketTracker: input.ticketTracker,
        config: input.previousEffectiveConfig,
        issue: input.issue,
        comments: input.comments,
        scanStartCursor: input.workflowState.lastScannedCommentCursor,
        approvalState: input.workflowState.foreignInputApproval,
        currentAssignee,
    }));
    if (!previouslyRequired.required) {
        return null;
    }
    const stillRequired = await (0, foreign_input_approval_1.resolveForeignApprovalRequirement)(buildServiceRuntimeForeignApprovalRequirementInput({
        ticketTracker: input.ticketTracker,
        config: input.effectiveConfig,
        issue: input.issue,
        comments: input.comments,
        scanStartCursor: input.workflowState.lastScannedCommentCursor,
        approvalState: input.workflowState.foreignInputApproval,
        currentAssignee,
    }));
    return !stillRequired.required;
}
function buildServiceRuntimeForeignApprovalRequirementInput(input) {
    const approvalInput = {
        ticketTracker: input.ticketTracker,
        config: input.config,
        issue: input.issue,
        comments: input.comments,
        scanStartCursor: input.scanStartCursor,
        currentAssignee: input.currentAssignee,
    };
    if (input.throughCursor !== undefined) {
        approvalInput.throughCursor = input.throughCursor;
    }
    if (input.approvalState !== undefined) {
        approvalInput.approvalState = input.approvalState;
    }
    return approvalInput;
}
function buildAcceptedMessage(workflowState, language, displayTimeZone, workflowDisplayCatalog) {
    const workflowDisplayLabels = (0, display_labels_1.resolveWorkflowDisplayLabels)({
        catalog: workflowDisplayCatalog,
        workflowTemplates: workflowState.workflowTemplates,
    });
    const workflow = workflowDisplayLabels.workflowTemplateLabel ??
        (0, catalog_1.translate)(language, "workflow.runContext.none");
    const pullRequestWorkflow = workflowDisplayLabels.workflowTemplateLabelsBySurface.pull_request ??
        (0, catalog_1.translate)(language, "workflow.runContext.none");
    const unplannedWorkflow = workflowDisplayLabels.workflowTemplateLabelsBySurface.unplanned ??
        (0, catalog_1.translate)(language, "workflow.runContext.none");
    const followupWorkflow = workflowDisplayLabels.workflowTemplateLabelsBySurface.followup ??
        (0, catalog_1.translate)(language, "workflow.runContext.none");
    const followupProposalPolicy = workflowState.followup?.proposalPolicy ?? "off";
    const followupProposalApproval = workflowState.followup?.proposalApproval ?? "auto";
    const recurring = workflowState.schedule?.mode === "off"
        ? "off"
        : `${workflowState.schedule?.mode} ${workflowState.schedule?.value}`;
    const scheduledRun = workflowState.scheduledRun?.runAt
        ? (0, display_time_1.formatHumanTimestamp)(workflowState.scheduledRun.runAt, language, displayTimeZone)
        : "off";
    const nextRun = workflowState.nextRunAt
        ? (0, display_time_1.formatHumanTimestamp)(workflowState.nextRunAt, language, displayTimeZone)
        : workflowState.scheduledRun?.runAt
            ? (0, display_time_1.formatHumanTimestamp)(workflowState.scheduledRun.runAt, language, displayTimeZone)
            : "-";
    const message = (0, catalog_1.translate)(language, "serviceRuntimeConfigScan.accepted", {
        workflow,
        pullRequestWorkflow,
        unplannedWorkflow,
        followupWorkflow,
        recurring,
        scheduledRun,
        nextRun,
    });
    return `${message}\n${(0, catalog_1.translate)(language, "issue.command.show.pullRequestWorkflow", {
        value: pullRequestWorkflow,
    })}\n${(0, catalog_1.translate)(language, "issue.command.show.unplannedWorkflow", {
        value: unplannedWorkflow,
    })}\n${(0, catalog_1.translate)(language, "issue.command.show.followupWorkflow", {
        value: followupWorkflow,
    })}\n${(0, catalog_1.translate)(language, "issue.command.show.followupProposalPolicy", {
        value: followupProposalPolicy,
    })}\n${(0, catalog_1.translate)(language, "issue.command.show.followupProposalApproval", {
        value: followupProposalApproval,
    })}`;
}
function buildInvalidCommandMessage(language, reason) {
    return (0, catalog_1.translate)(language, "serviceRuntimeConfigScan.invalidCommand", {
        reason: (0, catalog_1.translate)(language, resolveInvalidCommandReasonKey(reason)),
        usage: (0, catalog_1.translate)(language, "workflow.runContext.invalidCommand.usage"),
    });
}
function buildInvalidWorkflowCommandProjection(input) {
    if (input.issue.workflowState.status === types_2.WORKFLOW_STATUSES.aiNeedsHuman) {
        return undefined;
    }
    return (0, config_publish_spec_support_1.buildServiceRuntimeWorkflowProjection)({
        issue: input.issue,
        workflowLabels: input.workflowLabels,
        next: (0, workflow_projection_support_1.withWorkflowStatus)(input.issue.workflowState, types_2.WORKFLOW_STATUSES.aiNeedsHuman),
        previousWorkflowState: input.stickyState,
        nextWorkflowState: input.stickyState,
        previousNeedsHumanReason: input.currentNeedsHumanReason,
        nextNeedsHumanReason: null,
    });
}
function resolveInvalidCommandReasonKey(reason) {
    switch (reason) {
        case "missing-options":
            return "workflow.runContext.invalidCommand.missingOptions";
        case "missing-option-value":
            return "workflow.runContext.invalidCommand.missingOptionValue";
        case "invalid-option-value":
            return "workflow.runContext.invalidCommand.invalidOptionValue";
        case "duplicate-option":
            return "workflow.runContext.invalidCommand.duplicateOption";
        case "conflicting-schedule-options":
            return "workflow.runContext.invalidCommand.conflictingScheduleOptions";
        case "unsupported-command-body":
            return "workflow.runContext.invalidCommand.unsupportedCommandBody";
        default:
            return "workflow.runContext.invalidCommand.unexpectedArgument";
    }
}
