"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveWorkflowRunRoute = resolveWorkflowRunRoute;
const plan_progress_1 = require("./plan-progress");
const state_1 = require("./state");
const template_bindings_1 = require("./template-bindings");
const workflow_command_state_1 = require("./workflow-command-state");
const workflow_selection_support_1 = require("./workflow-selection-support");
function resolveWorkflowRunRoute(input) {
    if (isMergeIntegrationExecution(input.prepared.normalizedStickyState)) {
        return {
            kind: "execute",
            branch: "execute",
        };
    }
    const planningCommand = (0, workflow_command_state_1.getPendingWorkflowCommandUpdate)(input.prepared.latestCommand);
    const shouldPlan = shouldPlanWorkflowRun({
        stickyState: input.prepared.normalizedStickyState,
        resolution: input.prepared.resolution,
        command: planningCommand,
        shouldReplan: input.prepared.shouldReplan,
    });
    const planningIntent = shouldPlan
        ? resolveWorkflowPlanningIntent({
            stickyState: input.prepared.normalizedStickyState,
            resolution: input.prepared.resolution,
            command: planningCommand,
            shouldReplan: input.prepared.shouldReplan,
        })
        : null;
    const shouldSelect = shouldSelectWorkflowRun({
        prepared: input.prepared,
        command: planningCommand,
    });
    if (shouldPlan && shouldSelect) {
        return {
            kind: "select",
            branch: input.prepared.resolution.template !== null
                ? "select_with_template"
                : "select_without_template",
            planningIntent: planningIntent ?? "new_plan",
        };
    }
    if (shouldPlan) {
        return {
            kind: "plan",
            branch: input.prepared.resolution.template !== null
                ? "plan_template"
                : "plan_without_template",
            planningIntent: planningIntent ?? "new_plan",
            requiresPreflightReplan: input.prepared.resolution.template !== null
                ? shouldRequestPreflightReplan({
                    stickyState: input.prepared.normalizedStickyState,
                    resolution: input.prepared.resolution,
                    command: planningCommand,
                    shouldReplan: input.prepared.shouldReplan,
                })
                : false,
        };
    }
    return {
        kind: "execute",
        branch: "execute",
    };
}
function isMergeIntegrationExecution(stickyState) {
    return (stickyState?.workflowSurface === "merge" &&
        stickyState.pendingPlanningIntent === "replan" &&
        stickyState.plan !== null);
}
function shouldSelectWorkflowRun(input) {
    const { prepared } = input;
    if (prepared.resolution.binding.selector.mode === "auto" &&
        (prepared.resolution.binding.resolution.kind !== "template" ||
            input.command?.workflowSelection?.mode === "auto")) {
        return true;
    }
    if (prepared.resolution.binding.selector.mode === "auto_select" &&
        (prepared.resolution.binding.resolution.kind !== "template" ||
            input.command?.workflowSelection?.mode === "auto_select")) {
        return true;
    }
    return false;
}
function shouldRequestPreflightReplan(input) {
    if (input.stickyState === null) {
        return false;
    }
    if (input.command !== null || input.shouldReplan) {
        return false;
    }
    if (hasWorkflowSelectionChanged(input.stickyState, input.resolution)) {
        return false;
    }
    return hasWorkflowTemplateDrift(input.stickyState, input.resolution);
}
function resolveWorkflowPlanningIntent(input) {
    if (input.stickyState === null) {
        return "new_plan";
    }
    if (input.shouldReplan) {
        return "replan";
    }
    if (input.stickyState.pendingPlanningIntent !== undefined) {
        return input.stickyState.pendingPlanningIntent;
    }
    if (hasWorkflowSelectionChanged(input.stickyState, input.resolution)) {
        return (0, state_1.hasPendingWorkflowStartApproval)(input.stickyState)
            ? "revise_plan"
            : "replan";
    }
    if (hasWorkflowTemplateDrift(input.stickyState, input.resolution)) {
        return (0, state_1.hasPendingWorkflowStartApproval)(input.stickyState)
            ? "revise_plan"
            : "replan";
    }
    return "new_plan";
}
function shouldPlanWorkflowRun(input) {
    if (input.shouldReplan) {
        return true;
    }
    if (input.stickyState?.pendingPlanningIntent !== undefined) {
        return true;
    }
    if (input.stickyState === null) {
        return input.command === null;
    }
    if (hasWorkflowSelectionChanged(input.stickyState, input.resolution)) {
        return true;
    }
    if (hasWorkflowTemplateDrift(input.stickyState, input.resolution)) {
        return true;
    }
    if (input.stickyState.plan === null) {
        return true;
    }
    return !isRunnableWorkflowPlan(input.stickyState.plan);
}
function hasWorkflowTemplateDrift(stickyState, resolution) {
    if (stickyState === null) {
        return false;
    }
    const previousBinding = (0, template_bindings_1.getActiveWorkflowTemplateBinding)(stickyState);
    if (previousBinding === null) {
        return false;
    }
    const previousResolution = previousBinding.resolution;
    const nextResolution = resolution.binding.resolution;
    if (previousResolution.kind !== nextResolution.kind) {
        return true;
    }
    return (previousResolution.kind === "template" &&
        nextResolution.kind === "template" &&
        (previousResolution.templatePath !== nextResolution.templatePath ||
            previousResolution.digest !== nextResolution.digest));
}
function hasWorkflowSelectionChanged(stickyState, resolution) {
    const previousBinding = (0, template_bindings_1.getActiveWorkflowTemplateBinding)(stickyState);
    return (previousBinding !== null &&
        !(0, workflow_selection_support_1.areWorkflowSelectionsEqual)(previousBinding.selector, resolution.binding.selector));
}
function isRunnableWorkflowPlan(plan) {
    return ((0, plan_progress_1.selectNextReadyWorkflowStep)(plan) !== null || (0, plan_progress_1.isCompletedWorkflowPlan)(plan));
}
