"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ISSUE_CREATE_DRAFT_SCHEMA_VERSION = exports.ISSUE_CREATE_DRAFT_KIND = void 0;
exports.resolveIssueCreateAssignees = resolveIssueCreateAssignees;
exports.resolveIssueCreateDraft = resolveIssueCreateDraft;
exports.buildIssueCreateInitialWorkflowState = buildIssueCreateInitialWorkflowState;
exports.buildIssueCreateWorkflowLabelNames = buildIssueCreateWorkflowLabelNames;
exports.buildIssueCreateLabelNames = buildIssueCreateLabelNames;
exports.stripManagedIssueCreateLabelNames = stripManagedIssueCreateLabelNames;
exports.buildIssueCreateWorkflowProjection = buildIssueCreateWorkflowProjection;
exports.buildIssueCreateWorkflowState = buildIssueCreateWorkflowState;
exports.renderIssueCreateSummary = renderIssueCreateSummary;
exports.renderIssueCreatePlanLine = renderIssueCreatePlanLine;
exports.resolveIssueCreateWorkflowLabel = resolveIssueCreateWorkflowLabel;
exports.buildIssueCreateDraftFile = buildIssueCreateDraftFile;
exports.stringifyIssueCreateDraftFile = stringifyIssueCreateDraftFile;
exports.parseIssueCreateDraftFile = parseIssueCreateDraftFile;
exports.assertIssueCreateDraftMatchesTracker = assertIssueCreateDraftMatchesTracker;
// biome-ignore lint/nursery/noExcessiveLinesPerFile: Issue create helpers stay grouped around one command contract and draft JSON schema.
const node_fs_1 = require("node:fs");
const promises_1 = require("node:fs/promises");
const zod_1 = require("zod");
const control_plane_config_1 = require("../config/control-plane-config");
const provider_kinds_1 = require("../core/provider-kinds");
const catalog_1 = require("../i18n/catalog");
const issue_template_discovery_1 = require("../issues/issue-template-discovery");
const workflow_labels_1 = require("../platform/ticket-tracker/workflow-labels");
const types_1 = require("../platform/workflow-state/types");
const runtime_1 = require("../worker/runtime");
const comment_command_1 = require("../workflows/comment-command");
const display_labels_1 = require("../workflows/display-labels");
const config_override_validation_1 = require("../workflows/config-override-validation");
const recurring_1 = require("../workflows/recurring");
const followup_policy_1 = require("../workflows/followup-policy");
const recurring_auto_stop_1 = require("../workflows/recurring-auto-stop");
const scheduled_run_1 = require("../workflows/scheduled-run");
const state_1 = require("../workflows/state");
const template_bindings_1 = require("../workflows/template-bindings");
const template_registry_1 = require("../workflows/template-registry");
const types_2 = require("../workflows/types");
const validation_1 = require("../workflows/validation");
const workflow_template_selection_validation_1 = require("../workflows/workflow-template-selection-validation");
const setup_pipeline_1 = require("../workflows/setup-pipeline");
const draft_file_support_1 = require("./draft-file-support");
exports.ISSUE_CREATE_DRAFT_KIND = "alpaca.issueCreateDraft";
exports.ISSUE_CREATE_DRAFT_SCHEMA_VERSION = 2;
const issueCreateDraftJsonValueSchema = zod_1.z.lazy(() => zod_1.z.union([
    zod_1.z.string(),
    zod_1.z.number(),
    zod_1.z.boolean(),
    zod_1.z.null(),
    zod_1.z.array(issueCreateDraftJsonValueSchema),
    zod_1.z.record(zod_1.z.string(), issueCreateDraftJsonValueSchema),
]));
const workflowTemplateSelectorSchema = zod_1.z.discriminatedUnion("mode", [
    zod_1.z.object({ mode: zod_1.z.literal("auto") }).strict(),
    zod_1.z.object({ mode: zod_1.z.literal("auto_select") }).strict(),
    zod_1.z.object({ mode: zod_1.z.literal("no_template") }).strict(),
    zod_1.z
        .object({
        mode: zod_1.z.literal("template"),
        templatePath: zod_1.z.string().min(1),
    })
        .strict(),
]);
const workflowScheduleStateSchema = zod_1.z.discriminatedUnion("mode", [
    zod_1.z
        .object({
        mode: zod_1.z.literal("off"),
        value: zod_1.z.null(),
    })
        .strict(),
    zod_1.z
        .object({
        mode: zod_1.z.enum(["every", "cron"]),
        value: zod_1.z.string().min(1),
    })
        .strict(),
]);
const workflowScheduledRunCommandSchema = zod_1.z.discriminatedUnion("mode", [
    zod_1.z
        .object({
        mode: zod_1.z.enum(["run_at", "run_after"]),
        value: zod_1.z.string().min(1),
    })
        .strict(),
    zod_1.z
        .object({
        mode: zod_1.z.literal("off"),
        value: zod_1.z.null(),
    })
        .strict(),
]);
const workflowFirstRunCommandSchema = zod_1.z.discriminatedUnion("mode", [
    zod_1.z
        .object({
        mode: zod_1.z.enum(["run_at", "run_after"]),
        value: zod_1.z.string().min(1),
    })
        .strict(),
    zod_1.z
        .object({
        mode: zod_1.z.literal("now"),
        value: zod_1.z.null(),
    })
        .strict(),
]);
const workflowRecurringAutoStopCommandSchema = zod_1.z.discriminatedUnion("mode", [
    zod_1.z
        .object({
        mode: zod_1.z.literal("off"),
    })
        .strict(),
    zod_1.z
        .object({
        mode: zod_1.z.literal("update"),
        stopAt: zod_1.z.string().min(1).optional(),
        stopAfter: zod_1.z.string().min(1).optional(),
        stopAfterRuns: zod_1.z.number().int().positive().optional(),
    })
        .strict(),
]);
const workflowBaseBranchCommandSchema = zod_1.z.discriminatedUnion("mode", [
    zod_1.z
        .object({
        mode: zod_1.z.literal("set"),
        branch: zod_1.z.string().min(1),
    })
        .strict(),
    zod_1.z
        .object({
        mode: zod_1.z.literal("default"),
    })
        .strict(),
]);
const configOverrideEntrySchema = zod_1.z.discriminatedUnion("op", [
    zod_1.z
        .object({
        path: zod_1.z.string().min(1),
        op: zod_1.z.literal("set"),
        value: issueCreateDraftJsonValueSchema,
    })
        .strict(),
    zod_1.z
        .object({
        path: zod_1.z.string().min(1),
        op: zod_1.z.literal("inherit"),
    })
        .strict(),
    zod_1.z
        .object({
        path: zod_1.z.string().min(1),
        op: zod_1.z.literal("disable"),
    })
        .strict(),
]);
const issueCreateWorkflowOptionsSchema = zod_1.z
    .object({
    workflowSelection: workflowTemplateSelectorSchema.optional(),
    workflowTemplateSelectors: zod_1.z
        .object({
        // biome-ignore lint/style/useNamingConvention: Persisted workflow surface key is snake_case by contract.
        pull_request: workflowTemplateSelectorSchema.optional(),
        unplanned: workflowTemplateSelectorSchema.optional(),
    })
        .strict()
        .optional(),
    schedule: workflowScheduleStateSchema.optional(),
    scheduledRun: workflowScheduledRunCommandSchema.optional(),
    firstRun: workflowFirstRunCommandSchema.optional(),
    recurringAutoStop: workflowRecurringAutoStopCommandSchema.optional(),
    baseBranch: workflowBaseBranchCommandSchema.optional(),
    configOverridePatch: zod_1.z
        .object({
        entries: zod_1.z.array(configOverrideEntrySchema),
    })
        .strict()
        .optional(),
})
    .strict();
const issueCreateDraftFileSchema = zod_1.z
    .object({
    kind: zod_1.z.literal(exports.ISSUE_CREATE_DRAFT_KIND),
    schemaVersion: zod_1.z.literal(exports.ISSUE_CREATE_DRAFT_SCHEMA_VERSION),
    preparedAt: zod_1.z.string().min(1),
    tracker: zod_1.z
        .object({
        kind: zod_1.z.enum(provider_kinds_1.TICKET_TRACKER_KIND_VALUES),
        projectRef: zod_1.z.string().min(1),
    })
        .strict(),
    sourcePrompt: zod_1.z.string().nullable().optional(),
    title: zod_1.z.string().min(1).max(180),
    body: zod_1.z.string().min(1),
    selectedIssueTemplatePath: zod_1.z.string().nullable().optional(),
    workflowOptions: issueCreateWorkflowOptionsSchema.optional(),
    assignees: zod_1.z.array(zod_1.z.string()),
    labels: zod_1.z.array(zod_1.z.string()),
    milestoneRef: zod_1.z.string().optional(),
    projectRef: zod_1.z.string().optional(),
    disabled: zod_1.z.boolean(),
})
    .strict();
async function resolveIssueCreateAssignees(ticketTracker, assignees) {
    const dedupedAssignees = dedupeTextValues(assignees);
    if (dedupedAssignees.length > 0) {
        return dedupedAssignees;
    }
    return [await ticketTracker.getAuthenticatedUserLogin()];
}
async function resolveIssueCreateDraft(cwd, clients, options, acceptedAt = new Date().toISOString()) {
    if (options.mode === "manual") {
        const body = await loadIssueCreateBody(options.body);
        validateIssueCreateTitleAndBody(options.title, body, clients.locale);
        return {
            title: options.title,
            body,
            ...(options.workflowOptions !== undefined
                ? { workflowOptions: options.workflowOptions }
                : {}),
        };
    }
    if ((0, control_plane_config_1.resolveWorkersForPurpose)(clients.config, "thinking").length === 0) {
        throw new Error((0, catalog_1.translate)(clients.locale, "issue.command.create.noWorker"));
    }
    const workerRuntime = await (0, runtime_1.createConfiguredWorkerRuntime)(clients.config);
    const issueTemplateCandidates = await loadIssueDraftIssueTemplateCandidates(cwd, clients.config.ticketTracker.kind);
    const outputLanguage = clients.config.i18n.defaultLanguage;
    const draftResult = await workerRuntime.runIssueDraft({
        prompt: options.prompt,
        outputLanguage,
        acceptedAt,
        displayTimeZone: clients.config.i18n.displayTimeZone,
        availableIssueTemplates: issueTemplateCandidates,
        workspacePath: cwd,
        repositoryRoot: cwd,
    });
    if (draftResult.kind === "deferred") {
        throw new Error((0, catalog_1.translate)(clients.locale, "issue.command.create.workerDeferred", {
            cooldownUntil: draftResult.cooldownUntil ?? "-",
        }));
    }
    const launchResult = draftResult.launchResult;
    validateIssueCreateTitleAndBody(launchResult.draft.title, launchResult.draft.body, clients.locale);
    const workflowOptions = await resolveIssueCreatePromptWorkflowOptions({
        cwd,
        clients,
        workerRuntime,
        title: launchResult.draft.title,
        body: launchResult.draft.body,
        acceptedAt,
        outputLanguage,
        ...(options.workflowOptions !== undefined
            ? { explicitWorkflowOptions: options.workflowOptions }
            : {}),
    });
    return {
        title: launchResult.draft.title,
        body: launchResult.draft.body,
        selectedIssueTemplatePath: launchResult.draft.selectedIssueTemplatePath ?? null,
        sourcePrompt: options.prompt,
        ...(workflowOptions !== undefined ? { workflowOptions } : {}),
    };
}
async function resolveIssueCreatePromptWorkflowOptions(input) {
    const setup = await (0, setup_pipeline_1.runWorkflowSetupPipeline)({
        repoRoot: input.cwd,
        workspacePath: input.cwd,
        config: input.clients.config,
        worker: input.workerRuntime,
        title: input.title,
        issueBody: input.body,
        comments: [],
        bootstrapWorkflowState: null,
        sourceKind: "issue_create",
        sourceText: input.body,
        acceptedAt: input.acceptedAt,
        displayTimeZone: input.clients.config.i18n.displayTimeZone,
        responseLanguage: input.outputLanguage,
        ...(input.explicitWorkflowOptions !== undefined
            ? { explicitWorkflowOptions: input.explicitWorkflowOptions }
            : {}),
    });
    if (setup.kind === "deferred") {
        throw new Error((0, catalog_1.translate)(input.clients.locale, "issue.command.create.workerDeferred", {
            cooldownUntil: setup.cooldownUntil ?? "-",
        }));
    }
    if (setup.kind === "handoff") {
        throw new Error(setup.summary);
    }
    return setup.kind === "updated" ? setup.workflowOptions : undefined;
}
function buildIssueCreateInitialWorkflowState(options) {
    return {
        status: types_1.WORKFLOW_STATUSES.aiReady,
        rules: options.disabled ? [types_1.WORKFLOW_RULES.aiDisabled] : [],
    };
}
function buildIssueCreateWorkflowLabelNames(workflowLabels, projection) {
    const input = {
        workflowLabels,
        currentLabelNames: [],
        next: projection.next,
    };
    if (projection.labelProjection !== undefined) {
        input.labelProjection = projection.labelProjection;
    }
    if (projection.auxiliaryManagedLabels !== undefined) {
        input.auxiliaryManagedLabels = projection.auxiliaryManagedLabels;
    }
    return (0, workflow_labels_1.resolveWorkflowStateSyncLabelNames)(input);
}
function buildIssueCreateLabelNames(workflowLabels, baseLabelNames, projection) {
    const input = {
        workflowLabels,
        currentLabelNames: stripManagedIssueCreateLabelNames(baseLabelNames, workflowLabels),
        next: projection.next,
    };
    if (projection.labelProjection !== undefined) {
        input.labelProjection = projection.labelProjection;
    }
    if (projection.auxiliaryManagedLabels !== undefined) {
        input.auxiliaryManagedLabels = projection.auxiliaryManagedLabels;
    }
    return (0, workflow_labels_1.resolveWorkflowStateSyncLabelNames)(input);
}
function stripManagedIssueCreateLabelNames(labelNames, workflowLabels) {
    const managedLabelNames = new Set([
        ...(0, workflow_labels_1.getNonFollowupManagedLabelNames)(workflow_labels_1.DEFAULT_WORKFLOW_LABELS),
        (0, workflow_labels_1.getFollowupRequestLabelName)(workflow_labels_1.DEFAULT_WORKFLOW_LABELS),
        ...(0, workflow_labels_1.getNonFollowupManagedLabelNames)(workflowLabels),
        (0, workflow_labels_1.getFollowupRequestLabelName)(workflowLabels),
    ]);
    return dedupeTextValues(labelNames.filter((labelName) => !managedLabelNames.has(labelName)));
}
function buildIssueCreateWorkflowProjection(workflowLabels, snapshot, workflowState, disabled) {
    const recurringProjection = (0, recurring_1.resolveRecurringProjection)({
        snapshot,
        workflowState,
    });
    const scheduledProjection = (0, scheduled_run_1.resolveScheduledRunProjection)({
        snapshot: recurringProjection.snapshot,
        workflowState,
    });
    const isRecurring = (0, recurring_1.isRecurringParentWorkflowState)(workflowState);
    return {
        previous: snapshot,
        next: scheduledProjection.snapshot,
        ...(!isRecurring && workflowState?.scheduledRun === undefined && disabled
            ? { labelProjection: { omitReadyStatusLabel: true } }
            : {}),
        auxiliaryManagedLabels: {
            previous: [],
            next: (0, recurring_1.resolveRecurringLabelNames)(workflowLabels.aiRecurring, workflowState),
        },
    };
}
async function buildIssueCreateWorkflowState(cwd, clients, workflowOptions, acceptedAt = new Date().toISOString()) {
    if (workflowOptions === undefined) {
        return null;
    }
    validateIssueCreateWorkerOverride(workflowOptions, clients);
    const catalog = await (0, template_registry_1.loadWorkflowTemplates)((0, template_registry_1.getWorkflowTemplatesDirectoryPath)(cwd), clients.locale);
    const workflowSelection = workflowOptions.workflowSelection ?? null;
    const resolution = (0, template_registry_1.resolveWorkflowTemplateBindingSelection)({
        catalog,
        ...(workflowSelection?.mode === "template"
            ? {}
            : { workflowSurface: "issue" }),
        stickySelection: workflowSelection,
        defaultSelection: clients.config.workflowTemplateDefaults.issue,
        command: null,
    }, clients.locale);
    if (resolution.kind !== "resolved") {
        if (resolution.kind === "missing-template") {
            throw new Error((0, catalog_1.translate)(clients.locale, "workflow.runContext.missingTemplate", {
                templatePath: resolution.missingTemplatePath,
            }));
        }
        throw new Error((0, catalog_1.translate)(clients.locale, "workflow.runContext.catalogInvalid"));
    }
    const baseBranch = resolveIssueCreateBaseBranch(workflowOptions, clients.config);
    const effectiveConfigWorkflowStateInput = {
        baseBranch,
        ...(workflowOptions.configOverridePatch !== undefined
            ? { configOverrides: workflowOptions.configOverridePatch }
            : {}),
    };
    const effectiveConfig = (0, control_plane_config_1.resolveIssueEffectiveConfigForWorkflowState)(clients.config, effectiveConfigWorkflowStateInput);
    const workflowTemplateSelectors = (0, template_bindings_1.addWorkflowTemplateSelectors)({
        selectors: (0, template_bindings_1.createWorkflowTemplateSelectorMap)({
            defaultSelectors: (0, control_plane_config_1.resolveWorkflowTemplateDefaultsWithFollowup)(effectiveConfig),
            selectors: {
                issue: resolution.binding.selector,
            },
        }),
        updates: {
            ...workflowOptions.workflowTemplateSelectors,
        },
    });
    validateIssueCreateWorkflowTemplateSelection(catalog, resolution.template, workflowTemplateSelectors, effectiveConfig.followup.preferredWorkflowTemplates, clients.locale, effectiveConfig.maxNestedWorkflowDepth);
    const workflowTemplates = (0, template_bindings_1.resolveWorkflowTemplateBindings)({
        catalog,
        selectors: workflowTemplateSelectors,
    });
    const scheduledRun = resolveIssueCreateScheduledRun(workflowOptions, acceptedAt, clients);
    const recurring = resolveIssueCreateRecurringState(workflowOptions, workflowTemplates, acceptedAt, clients);
    const followup = (0, followup_policy_1.resolveWorkflowFollowupState)({
        config: effectiveConfig.followup,
    });
    return (0, state_1.buildPersistedWorkflowState)({
        workflowSurface: "issue",
        workflowTemplates,
        baseBranch,
        priorityRank: null,
        ...(workflowOptions.schedule !== undefined
            ? {
                schedule: workflowOptions.schedule,
                ...(workflowOptions.schedule.mode !== "off"
                    ? { recurring: recurring ?? { kind: "parent" } }
                    : {}),
                nextRunAt: resolveIssueCreateNextRunAt(workflowOptions.schedule, workflowOptions.firstRun, acceptedAt, clients),
            }
            : {}),
        ...(scheduledRun !== null ? { scheduledRun } : {}),
        ...(recurring !== null && workflowOptions.schedule?.mode === "off"
            ? { recurring }
            : {}),
        executionContract: (0, state_1.createDefaultWorkflowExecutionContract)(),
        plan: null,
        predictedTouchedPaths: [],
        ...(workflowOptions.configOverridePatch !== undefined
            ? { configOverrides: workflowOptions.configOverridePatch }
            : {}),
        followup,
    });
}
function validateIssueCreateWorkerOverride(workflowOptions, clients) {
    if (!(0, config_override_validation_1.hasUnavailableWorkerConfigOverride)({
        configWorkers: (0, control_plane_config_1.getConfiguredWorkerProviders)(clients.config),
        patch: workflowOptions.configOverridePatch,
    })) {
        return;
    }
    throw new Error((0, catalog_1.translate)(clients.locale, "cli.parser.issue.create.invalidWorkflowOption", {
        reason: (0, catalog_1.translate)(clients.locale, "workflow.runContext.invalidCommand.invalidOptionValue"),
    }));
}
function renderIssueCreateSummary(issue, workflowState, workflowStatus, locale, workflowDisplayCatalog) {
    return [
        (0, catalog_1.translate)(locale, "issue.command.create.created", {
            displayId: issue.displayId,
        }),
        (0, catalog_1.translate)(locale, "issue.command.create.url", { value: issue.url }),
        (0, catalog_1.translate)(locale, "issue.command.create.status", {
            value: workflowStatus,
        }),
        (0, catalog_1.translate)(locale, "issue.command.create.workflow", {
            value: resolveIssueCreateWorkflowLabel({
                workflowState,
                locale,
                workflowDisplayCatalog,
            }),
        }),
        renderIssueCreatePlanLine(workflowState, locale),
    ]
        .filter((line) => line !== null)
        .join("\n");
}
function renderIssueCreatePlanLine(workflowState, locale) {
    if (workflowState?.plan !== null) {
        return null;
    }
    return (0, catalog_1.translate)(locale, "issue.command.create.plan", {
        value: (0, catalog_1.translate)(locale, "issue.command.create.plan.pending"),
    });
}
function resolveIssueCreateWorkflowLabel(input) {
    return ((0, display_labels_1.resolveWorkflowDisplayLabels)({
        catalog: input.workflowDisplayCatalog,
        workflowTemplates: input.workflowState?.workflowTemplates ?? null,
    }).workflowTemplateLabel ??
        (0, catalog_1.translate)(input.locale, "workflow.runContext.none"));
}
function buildIssueCreateDraftFile(input) {
    return {
        kind: exports.ISSUE_CREATE_DRAFT_KIND,
        schemaVersion: exports.ISSUE_CREATE_DRAFT_SCHEMA_VERSION,
        preparedAt: input.preparedAt,
        tracker: {
            kind: input.config.ticketTracker.kind,
            projectRef: input.config.ticketTracker.projectRef,
        },
        ...(input.draft.sourcePrompt !== undefined
            ? { sourcePrompt: input.draft.sourcePrompt }
            : {}),
        title: input.draft.title,
        body: input.draft.body,
        selectedIssueTemplatePath: input.draft.selectedIssueTemplatePath ?? null,
        ...(input.draft.workflowOptions !== undefined
            ? { workflowOptions: input.draft.workflowOptions }
            : {}),
        assignees: [...input.assignees],
        labels: [...input.labels],
        ...(input.milestoneRef !== undefined
            ? { milestoneRef: input.milestoneRef }
            : {}),
        ...(input.projectRef !== undefined ? { projectRef: input.projectRef } : {}),
        disabled: input.disabled,
    };
}
function stringifyIssueCreateDraftFile(draftFile) {
    return (0, draft_file_support_1.stringifyReusableDraftFile)(draftFile);
}
function parseIssueCreateDraftFile(text, locale) {
    return (0, draft_file_support_1.parseReusableDraftFileJson)({
        text,
        invalidDraftFileMessage: (0, catalog_1.translate)(locale, "issue.command.create.invalidDraftFile"),
        parse: (parsedJson) => {
            const parsed = issueCreateDraftFileSchema.parse(parsedJson);
            validateIssueCreateTitleAndBody(parsed.title, parsed.body, locale);
            const workflowOptions = parsed.workflowOptions === undefined
                ? undefined
                : parseIssueCreateDraftWorkflowOptions(parsed.workflowOptions, locale);
            return {
                kind: parsed.kind,
                schemaVersion: parsed.schemaVersion,
                preparedAt: parsed.preparedAt,
                tracker: parsed.tracker,
                ...(parsed.sourcePrompt !== undefined
                    ? { sourcePrompt: parsed.sourcePrompt }
                    : {}),
                title: parsed.title,
                body: parsed.body,
                ...(parsed.selectedIssueTemplatePath !== undefined
                    ? { selectedIssueTemplatePath: parsed.selectedIssueTemplatePath }
                    : {}),
                ...(workflowOptions !== undefined ? { workflowOptions } : {}),
                assignees: parsed.assignees,
                labels: parsed.labels,
                ...(parsed.milestoneRef !== undefined
                    ? { milestoneRef: parsed.milestoneRef }
                    : {}),
                ...(parsed.projectRef !== undefined
                    ? { projectRef: parsed.projectRef }
                    : {}),
                disabled: parsed.disabled,
            };
        },
    });
}
function parseIssueCreateDraftWorkflowOptions(workflowOptions, locale) {
    const normalized = (0, setup_pipeline_1.normalizeWorkflowSetupOptionDraft)(workflowOptions);
    if (normalized.kind !== "update") {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.create.invalidDraftFile"));
    }
    const parsed = normalized.fields;
    for (const entry of parsed.configOverridePatch?.entries ?? []) {
        try {
            (0, config_override_validation_1.assertConfigOverrideEntryValid)(entry);
        }
        catch {
            throw new Error((0, catalog_1.translate)(locale, "issue.command.create.invalidDraftFile"));
        }
    }
    return parsed;
}
function assertIssueCreateDraftMatchesTracker(draftFile, config, locale) {
    if (draftFile.tracker.kind !== config.ticketTracker.kind ||
        draftFile.tracker.projectRef !== config.ticketTracker.projectRef) {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.create.draftTrackerMismatch"));
    }
}
function validateIssueCreateTitleAndBody(title, body, locale) {
    if ((0, comment_command_1.hasIssueCommentCommandOnFirstNonEmptyLine)(title)) {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.create.invalidTitleCommand"));
    }
    if ((0, comment_command_1.hasIssueCommentCommandOnFirstNonEmptyLine)(body)) {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.create.invalidBodyCommand"));
    }
}
async function loadIssueCreateBody(body) {
    if (body.kind === "text") {
        return body.text;
    }
    if (body.path === "-") {
        return (0, node_fs_1.readFileSync)(0, "utf8");
    }
    return (0, promises_1.readFile)(body.path, "utf8");
}
async function loadIssueDraftIssueTemplateCandidates(cwd, trackerKind) {
    const templates = await (0, issue_template_discovery_1.discoverIssueTemplates)({
        repoRoot: cwd,
        trackerKind,
    });
    return (0, issue_template_discovery_1.toWorkerDraftTemplateCandidates)(templates);
}
function resolveIssueCreateNextRunAt(schedule, firstRun, acceptedAt, clients) {
    if (schedule.mode === "off") {
        return null;
    }
    const nextRunAt = (0, recurring_1.resolveInitialRecurringNextRunAt)({
        schedule,
        firstRun,
        acceptedAt,
        displayTimeZone: clients.config.i18n.displayTimeZone,
    });
    if (nextRunAt !== null) {
        return nextRunAt;
    }
    throw new Error((0, catalog_1.translate)(clients.locale, "issue.command.create.invalidSchedule", {
        mode: schedule.mode,
        value: schedule.value,
    }));
}
function resolveIssueCreateScheduledRun(workflowOptions, acceptedAt, clients) {
    const command = workflowOptions.scheduledRun;
    if (command === undefined || command.mode === "off") {
        return null;
    }
    const scheduledRun = (0, scheduled_run_1.materializeScheduledRunCommand)({
        command,
        acceptedAt,
        displayTimeZone: clients.config.i18n.displayTimeZone,
    });
    if (scheduledRun !== null) {
        return scheduledRun;
    }
    throw new Error((0, catalog_1.translate)(clients.locale, "issue.command.create.invalidScheduledRun", {
        mode: command.mode,
        value: command.value,
    }));
}
function resolveIssueCreateRecurringState(workflowOptions, workflowTemplates, acceptedAt, clients) {
    if (workflowOptions.recurringAutoStop === undefined) {
        return null;
    }
    const workflowState = (0, state_1.buildPersistedWorkflowState)({
        workflowSurface: "issue",
        workflowTemplates,
        baseBranch: resolveIssueCreateBaseBranch(workflowOptions, clients.config),
        priorityRank: null,
        ...(workflowOptions.schedule !== undefined
            ? {
                schedule: workflowOptions.schedule,
                ...(workflowOptions.schedule.mode !== "off"
                    ? { recurring: { kind: "parent" } }
                    : {}),
            }
            : {}),
        executionContract: (0, state_1.createDefaultWorkflowExecutionContract)(),
        plan: null,
    });
    const resolution = (0, recurring_auto_stop_1.applyRecurringAutoStopCommand)({
        workflowState,
        command: workflowOptions.recurringAutoStop,
        acceptedAt,
        displayTimeZone: clients.config.i18n.displayTimeZone,
    });
    if (resolution.kind === "ok") {
        return resolution.workflowState.recurring ?? null;
    }
    throw new Error((0, catalog_1.translate)(clients.locale, "issue.command.create.invalidRecurringAutoStop"));
}
function resolveIssueCreateBaseBranch(workflowOptions, config) {
    const command = workflowOptions.baseBranch;
    if (command?.mode === "set") {
        return command.branch;
    }
    return config.repositoryHost.baseBranch;
}
function validateIssueCreateWorkflowTemplateSelection(catalog, selectedTemplate, workflowTemplateSelectors, preferredWorkflowTemplates, locale, maxNestedWorkflowDepth) {
    if (selectedTemplate !== null) {
        throwOnInvalidWorkflowTemplateSelection((0, workflow_template_selection_validation_1.validateWorkflowTemplateSelection)({
            catalog,
            templatePath: selectedTemplate.templatePath,
            workflowSurface: "issue",
            maxNestedWorkflowDepth,
        }), "workflow", locale);
    }
    for (const surface of template_bindings_1.SIDE_WORKFLOW_TEMPLATE_SURFACES) {
        throwOnInvalidWorkflowTemplateSelection((0, workflow_template_selection_validation_1.validateWorkflowTemplateSelection)({
            catalog,
            templatePath: (0, workflow_template_selection_validation_1.resolveSelectedWorkflowTemplatePath)(workflowTemplateSelectors[surface], surface),
            workflowSurface: surface,
            maxNestedWorkflowDepth,
        }), surface, locale);
    }
    validateIssueCreatePreferredFollowupTemplates(catalog, preferredWorkflowTemplates, locale, maxNestedWorkflowDepth);
}
function validateIssueCreatePreferredFollowupTemplates(catalog, preferredWorkflowTemplates, locale, maxNestedWorkflowDepth) {
    for (const candidate of preferredWorkflowTemplates) {
        const selector = (0, types_2.parseFollowupWorkflowTemplateCandidateSelector)(candidate);
        if (selector === null) {
            continue;
        }
        throwOnInvalidWorkflowTemplateSelection((0, workflow_template_selection_validation_1.validateWorkflowTemplateSelection)({
            catalog,
            templatePath: (0, workflow_template_selection_validation_1.resolveSelectedWorkflowTemplatePath)(selector, "followup"),
            workflowSurface: "followup",
            maxNestedWorkflowDepth,
        }), "followup", locale);
    }
}
function throwOnInvalidWorkflowTemplateSelection(result, slot, locale) {
    switch (result.kind) {
        case "ok":
            return;
        case "missing-template":
            throw new Error((0, catalog_1.translate)(locale, "workflow.runContext.missingTemplate", {
                templatePath: result.templatePath,
            }));
        case "invalid-surface":
            throw new Error((0, catalog_1.translate)(locale, `issue.command.create.invalidTemplateSlot.${slot}`, {
                templatePath: result.template.templatePath,
            }));
        case "invalid-tree":
            throw new Error((0, validation_1.formatWorkflowTemplateValidationSummary)({
                locale,
                diagnostics: result.diagnostics,
                templatePath: result.template.templatePath,
            }));
    }
}
function dedupeTextValues(values) {
    return [...new Set(values)];
}
