"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sanitizeWorkerVisibleWorkflowState = sanitizeWorkerVisibleWorkflowState;
exports.prepareWorkflowRoutingInputs = prepareWorkflowRoutingInputs;
const canonical_workflow_state_1 = require("../comments/canonical-workflow-state");
const workflow_update_1 = require("../comments/workflow-update");
const control_plane_config_1 = require("../config/control-plane-config");
const catalog_1 = require("../i18n/catalog");
const command_apply_1 = require("./command-apply");
const foreign_input_approval_1 = require("./foreign-input-approval");
const run_context_summaries_1 = require("./run-context-summaries");
const template_registry_1 = require("./template-registry");
const workflow_command_state_1 = require("./workflow-command-state");
const followup_policy_1 = require("./followup-policy");
const types_1 = require("./types");
const template_bindings_1 = require("./template-bindings");
function sanitizeWorkerVisibleWorkflowState(workflowState, options = {}) {
    if (workflowState === null) {
        return workflowState;
    }
    const stripDependencySyncState = options.includeDependencySyncState !== true &&
        workflowState.dependencySyncState !== undefined;
    const stripMergeContext = workflowState.mergeContext !== undefined;
    if (!stripDependencySyncState && !stripMergeContext) {
        return workflowState;
    }
    const { dependencySyncState, mergeContext: _mergeContext, ...sanitizedState } = workflowState;
    if (!stripDependencySyncState && dependencySyncState !== undefined) {
        return {
            ...sanitizedState,
            dependencySyncState,
        };
    }
    return sanitizedState;
}
async function prepareWorkflowRoutingInputs(input) {
    const workflowTemplateDefaults = input.workflowTemplateDefaults ?? control_plane_config_1.DEFAULT_CONFIG.workflowTemplateDefaults;
    const canonicalComment = (0, canonical_workflow_state_1.resolveCanonicalWorkflowStateComment)(input.comments, input.locale);
    if (canonicalComment.kind === "invalid") {
        return {
            kind: "handoff",
            summary: canonicalComment.summary,
            workflowTemplateName: null,
            workflowState: null,
        };
    }
    const latestUpdate = findLatestWorkflowUpdate(input.comments);
    const workflowStateForScan = canonicalComment.kind === "found"
        ? canonicalComment.workflowState
        : input.bootstrapWorkflowState;
    const latestCommand = (0, workflow_command_state_1.resolvePendingWorkflowCommand)(input.comments, {
        issueBody: input.issueBody,
        workflowState: workflowStateForScan,
    });
    const latestCommandUpdate = (0, workflow_command_state_1.getPendingWorkflowCommandUpdate)(latestCommand);
    const catalog = await loadWorkflowTemplateCatalogForRouting(input);
    if ("kind" in catalog) {
        return catalog;
    }
    const stickyState = canonicalComment.kind === "found"
        ? canonicalComment.workflowState
        : input.bootstrapWorkflowState;
    const activeWorkflowSurface = stickyState?.workflowSurface ?? input.workflowSurface;
    const preCanonicalForeignInputApproval = stickyState === null
        ? await (0, foreign_input_approval_1.resolvePreCanonicalForeignInputApproval)({
            comments: input.comments,
            approvedAssignee: input.foreignInputApprovalAssignee,
        })
        : undefined;
    const appliedCommandState = (0, command_apply_1.applyWorkflowCommandToStickyState)({
        stickyState,
        command: latestCommandUpdate,
        baseBranchDefault: input.baseBranchDefault ?? "main",
        workflowSurface: activeWorkflowSurface,
        workflowTemplateDefaults,
    });
    const followupConfig = (0, followup_policy_1.resolveWorkflowFollowupConfigFromPatch)(input.followupConfig ?? control_plane_config_1.DEFAULT_CONFIG.followup, appliedCommandState.configOverrides);
    const shouldReplan = appliedCommandState.shouldReplan ||
        shouldSelectActiveWorkflowTemplate({
            activeWorkflowSurface,
            appliedCommandState,
            catalog,
            command: latestCommandUpdate,
            stickyState,
        }) ||
        hasActiveSideWorkflowTemplateUpdate(appliedCommandState, activeWorkflowSurface);
    const resolution = resolveAutoWorkflowTemplateResolutionFromStickyState({
        catalog,
        command: latestCommandUpdate,
        resolution: (0, template_registry_1.resolveWorkflowTemplateBindingSelection)({
            catalog,
            workflowSurface: activeWorkflowSurface,
            stickySelection: resolveStickySelectionForTemplateRouting({
                workflowSurface: activeWorkflowSurface,
                appliedCommandState,
                catalog,
            }),
            defaultSelection: (0, template_bindings_1.isWorkflowTemplateBindingSurface)(activeWorkflowSurface)
                ? workflowTemplateDefaults[activeWorkflowSurface]
                : null,
            command: latestCommand?.command.kind === "invalid"
                ? latestCommand.command
                : null,
        }, input.locale),
        stickyState,
        workflowSurface: activeWorkflowSurface,
    });
    if (resolution.kind === "invalid-command") {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildInvalidWorkflowCommandSummary)(resolution, input.locale),
            workflowTemplateName: null,
            workflowState: stickyState,
        };
    }
    if (resolution.kind === "missing-template") {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildMissingWorkflowTemplateSummary)(resolution, input.locale),
            workflowTemplateName: null,
            workflowState: null,
        };
    }
    const missingCanonicalHandoff = buildMissingCanonicalExecutionHandoff({
        canonicalMissing: canonicalComment.kind === "missing",
        latestWorkflowTemplateLabel: latestUpdate?.parsed.workflowTemplateLabel,
        latestCommand,
        locale: input.locale,
    });
    if (missingCanonicalHandoff !== null) {
        return missingCanonicalHandoff;
    }
    const prepared = {
        catalog,
        stickyState,
        normalizedStickyState: resolveNormalizedStickyState({
            canonicalFound: canonicalComment.kind === "found",
            bootstrapWorkflowState: input.bootstrapWorkflowState,
            stickyState,
            workflowSurface: activeWorkflowSurface,
            activeWorkflowTemplateResolution: resolution.binding.resolution,
        }),
        latestCommand,
        appliedCommandState,
        shouldReplan,
        workflowSurface: activeWorkflowSurface,
        resolution,
        workflowTemplateDefaults,
        followupConfig,
    };
    if (preCanonicalForeignInputApproval !== undefined) {
        prepared.preCanonicalForeignInputApproval =
            preCanonicalForeignInputApproval;
    }
    return prepared;
}
async function loadWorkflowTemplateCatalogForRouting(input) {
    const workflowTemplatesDirectory = (0, template_registry_1.getWorkflowTemplatesDirectoryPath)(input.repoRoot);
    try {
        return await (0, template_registry_1.loadWorkflowTemplates)(workflowTemplatesDirectory, input.locale);
    }
    catch (error) {
        return {
            kind: "handoff",
            summary: (0, run_context_summaries_1.buildWorkflowCatalogErrorSummary)(error, input.locale),
            workflowTemplateName: null,
            workflowState: null,
        };
    }
}
function buildMissingCanonicalExecutionHandoff(input) {
    if (!input.canonicalMissing ||
        input.latestWorkflowTemplateLabel == null ||
        input.latestCommand !== null) {
        return null;
    }
    return {
        kind: "handoff",
        summary: (0, catalog_1.translate)(input.locale, "workflow.runContext.canonical.missingForExecution"),
        workflowTemplateName: input.latestWorkflowTemplateLabel,
        workflowState: null,
    };
}
function resolveNormalizedStickyState(input) {
    if (input.canonicalFound ||
        input.bootstrapWorkflowState === null ||
        input.stickyState !== input.bootstrapWorkflowState) {
        return input.stickyState;
    }
    if (!(0, template_bindings_1.isWorkflowTemplateBindingSurface)(input.workflowSurface)) {
        return input.stickyState;
    }
    const binding = (0, template_bindings_1.getWorkflowTemplateBinding)({
        workflowTemplates: input.stickyState.workflowTemplates,
        surface: input.workflowSurface,
    });
    return {
        ...input.stickyState,
        workflowTemplates: (0, template_bindings_1.setWorkflowTemplateBinding)({
            workflowTemplates: input.stickyState.workflowTemplates,
            surface: input.workflowSurface,
            binding: (0, template_bindings_1.createWorkflowTemplateBinding)({
                selector: binding.selector,
                resolution: input.activeWorkflowTemplateResolution,
            }),
        }),
    };
}
function resolveAutoWorkflowTemplateResolutionFromStickyState(input) {
    if (input.resolution.kind !== "resolved" ||
        input.resolution.binding.selector.mode !== "auto" ||
        input.resolution.binding.resolution.kind !== "none" ||
        input.command?.workflowSelection?.mode === "auto" ||
        input.stickyState === null) {
        return input.resolution;
    }
    const stickyBinding = (0, template_bindings_1.getActiveWorkflowTemplateBinding)({
        workflowTemplates: input.stickyState.workflowTemplates,
        workflowSurface: input.workflowSurface,
    });
    if (stickyBinding === null ||
        stickyBinding.selector.mode !== "auto" ||
        stickyBinding.resolution.kind !== "template") {
        return input.resolution;
    }
    const template = input.catalog.templateByPath.get(stickyBinding.resolution.templatePath);
    if (template === undefined ||
        template.system ||
        !(0, template_bindings_1.isWorkflowTemplateBindingSurface)(input.workflowSurface) ||
        !(0, template_registry_1.workflowTemplateTargetsSurface)(template, input.workflowSurface)) {
        return input.resolution;
    }
    return {
        ...input.resolution,
        binding: (0, template_bindings_1.createWorkflowTemplateBinding)({
            selector: input.resolution.binding.selector,
            resolution: (0, template_bindings_1.buildWorkflowTemplateResolution)(template),
        }),
        template,
    };
}
function resolveStickySelectionForTemplateRouting(input) {
    if (input.workflowSurface === "issue") {
        return input.appliedCommandState.selectionSource === "implicit" ||
            input.appliedCommandState.selectionSource === "config"
            ? null
            : input.appliedCommandState.selection;
    }
    if (!(0, template_bindings_1.isSideWorkflowTemplateSurface)(input.workflowSurface)) {
        return null;
    }
    return resolveSurfaceSelectorForTemplateRouting({
        primarySelection: input.appliedCommandState.selection,
        primarySelectionSource: input.appliedCommandState.selectionSource,
        sideSelector: (0, command_apply_1.getAppliedWorkflowTemplateSelector)(input.appliedCommandState, input.workflowSurface),
        catalog: input.catalog,
        workflowSurface: input.workflowSurface,
    });
}
function resolveSurfaceSelectorForTemplateRouting(input) {
    if (input.sideSelector !== undefined) {
        return input.sideSelector;
    }
    if (input.primarySelectionSource === "implicit" ||
        input.primarySelectionSource === "config") {
        return null;
    }
    if (selectorTargetsWorkflowSurface(input.primarySelection, input.catalog, input.workflowSurface)) {
        return input.primarySelection;
    }
    return (0, types_1.createAutoSelectWorkflowTemplateSelector)();
}
function selectorTargetsWorkflowSurface(selector, catalog, workflowSurface) {
    if (selector.mode !== "template") {
        return true;
    }
    const template = catalog.templateByPath.get(selector.templatePath);
    return (template !== undefined &&
        (0, template_registry_1.workflowTemplateTargetsSurface)(template, workflowSurface));
}
function shouldSelectActiveWorkflowTemplate(input) {
    if (input.appliedCommandState.selection.mode !== "auto" &&
        input.appliedCommandState.selection.mode !== "auto_select") {
        return false;
    }
    if (input.appliedCommandState.selection.mode === "auto_select" &&
        !(0, template_registry_1.hasAutoSelectableWorkflowTemplate)({
            catalog: input.catalog,
            workflowSurface: input.activeWorkflowSurface,
        })) {
        return false;
    }
    if (input.appliedCommandState.selectionSource === "implicit") {
        return ((0, template_registry_1.resolveImplicitWorkflowTemplateSelector)({
            catalog: input.catalog,
            workflowSurface: input.activeWorkflowSurface,
        }).mode === "auto_select");
    }
    if (input.appliedCommandState.selectionSource === "config") {
        return true;
    }
    if (input.command?.workflowSelection?.mode === "auto" ||
        input.command?.workflowSelection?.mode === "auto_select") {
        return true;
    }
    if (input.stickyState === null) {
        return true;
    }
    const binding = (0, template_bindings_1.getActiveWorkflowTemplateBinding)({
        workflowTemplates: input.stickyState.workflowTemplates,
        workflowSurface: input.activeWorkflowSurface,
    });
    return binding !== null && binding.resolution.kind !== "template";
}
function hasActiveSideWorkflowTemplateUpdate(appliedCommandState, workflowSurface) {
    return ((0, template_bindings_1.isSideWorkflowTemplateSurface)(workflowSurface) &&
        (0, command_apply_1.hasAppliedWorkflowTemplateSelectorUpdate)(appliedCommandState, workflowSurface));
}
function findLatestWorkflowUpdate(comments) {
    for (let index = comments.length - 1; index >= 0; index -= 1) {
        const comment = comments[index];
        if (comment === undefined) {
            continue;
        }
        const parsed = (0, workflow_update_1.parseWorkflowUpdate)(comment.body);
        if (parsed !== null) {
            return { parsed };
        }
    }
    return null;
}
