"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runWorkflowSetupPipeline = runWorkflowSetupPipeline;
exports.buildWorkerWorkflowOptionConfigSummary = buildWorkerWorkflowOptionConfigSummary;
exports.workflowOptionsFromWorkerAiWorkflowOptionAutofill = workflowOptionsFromWorkerAiWorkflowOptionAutofill;
exports.normalizeWorkflowSetupOptionDraft = normalizeWorkflowSetupOptionDraft;
const control_plane_config_1 = require("../config/control-plane-config");
const types_1 = require("../platform/ticket-tracker/types");
const types_2 = require("../platform/workflow-state/types");
const workflow_option_contract_support_1 = require("../worker/workflow-option-contract-support");
const workflow_selection_runtime_support_1 = require("../worker/workflow-selection-runtime-support");
const run_context_1 = require("./run-context");
const followup_policy_1 = require("./followup-policy");
const template_bindings_1 = require("./template-bindings");
const build_1 = require("./state/build");
const workflow_contract_1 = require("./workflow-contract");
const workflow_option_normalizer_1 = require("./workflow-option-normalizer");
const workflow_option_merge_1 = require("./workflow-option-merge");
async function runWorkflowSetupPipeline(input) {
    const comments = [...input.comments];
    const promptIssue = input.issue ??
        buildSyntheticIssue({
            title: input.title ?? "",
            body: input.issueBody,
            acceptedAt: input.acceptedAt,
        });
    const selection = await resolveSetupWorkflowSelection({
        ...input,
        issue: promptIssue,
        comments,
        explicitWorkflowOptions: input.explicitWorkflowOptions ?? null,
    });
    if (selection.kind === "handoff") {
        return selection;
    }
    const autofill = await resolveSetupWorkflowOptionAutofill({
        ...input,
        selectedWorkflowTemplate: selection.selectedWorkflowTemplate,
        workflowState: selection.workflowState,
    });
    if (autofill.kind === "deferred") {
        return autofill;
    }
    const workflowOptions = (0, workflow_option_merge_1.mergeWorkflowSetupOptions)({
        selection: selection.workflowOptions,
        autofill: autofill.workflowOptions,
        explicit: input.explicitWorkflowOptions ?? null,
    });
    if (workflowOptions === null) {
        return {
            kind: "unchanged",
            workflowOptions: null,
            workflowState: selection.workflowState,
            selectedWorkflowTemplate: selection.selectedWorkflowTemplate,
            workerDurationMs: autofill.workerDurationMs,
        };
    }
    return {
        kind: "updated",
        workflowOptions,
        workflowState: selection.workflowState,
        selectedWorkflowTemplate: selection.selectedWorkflowTemplate,
        workerDurationMs: autofill.workerDurationMs,
    };
}
async function resolveSetupWorkflowSelection(input) {
    const bootstrapWorkflowState = input.bootstrapWorkflowState;
    if (input.sourceKind === "fresh_comment") {
        return {
            kind: "resolved",
            workflowOptions: null,
            workflowState: bootstrapWorkflowState,
            selectedWorkflowTemplate: await resolveSelectedWorkflowTemplateFromState({
                ...input,
                workflowState: bootstrapWorkflowState,
            }),
        };
    }
    if (input.explicitWorkflowOptions?.workflowSelection !== undefined) {
        const explicitSelection = await resolveSelectedWorkflowTemplateFromExplicitWorkflowSelection({
            ...input,
            workflowSelection: input.explicitWorkflowOptions.workflowSelection,
        });
        if (explicitSelection.kind === "handoff") {
            return explicitSelection;
        }
        return {
            kind: "resolved",
            workflowOptions: null,
            workflowState: explicitSelection.workflowState,
            selectedWorkflowTemplate: explicitSelection.selectedWorkflowTemplate,
        };
    }
    const routingBootstrapWorkflowState = bootstrapWorkflowState ??
        buildSetupBootstrapWorkflowState({
            config: input.config,
            issue: input.issue,
            issueBody: input.issueBody,
            workflowSurface: input.workflowSurface ?? "issue",
        });
    const route = await (0, run_context_1.resolveWorkflowRunContext)(input.repoRoot, input.comments, input.responseLanguage, {
        maxNestedWorkflowDepth: input.config.maxNestedWorkflowDepth,
        workflowSurface: input.workflowSurface ?? "issue",
        bootstrapWorkflowState: routingBootstrapWorkflowState,
        issueBody: input.issueBody,
        baseBranchDefault: input.config.repositoryHost.baseBranch,
        workflowStartApprovalConfig: input.config,
        workflowStartApprovalTarget: input.issue.kind === types_1.TRACKER_ITEM_KINDS.pullRequest
            ? "pull_request"
            : "issue",
    });
    if (route.kind === "handoff") {
        if (bootstrapWorkflowState === null) {
            return {
                kind: "resolved",
                workflowOptions: null,
                workflowState: null,
                selectedWorkflowTemplate: null,
            };
        }
        return {
            kind: "handoff",
            summary: route.summary,
            workflowState: route.workflowState,
            selectedWorkflowTemplate: null,
            workerDurationMs: 0,
        };
    }
    if (route.kind !== "select") {
        return {
            kind: "resolved",
            workflowOptions: resolveSetupWorkflowOptionsForNonSelectRoute({
                sourceKind: input.sourceKind,
                route,
            }),
            workflowState: route.workflowState,
            selectedWorkflowTemplate: buildSelectedWorkflowTemplateContext({
                workflowTemplateName: route.workflowTemplateName,
                workflow: route.workflow,
            }),
        };
    }
    return {
        kind: "resolved",
        workflowOptions: input.sourceKind === "issue_create"
            ? {
                workflowSelection: resolveSetupWorkflowDefaultSelector({
                    config: input.config,
                    workflowSurface: input.workflowSurface ?? "issue",
                }),
            }
            : null,
        workflowState: route.workflowState,
        selectedWorkflowTemplate: null,
    };
}
function resolveSetupWorkflowOptionsForNonSelectRoute(input) {
    const activeBinding = (0, template_bindings_1.getActiveWorkflowTemplateBinding)(input.route.workflowState);
    if (activeBinding?.selector.mode === "no_template") {
        return { workflowSelection: activeBinding.selector };
    }
    if (input.route.workflowTemplateName !== null) {
        return {
            workflowSelection: (0, workflow_selection_runtime_support_1.toWorkflowTemplateSelector)(input.route.workflowTemplateName),
        };
    }
    if (input.sourceKind !== "issue_create") {
        return null;
    }
    const selector = activeBinding?.selector ?? { mode: "no_template" };
    return { workflowSelection: selector };
}
function resolveSetupWorkflowDefaultSelector(input) {
    return (0, template_bindings_1.isWorkflowTemplateBindingSurface)(input.workflowSurface)
        ? input.config.workflowTemplateDefaults[input.workflowSurface]
        : { mode: "no_template" };
}
function buildSetupBootstrapWorkflowState(input) {
    return (0, build_1.buildPersistedWorkflowState)({
        workflowSurface: input.workflowSurface,
        workflowTemplates: (0, template_bindings_1.createUnresolvedWorkflowTemplateBindings)(input.config.workflowTemplateDefaults),
        baseBranch: input.config.repositoryHost.baseBranch,
        priorityRank: null,
        executionContract: (0, workflow_contract_1.createDefaultWorkflowExecutionContract)(input.issue.title || input.issueBody || null),
        plan: null,
        followup: (0, followup_policy_1.resolveWorkflowFollowupState)({
            config: input.config.followup,
        }),
    });
}
async function resolveSetupWorkflowOptionAutofill(input) {
    if (input.config.aiWorkflowOptionAutofill === "off" ||
        input.sourceText.trim().length === 0) {
        return { kind: "resolved", workflowOptions: null, workerDurationMs: 0 };
    }
    const workerResult = await input.worker.runAiWorkflowOptionAutofill({
        prompt: input.sourceText,
        outputLanguage: input.responseLanguage,
        acceptedAt: input.acceptedAt,
        displayTimeZone: input.displayTimeZone,
        selectedWorkflowTemplate: input.selectedWorkflowTemplate,
        configSummary: buildWorkerWorkflowOptionConfigSummary(input.config),
        workspacePath: input.workspacePath,
        repositoryRoot: input.repoRoot,
    });
    if (workerResult.kind === "deferred") {
        return {
            kind: "deferred",
            reason: workerResult.reason,
            triedProfiles: workerResult.triedProfiles,
            cooldownUntil: workerResult.cooldownUntil,
            attemptedWorkerExecution: workerResult.attemptedWorkerExecution,
            workerDurationMs: workerResult.workerDurationMs,
        };
    }
    return {
        kind: "resolved",
        workflowOptions: suppressFollowupProposalAutofillWhenExplicitlyOff({
            workflowOptions: workflowOptionsFromWorkerAiWorkflowOptionAutofill(workerResult.launchResult.autofill.workflow),
            workflowState: input.workflowState,
        }),
        workerDurationMs: workerResult.workerDurationMs ?? 0,
    };
}
const FOLLOWUP_PROPOSAL_AUTOFILL_OVERRIDE_PATHS = new Set([
    "followup.proposalPolicy",
    "followup.proposalApproval",
]);
function suppressFollowupProposalAutofillWhenExplicitlyOff(input) {
    if (input.workflowOptions === null ||
        !hasExplicitFollowupProposalOffOverride(input.workflowState)) {
        return input.workflowOptions;
    }
    const patch = input.workflowOptions.configOverridePatch;
    if (patch === undefined) {
        return input.workflowOptions;
    }
    const entries = patch.entries.filter((entry) => !FOLLOWUP_PROPOSAL_AUTOFILL_OVERRIDE_PATHS.has(entry.path));
    if (entries.length === patch.entries.length) {
        return input.workflowOptions;
    }
    const workflowOptions = {
        ...input.workflowOptions,
    };
    if (entries.length > 0) {
        workflowOptions.configOverridePatch = { entries };
    }
    else {
        delete workflowOptions.configOverridePatch;
    }
    return Object.keys(workflowOptions).length === 0 ? null : workflowOptions;
}
function hasExplicitFollowupProposalOffOverride(workflowState) {
    const entries = workflowState?.configOverrides?.entries;
    if (entries === undefined) {
        return false;
    }
    for (let index = entries.length - 1; index >= 0; index -= 1) {
        const entry = entries[index];
        if (entry === undefined) {
            continue;
        }
        if (entry.path !== "followup.proposalPolicy") {
            continue;
        }
        return entry.op === "set" && entry.value === "off";
    }
    return false;
}
async function resolveSelectedWorkflowTemplateFromState(input) {
    const workflowState = input.workflowState;
    if (workflowState === null) {
        return null;
    }
    const templateName = (0, template_bindings_1.getWorkflowTemplateName)((0, template_bindings_1.getActiveWorkflowTemplateBinding)(workflowState));
    if (templateName === null) {
        return null;
    }
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, workflowState);
    const planningContext = await (0, run_context_1.resolveWorkflowPlanningContextForSelection)({
        repoRoot: input.repoRoot,
        workflowState,
        templateName,
        locale: input.responseLanguage,
        maxNestedWorkflowDepth: input.config.maxNestedWorkflowDepth,
        planningIntent: "new_plan",
        workflowSurface: workflowState.workflowSurface,
        issueNotesPath: effectiveConfig.paths.issueNotes,
        workflowStartApprovalMode: resolveWorkflowSetupStartApprovalMode({
            config: effectiveConfig,
            issue: input.issue,
            workflowState,
            planningIntent: "new_plan",
        }),
    });
    return planningContext.kind === "plan"
        ? buildSelectedWorkflowTemplateContext({
            workflowTemplateName: planningContext.workflowTemplateName,
            workflow: planningContext.workflow,
        })
        : { templatePath: templateName };
}
async function resolveSelectedWorkflowTemplateFromExplicitWorkflowSelection(input) {
    const workflowSurface = input.bootstrapWorkflowState?.workflowSurface ??
        input.workflowSurface ??
        "issue";
    const templateName = input.workflowSelection.mode === "template"
        ? input.workflowSelection.templatePath
        : null;
    const workflowTemplateSelectors = (0, template_bindings_1.createWorkflowTemplateSelectorMap)({
        workflowTemplates: input.bootstrapWorkflowState?.workflowTemplates,
        defaultSelectors: input.config.workflowTemplateDefaults,
        selectors: (0, template_bindings_1.isWorkflowTemplateBindingSurface)(workflowSurface)
            ? { [workflowSurface]: input.workflowSelection }
            : {},
    });
    const workflowState = input.bootstrapWorkflowState === null
        ? (0, build_1.buildPersistedWorkflowState)({
            workflowSurface,
            workflowTemplates: (0, template_bindings_1.createUnresolvedWorkflowTemplateBindings)(workflowTemplateSelectors),
            baseBranch: input.config.repositoryHost.baseBranch,
            priorityRank: null,
            executionContract: (0, workflow_contract_1.createDefaultWorkflowExecutionContract)(),
            plan: null,
            followup: (0, followup_policy_1.resolveWorkflowFollowupState)({
                config: input.config.followup,
            }),
        })
        : {
            ...input.bootstrapWorkflowState,
            workflowSurface,
            workflowTemplates: (0, template_bindings_1.createUnresolvedWorkflowTemplateBindings)(workflowTemplateSelectors),
        };
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(input.config, workflowState);
    const planningContext = await (0, run_context_1.resolveWorkflowPlanningContextForSelection)({
        repoRoot: input.repoRoot,
        workflowState,
        templateName,
        locale: input.responseLanguage,
        maxNestedWorkflowDepth: input.config.maxNestedWorkflowDepth,
        planningIntent: "new_plan",
        workflowSurface,
        issueNotesPath: effectiveConfig.paths.issueNotes,
        workflowStartApprovalMode: resolveWorkflowSetupStartApprovalMode({
            config: effectiveConfig,
            issue: input.issue,
            workflowState,
            planningIntent: "new_plan",
        }),
    });
    if (planningContext.kind === "handoff") {
        return {
            kind: "handoff",
            summary: planningContext.summary,
            workflowState: planningContext.workflowState,
            selectedWorkflowTemplate: null,
            workerDurationMs: 0,
        };
    }
    return {
        kind: "resolved",
        workflowState: planningContext.workflowState,
        selectedWorkflowTemplate: buildSelectedWorkflowTemplateContext({
            workflowTemplateName: planningContext.workflowTemplateName,
            workflow: planningContext.workflow,
        }),
    };
}
function resolveWorkflowSetupStartApprovalMode(input) {
    const startApprovalIntent = input.workflowState.pendingWorkflowStartApprovalIntent;
    return (0, control_plane_config_1.resolveWorkflowStartApprovalModeForPlanningIntent)({
        target: input.issue.kind === types_1.TRACKER_ITEM_KINDS.pullRequest
            ? "pull_request"
            : "issue",
        planningIntent: input.planningIntent,
        ...(startApprovalIntent === undefined ? {} : { startApprovalIntent }),
        config: input.config,
    });
}
function buildSelectedWorkflowTemplateContext(input) {
    if (input.workflowTemplateName === null) {
        return null;
    }
    return {
        templatePath: input.workflowTemplateName,
        workflowSurface: input.workflow.workflowSurface ?? "issue",
        templateBody: input.workflow.templateBody ?? null,
        requiredSkills: input.workflow.requiredSkills ?? [],
        requiredMcp: input.workflow.requiredMcp ?? [],
    };
}
function buildWorkerWorkflowOptionConfigSummary(config) {
    return {
        issueCompletion: config.issueCompletion,
        baseBranch: config.repositoryHost.baseBranch,
        aiRunLimits: {
            maxRuns: config.aiRunLimits.maxRuns,
            maxHours: config.aiRunLimits.maxHours,
        },
        recurring: {
            maxActiveChildren: config.recurring.maxActiveChildren,
        },
        followup: {
            proposalPolicy: config.followup.proposalPolicy,
            proposalApproval: config.followup.proposalApproval,
            maxIssuesPerSource: config.followup.maxIssuesPerSource,
        },
        defaultReviewers: config.repositoryHost.pullRequest?.defaultReviewers ?? [],
        foreignIssueApprovalScope: config.foreignIssueApprovalScope,
        workflowStart: {
            newPlan: config.approvals.workflowStart.newPlan,
            replan: config.approvals.workflowStart.replan,
            scope: config.approvals.workflowStart.scope,
        },
    };
}
function workflowOptionsFromWorkerAiWorkflowOptionAutofill(workflow) {
    if (workflow === null) {
        return null;
    }
    const configOverridePatch = (0, workflow_option_contract_support_1.buildWorkerWorkflowConfigOverridePatch)(workflow.overrides);
    const baseBranch = buildWorkerWorkflowBaseBranchCommand(workflow.overrides);
    const normalized = (0, workflow_option_normalizer_1.normalizeWorkflowCommandUpdateDraftFields)(buildWorkflowSetupOptionDraft({
        schedule: workflow.schedule,
        scheduledRun: workflow.scheduledRun,
        firstRun: workflow.firstRun,
        recurringAutoStop: workflow.recurringAutoStop,
        baseBranch,
        configOverridePatch,
    }));
    if (normalized.kind === "invalid" &&
        normalized.reason === "missing-options") {
        return null;
    }
    if (normalized.kind !== "update") {
        throw new Error(`Invalid worker workflow options: ${normalized.reason}`);
    }
    const fields = { ...normalized.fields };
    // Command normalization may infer side workflow selectors for explicit
    // command ergonomics. Autofill can only update non-template options.
    delete fields.workflowTemplateSelectors;
    return Object.keys(fields).length === 0 ? null : fields;
}
function normalizeWorkflowSetupOptionDraft(input) {
    return (0, workflow_option_normalizer_1.normalizeWorkflowCommandUpdateDraftFields)(buildWorkflowSetupOptionDraft(input));
}
function buildWorkerWorkflowBaseBranchCommand(overrides) {
    if (overrides === undefined || overrides === null) {
        return undefined;
    }
    if (!Object.hasOwn(overrides, "baseBranch")) {
        return undefined;
    }
    if (overrides.baseBranch === undefined || overrides.baseBranch === null) {
        return undefined;
    }
    return { mode: "set", branch: overrides.baseBranch };
}
function buildWorkflowSetupOptionDraft(input) {
    return (0, workflow_option_normalizer_1.compactWorkflowCommandUpdateFields)(input);
}
function buildSyntheticIssue(input) {
    return {
        id: "draft",
        displayId: "draft",
        title: input.title,
        baseTitle: input.title,
        body: input.body,
        url: "",
        author: null,
        kind: types_1.TRACKER_ITEM_KINDS.issue,
        assignees: [],
        isOpen: true,
        updatedAt: input.acceptedAt,
        workflowState: {
            status: types_2.WORKFLOW_STATUSES.aiReady,
            rules: [],
        },
    };
}
