"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyWorkflowCommandToStickyState = applyWorkflowCommandToStickyState;
exports.getAppliedWorkflowTemplateSelector = getAppliedWorkflowTemplateSelector;
exports.hasAppliedWorkflowTemplateSelectorUpdate = hasAppliedWorkflowTemplateSelectorUpdate;
exports.applyAppliedWorkflowCommandToPersistedState = applyAppliedWorkflowCommandToPersistedState;
exports.mergeConfigOverridePatch = mergeConfigOverridePatch;
exports.mergeConfigOverridePatchEntries = mergeConfigOverridePatchEntries;
const optional_text_1 = require("./optional-text");
const template_bindings_1 = require("./template-bindings");
const types_1 = require("./types");
const workflow_selection_support_1 = require("./workflow-selection-support");
function applyWorkflowCommandToStickyState(input) {
    const baseBranch = resolveAppliedBaseBranch({
        stickyBaseBranch: input.stickyState?.baseBranch,
        command: input.command?.baseBranch,
        baseBranchDefault: input.baseBranchDefault ?? "main",
    });
    const updatedWorkflowTemplateSurfaces = getUpdatedWorkflowTemplateSurfaces(input.command);
    const workflowTemplateSelectors = (0, template_bindings_1.buildSideWorkflowTemplateSelectors)({
        workflowTemplates: input.stickyState?.workflowTemplates,
        selectorUpdates: input.command?.workflowTemplateSelectors,
        selectorDefaults: input.workflowTemplateDefaults,
    });
    const activeSurface = input.stickyState?.workflowSurface ?? input.workflowSurface ?? "issue";
    const activeBinding = input.stickyState === null
        ? undefined
        : (0, template_bindings_1.getActiveWorkflowTemplateBinding)({
            workflowTemplates: input.stickyState.workflowTemplates,
            workflowSurface: activeSurface,
        });
    const selection = input.command?.workflowSelection ??
        activeBinding?.selector ??
        ((0, template_bindings_1.isWorkflowTemplateBindingSurface)(activeSurface)
            ? input.workflowTemplateDefaults?.[activeSurface]
            : undefined) ??
        (0, types_1.createAutoSelectWorkflowTemplateSelector)();
    const selectionSource = input.command?.workflowSelection !== undefined
        ? "command"
        : activeBinding !== undefined
            ? "sticky"
            : (0, template_bindings_1.isWorkflowTemplateBindingSurface)(activeSurface) &&
                input.workflowTemplateDefaults?.[activeSurface] !== undefined
                ? "config"
                : "implicit";
    const schedule = input.command?.scheduledRun !== undefined &&
        input.command.scheduledRun.mode !== "off"
        ? (0, types_1.createOffWorkflowScheduleState)()
        : (input.command?.schedule ??
            input.stickyState?.schedule ??
            (0, types_1.createOffWorkflowScheduleState)());
    const commandContext = (0, optional_text_1.normalizeOptionalText)(input.command?.bodyAfterCommand ?? null);
    return {
        selection,
        selectionSource,
        workflowTemplateSelectors,
        updatedWorkflowTemplateSurfaces,
        schedule,
        baseBranch,
        configOverrides: mergeConfigOverridePatch(input.stickyState?.configOverrides, input.command?.configOverridePatch),
        ...(input.command?.recurringAutoStop !== undefined
            ? { recurringAutoStop: input.command.recurringAutoStop }
            : {}),
        ...(input.command?.schedule !== undefined ||
            input.command?.scheduledRun !== undefined
            ? { didUpdateSchedule: true }
            : {}),
        ...(input.command?.recurringAutoStop !== undefined
            ? { didUpdateRecurringAutoStop: true }
            : {}),
        shouldReplan: input.command?.workflowSelection !== undefined || commandContext !== null,
        commandContext,
    };
}
function getAppliedWorkflowTemplateSelector(applied, surface) {
    if (!isConfigurableSideWorkflowSurface(surface)) {
        return undefined;
    }
    return applied.workflowTemplateSelectors[surface];
}
function hasAppliedWorkflowTemplateSelectorUpdate(applied, surface) {
    if (!isConfigurableSideWorkflowSurface(surface)) {
        return false;
    }
    return applied.updatedWorkflowTemplateSurfaces.includes(surface);
}
function applyAppliedWorkflowCommandToPersistedState(stickyState, applied) {
    const activeSurface = stickyState.workflowSurface;
    let workflowTemplates = stickyState.workflowTemplates;
    if ((0, template_bindings_1.isWorkflowTemplateBindingSurface)(activeSurface)) {
        const currentActiveBinding = (0, template_bindings_1.getWorkflowTemplateBinding)({
            workflowTemplates: stickyState.workflowTemplates,
            surface: activeSurface,
        });
        workflowTemplates = (0, template_bindings_1.setWorkflowTemplateBinding)({
            workflowTemplates,
            surface: activeSurface,
            binding: (0, workflow_selection_support_1.areWorkflowSelectionsEqual)(applied.selection, currentActiveBinding.selector)
                ? (0, template_bindings_1.createWorkflowTemplateBinding)({
                    selector: applied.selection,
                    resolution: currentActiveBinding.resolution,
                })
                : (0, template_bindings_1.createWorkflowTemplateBinding)({
                    selector: applied.selection,
                }),
        });
    }
    for (const surface of template_bindings_1.SIDE_WORKFLOW_TEMPLATE_SURFACES) {
        workflowTemplates = applySideWorkflowTemplateUpdate({
            workflowTemplates,
            surface,
            didUpdate: hasAppliedWorkflowTemplateSelectorUpdate(applied, surface),
            selector: getAppliedWorkflowTemplateSelector(applied, surface),
        });
    }
    const nextState = {
        ...stickyState,
        workflowTemplates,
        schedule: applied.schedule,
        baseBranch: applied.baseBranch,
    };
    if (applied.didUpdateSchedule) {
        delete nextState.scheduledRun;
        if (applied.schedule.mode === "off") {
            delete nextState.recurring;
            nextState.nextRunAt = null;
        }
        else {
            nextState.recurring = stickyState.recurring ?? { kind: "parent" };
        }
    }
    if (applied.didUpdateRecurringAutoStop) {
        if (applied.recurringAutoStop?.mode === "off") {
            if (nextState.recurring === undefined) {
                delete nextState.recurring;
            }
            else {
                nextState.recurring = { kind: "parent" };
            }
        }
        else if (nextState.recurring === undefined) {
            nextState.recurring = { kind: "parent" };
        }
    }
    if (applied.configOverrides === undefined) {
        delete nextState.configOverrides;
    }
    else {
        nextState.configOverrides = applied.configOverrides;
    }
    return nextState;
}
function resolveAppliedBaseBranch(input) {
    if (input.command?.mode === "set") {
        return input.command.branch;
    }
    if (input.command?.mode === "default") {
        return input.baseBranchDefault;
    }
    return input.stickyBaseBranch ?? input.baseBranchDefault;
}
function getUpdatedWorkflowTemplateSurfaces(command) {
    return (0, template_bindings_1.getSideWorkflowTemplateSelectorSurfaces)(command?.workflowTemplateSelectors);
}
function applySideWorkflowTemplateUpdate(input) {
    if (!input.didUpdate) {
        return input.workflowTemplates;
    }
    return (0, template_bindings_1.setWorkflowTemplateBinding)({
        workflowTemplates: input.workflowTemplates,
        surface: input.surface,
        binding: (0, template_bindings_1.createWorkflowTemplateBinding)({
            selector: (0, template_bindings_1.normalizePersistedSideWorkflowTemplateSelector)(input.selector),
        }),
    });
}
function isConfigurableSideWorkflowSurface(surface) {
    return template_bindings_1.SIDE_WORKFLOW_TEMPLATE_SURFACES.includes(surface);
}
function mergeConfigOverridePatch(stickyPatch, commandPatch) {
    if (commandPatch === undefined) {
        return stickyPatch;
    }
    const mergedEntries = mergeConfigOverridePatchEntries(stickyPatch?.entries, commandPatch.entries, { keepInheritEntries: false });
    if (mergedEntries.length === 0) {
        return undefined;
    }
    return {
        entries: mergedEntries,
    };
}
function mergeConfigOverridePatchEntries(previousEntries, nextEntries, options) {
    const mergedEntries = [...(previousEntries ?? [])];
    for (const entry of nextEntries) {
        removeOverrideEntryAtPath(mergedEntries, entry.path);
        if (entry.op === "disable" || entry.op === "inherit") {
            removeDescendantOverrideEntries(mergedEntries, entry.path);
        }
        if (entry.op !== "inherit" || options.keepInheritEntries) {
            mergedEntries.push(entry);
        }
    }
    return mergedEntries;
}
function removeOverrideEntryAtPath(entries, path) {
    const index = entries.findIndex((entry) => entry.path === path);
    if (index !== -1) {
        entries.splice(index, 1);
    }
}
function removeDescendantOverrideEntries(entries, parentPath) {
    for (let index = entries.length - 1; index >= 0; index -= 1) {
        const entry = entries[index];
        if (entry !== undefined && isDescendantPath(entry.path, parentPath)) {
            entries.splice(index, 1);
        }
    }
}
function isDescendantPath(path, parentPath) {
    return path.startsWith(`${parentPath}.`);
}
