"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensurePullRequest = ensurePullRequest;
exports.buildRoutingResolution = buildRoutingResolution;
exports.resolvePullRequestThreadRecord = resolvePullRequestThreadRecord;
exports.getOpenPullRequest = getOpenPullRequest;
exports.getOpenPullRequestForBase = getOpenPullRequestForBase;
exports.filterPullRequestByBase = filterPullRequestByBase;
exports.filterPullRequestForBase = filterPullRequestForBase;
exports.buildCommitMessage = buildCommitMessage;
exports.buildCliSummary = buildCliSummary;
exports.buildRunCliSummary = buildRunCliSummary;
exports.isTerminalWorkflowSuccess = isTerminalWorkflowSuccess;
exports.isTerminalWorkflowSuccessCandidate = isTerminalWorkflowSuccessCandidate;
exports.shouldCloseTerminalWorkflowSuccess = shouldCloseTerminalWorkflowSuccess;
exports.createEffectExecutionResult = createEffectExecutionResult;
exports.extractEffectExecutionResult = extractEffectExecutionResult;
exports.resolveFailureSummary = resolveFailureSummary;
exports.buildFailureSummary = buildFailureSummary;
exports.buildRedactedFailureSummary = buildRedactedFailureSummary;
exports.renderFailureDetails = renderFailureDetails;
exports.outcomeToStatus = outcomeToStatus;
exports.resolveReadyLabel = resolveReadyLabel;
const command_1 = require("../../core/command");
const catalog_1 = require("../../i18n/catalog");
const base_title_1 = require("../../issues/base-title");
const constants_1 = require("../../platform/constants");
const types_1 = require("../../platform/ticket-tracker/types");
const types_2 = require("../../platform/workflow-state/types");
const constants_2 = require("../../worker/constants");
const errors_1 = require("../../worker/errors");
const types_3 = require("../../worker/types");
const tree_1 = require("../../comments/canonical-workflow-state/tree");
const constants_3 = require("../constants");
const log_text_1 = require("../log-text");
const presentation_1 = require("./presentation");
const shared_1 = require("./shared");
const recurring_1 = require("../../workflows/recurring");
async function ensurePullRequest(repositoryHost, issue, branchName, baseBranch) {
    const existing = getOpenPullRequestForBase(await repositoryHost.findPullRequestByBranch(branchName), baseBranch);
    if (existing) {
        return { number: existing.number, url: existing.url, source: "existing" };
    }
    const pullRequest = await repositoryHost.createPullRequest({
        title: (0, base_title_1.resolveIssueBaseTitle)(issue),
        body: `Refs ${issue.displayId}`,
        headBranch: branchName,
        baseBranch,
        draft: true,
    });
    return {
        number: pullRequest.number,
        url: pullRequest.url,
        source: "created",
    };
}
function buildRoutingResolution(branchAheadOfBase, pullRequest, pullRequestThreadRecord = null) {
    const openPullRequest = getOpenPullRequest(pullRequest);
    const pullRequestThreadId = openPullRequest && pullRequestThreadRecord
        ? pullRequestThreadRecord.id
        : null;
    return {
        facts: {
            branchAheadOfBase,
            openPullRequestExists: openPullRequest !== null,
            pullRequestThreadId,
        },
        pullRequestUrl: openPullRequest?.url ?? null,
        pullRequestThreadId,
    };
}
async function resolvePullRequestThreadRecord(ticketTracker, pullRequest) {
    const openPullRequest = getOpenPullRequest(pullRequest);
    if (!openPullRequest) {
        return null;
    }
    return ticketTracker.getPullRequestThreadRecord({
        pullRequestNumber: openPullRequest.number,
        pullRequestUrl: openPullRequest.url,
    });
}
function getOpenPullRequest(pullRequest) {
    return pullRequest?.state === constants_1.PLATFORM_PULL_REQUEST_STATES.open
        ? pullRequest
        : null;
}
function getOpenPullRequestForBase(pullRequest, baseBranch) {
    return getOpenPullRequest(filterPullRequestByBase(pullRequest, baseBranch));
}
function filterPullRequestByBase(pullRequest, baseBranch) {
    return pullRequest?.baseBranch === baseBranch ? pullRequest : null;
}
function filterPullRequestForBase(pullRequest, baseBranch) {
    return getOpenPullRequestForBase(pullRequest, baseBranch);
}
function buildCommitMessage(issueDisplayId, title) {
    return `feat: issue ${issueDisplayId} ${title}`;
}
function buildCliSummary(state, effectResult) {
    return buildRunCliSummary({
        issue: state.issue,
        outcome: resolveRunIssueOutcome(state.finalOutcome),
        responseLanguage: state.responseLanguage,
        summary: state.summary,
        commentUrl: effectResult.commentUrl,
        prUrl: effectResult.pullRequestUrl,
        pullRequestThreadId: state.pullRequestThreadId,
        nextStep: state.presentation.cliNext,
    });
}
function buildRunCliSummary(input) {
    const headline = input.headline ??
        (0, catalog_1.translate)(input.responseLanguage ?? "en", "run.summary.issueHeadline", {
            issueDisplayId: input.issue.displayId,
            summary: input.summary ?? "",
        });
    return {
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        issue_id: input.issue.id,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        issue_display_id: input.issue.displayId,
        outcome: input.outcome,
        headline,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        issue_url: input.issue.url,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        comment_url: input.commentUrl,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        pr_url: input.prUrl,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        pull_request_thread_id: input.pullRequestThreadId ?? null,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        next_step: input.nextStep,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        deferred_reason: input.deferredReason ?? null,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        interrupt_reason: input.interruptReason ?? null,
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        tried_profiles: input.triedProfiles ?? [],
        // biome-ignore lint/style/useNamingConvention: Public CLI summary shape is snake_case.
        cooldown_until: input.cooldownUntil ?? null,
    };
}
function isTerminalWorkflowSuccess(state) {
    return isTerminalWorkflowSuccessCandidate({
        runMode: state.runMode,
        finalOutcome: state.finalOutcome,
        recordsRunOutcome: state.recordsRunOutcome,
        continuation: state.continuation,
        workflowState: state.workflowState,
    });
}
function isTerminalWorkflowSuccessCandidate(input) {
    if (input.runMode !== types_3.WORKER_RUN_MODES.workflowExecute &&
        input.runMode !== types_3.WORKER_RUN_MODES.workflowClosing) {
        return false;
    }
    if (input.finalOutcome !== constants_2.WORKER_OUTCOMES.proceed ||
        !input.recordsRunOutcome ||
        input.continuation !== null ||
        input.workflowState === null) {
        return false;
    }
    const workflowPlan = input.workflowState.plan;
    if (workflowPlan === null ||
        !(0, tree_1.selectWorkflowPlanProgress)(workflowPlan).isCompleted) {
        return false;
    }
    if ((0, recurring_1.isRecurringParentWorkflowState)(input.workflowState)) {
        return false;
    }
    return true;
}
function shouldCloseTerminalWorkflowSuccess(state) {
    if (!isTerminalWorkflowSuccess(state)) {
        return false;
    }
    return (state.issue.kind === types_1.TRACKER_ITEM_KINDS.issue &&
        !state.facts.branchAheadOfBase &&
        !state.facts.openPullRequestExists);
}
function resolveRunIssueOutcome(outcome) {
    switch (outcome) {
        case constants_2.WORKER_OUTCOMES.proceed:
            return constants_3.RUN_ISSUE_OUTCOMES.queuedAi;
        case constants_2.WORKER_OUTCOMES.waitHuman:
            return constants_3.RUN_ISSUE_OUTCOMES.queuedHuman;
        case constants_2.WORKER_OUTCOMES.fail:
            return constants_3.RUN_ISSUE_OUTCOMES.failed;
    }
}
function createEffectExecutionResult(pullRequestUrl, commentUrl, pullRequestThreadId = null) {
    return { commentUrl, pullRequestThreadId, pullRequestUrl, publications: [] };
}
function extractEffectExecutionResult(error, fallback) {
    if (error instanceof shared_1.EffectExecutionError) {
        return error.result;
    }
    return fallback;
}
function resolveFailureSummary(error, responseLanguage = "en", issueDisplayId) {
    const resolvedError = unwrapFailureError(error);
    if ((0, errors_1.isWorkerFailureError)(resolvedError)) {
        if (resolvedError.failureKind === errors_1.WORKER_FAILURE_KINDS.executionFailed) {
            return {
                diagnostic: resolvedError.diagnosticMessage,
                public: buildRedactedFailureSummary(responseLanguage, issueDisplayId),
            };
        }
        return {
            diagnostic: resolvedError.diagnosticMessage,
            public: resolvedError.publicMessage,
        };
    }
    if (resolvedError instanceof Error) {
        return {
            diagnostic: resolvedError.message,
            public: buildRedactedFailureSummary(responseLanguage, issueDisplayId),
        };
    }
    return {
        diagnostic: "Unknown failure.",
        public: buildRedactedFailureSummary(responseLanguage, issueDisplayId),
    };
}
function buildFailureSummary(error, responseLanguage = "en") {
    return resolveFailureSummary(error, responseLanguage).diagnostic;
}
function buildRedactedFailureSummary(responseLanguage = "en", issueDisplayId) {
    const lines = [
        (0, presentation_1.buildExecutionFailedSummary)(responseLanguage),
        (0, catalog_1.translate)(responseLanguage, "run.presentation.failure.redacted"),
    ];
    if (issueDisplayId !== undefined && issueDisplayId.trim().length > 0) {
        lines.push((0, catalog_1.translate)(responseLanguage, "run.presentation.failure.investigationInstruction"), [
            "```text",
            (0, catalog_1.translate)(responseLanguage, "run.presentation.failure.investigationPrompt", {
                issueDisplayId,
            }),
            "```",
        ].join("\n"));
    }
    return lines.join("\n\n");
}
function renderFailureDetails(error, responseLanguage = "en") {
    void responseLanguage;
    const resolvedError = unwrapFailureError(error);
    const commandError = resolvedError instanceof command_1.CommandError
        ? resolvedError
        : (0, errors_1.isWorkerFailureError)(resolvedError) &&
            resolvedError.cause instanceof command_1.CommandError
            ? resolvedError.cause
            : null;
    const lines = [
        (0, log_text_1.issueLogField)("error", buildFailureSummaryForLog(error, responseLanguage)),
    ];
    if (commandError) {
        lines.push((0, log_text_1.issueLogField)("command", commandError.command), (0, log_text_1.issueLogField)("args", commandError.args.join(" ") || log_text_1.ISSUE_LOG_TEXT.none), (0, log_text_1.issueLogField)("cwd", commandError.cwd ?? log_text_1.ISSUE_LOG_TEXT.none));
        if (commandError.stdout.trim().length > 0) {
            lines.push(`${log_text_1.ISSUE_LOG_TEXT.field.stdout}:`, commandError.stdout.trimEnd());
        }
        if (commandError.stderr.trim().length > 0) {
            lines.push(`${log_text_1.ISSUE_LOG_TEXT.field.stderr}:`, commandError.stderr.trimEnd());
        }
    }
    return lines.join("\n");
}
function buildFailureSummaryForLog(error, responseLanguage = "en") {
    const resolvedError = unwrapFailureError(error);
    if (resolvedError instanceof command_1.CommandError) {
        return [
            "Command failed",
            `(${resolvedError.exitCode}):`,
            [resolvedError.command, ...resolvedError.args].join(" "),
        ].join(" ");
    }
    if ((0, errors_1.isWorkerFailureError)(resolvedError)) {
        return resolvedError.publicMessage;
    }
    return buildFailureSummary(error, responseLanguage);
}
function unwrapFailureError(error) {
    let current = error;
    while (current instanceof shared_1.WorkerCycleError ||
        current instanceof shared_1.EffectExecutionError) {
        const cause = current.cause;
        if (cause === undefined) {
            break;
        }
        current = cause;
    }
    return current;
}
function outcomeToStatus(outcome) {
    switch (outcome) {
        case constants_2.WORKER_OUTCOMES.proceed:
            return types_2.WORKFLOW_STATUSES.aiReady;
        case constants_2.WORKER_OUTCOMES.waitHuman:
        case constants_2.WORKER_OUTCOMES.fail:
            return types_2.WORKFLOW_STATUSES.aiNeedsHuman;
    }
}
function resolveReadyLabel(config) {
    return config.ticketTracker.workflowLabels.aiReady;
}
