"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveRenderedTitleIfChanged = resolveRenderedTitleIfChanged;
exports.resolveIssueTitleProgress = resolveIssueTitleProgress;
exports.shouldPublishSameIssueReplanThroughPublisher = shouldPublishSameIssueReplanThroughPublisher;
exports.publishSameIssueReplanTransition = publishSameIssueReplanTransition;
exports.buildSameIssueReplanIntent = buildSameIssueReplanIntent;
exports.resolveWorkflowUpdateTitleForTransitionState = resolveWorkflowUpdateTitleForTransitionState;
exports.shouldPublishWorkflowUpdateComment = shouldPublishWorkflowUpdateComment;
exports.resolveVisibleEventForTransition = resolveVisibleEventForTransition;
exports.applyRunningPullRequestHandoffPresentation = applyRunningPullRequestHandoffPresentation;
exports.applyPullRequestHandoffSourcePresentation = applyPullRequestHandoffSourcePresentation;
exports.buildPullRequestHandoffSourceWorkflowStateBase = buildPullRequestHandoffSourceWorkflowStateBase;
exports.formatPullRequestHandoffSummary = formatPullRequestHandoffSummary;
exports.buildWorkflowStateForCanonicalComment = buildWorkflowStateForCanonicalComment;
exports.resolveCommentNextForWrite = resolveCommentNextForWrite;
const canonical_workflow_state_1 = require("../../comments/canonical-workflow-state");
const helpers_1 = require("../../comments/canonical-workflow-state/helpers");
const tree_1 = require("../../comments/canonical-workflow-state/tree");
const workflow_update_1 = require("../../comments/workflow-update");
const catalog_1 = require("../../i18n/catalog");
const title_progress_1 = require("../../platform/ticket-tracker/title-progress");
const constants_1 = require("../../worker/constants");
const types_1 = require("../../worker/types");
const publish_precondition_support_1 = require("../../workflows/publish-precondition-support");
const approval_instructions_1 = require("../../workflows/approval-instructions");
const visible_update_builders_1 = require("../../workflows/visible-update-builders");
const publisher_events_1 = require("../../workflows/publisher-events");
const types_2 = require("../../workflows/types");
const publisher_factory_1 = require("./publisher-factory");
const results_1 = require("./results");
const same_issue_replan_publication_1 = require("./same-issue-replan-publication");
const same_issue_replan_state_support_1 = require("./same-issue-replan-state-support");
const shared_1 = require("./shared");
function resolveRenderedTitleIfChanged(input) {
    if (!input.enabled && input.baseTitleOverride === undefined) {
        return null;
    }
    const options = {
        locale: input.locale,
        surface: input.surface,
        ...(input.suppressDoneLabel !== undefined
            ? { suppressDoneLabel: input.suppressDoneLabel }
            : {}),
    };
    const title = (0, title_progress_1.renderTitleWithProgress)(input.baseTitleOverride ?? input.issue.baseTitle, input.enabled ? resolveIssueTitleProgress(input.workflowState) : null, options);
    return input.issue.title === title ? null : title;
}
function resolveIssueTitleProgress(workflowState) {
    const plan = workflowState?.plan;
    if (!plan || plan.steps.length === 0) {
        return null;
    }
    const progress = (0, tree_1.selectWorkflowPlanProgress)(plan);
    return {
        completedStepCount: progress.completedStepCount,
        stepCount: plan.steps.length,
        isDone: progress.isCompleted,
    };
}
function shouldPublishSameIssueReplanThroughPublisher(state) {
    return state.sameIssueReplanSource !== null;
}
async function publishSameIssueReplanTransition(context) {
    const { state } = context;
    if (state.workflowState === null) {
        throw new Error("Workflow state is required for same issue replan publish.");
    }
    const replanIssue = await (0, shared_1.hydratePullRequestIssueSourceBranchName)(context.ticketTracker, state.issue);
    const comments = await (0, shared_1.loadSortedIssueComments)(context.ticketTracker, context.issueId, {
        timeline: "issue-only",
    });
    const previousWorkflowStateResolution = resolvePreviousWorkflowStateForReplanPublish(comments, state);
    const previousWorkflowState = previousWorkflowStateResolution.workflowState;
    const nextWorkflowState = buildWorkflowStateForCanonicalComment(state, comments);
    const sameIssueReplanSource = state.sameIssueReplanSource;
    if (sameIssueReplanSource === null) {
        throw new Error("Same-issue replan publish requires an explicit source.");
    }
    const visibleUpdate = await buildSameIssueReplanVisibleUpdate({
        context,
        nextWorkflowState,
        intentKind: sameIssueReplanSource,
    });
    const publisher = (0, publisher_factory_1.createRunWorkflowPublisher)(context);
    const request = (0, same_issue_replan_publication_1.buildSameIssueReplanPublishRequest)({
        intent: buildSameIssueReplanIntent({
            kind: sameIssueReplanSource,
            issue: replanIssue,
            state,
            previousWorkflowState,
            currentWorkflowStateCommentId: previousWorkflowStateResolution.currentWorkflowStateCommentId,
            nextWorkflowState,
            previousNeedsHumanReason: (0, workflow_update_1.findLatestNeedsHumanReason)(comments),
            visibleUpdate,
        }),
        issueComments: comments,
        workflowLabels: context.workflowLabels,
        responseLanguage: state.responseLanguage,
    });
    if (request === null) {
        throw new Error("Same-issue replan publish requires a managed pull request thread.");
    }
    return {
        request,
        result: await publisher.publishWorkflow(request),
    };
}
function resolvePreviousWorkflowStateForReplanPublish(comments, state) {
    const resolution = (0, canonical_workflow_state_1.resolveCanonicalWorkflowStateComment)(comments, state.responseLanguage);
    if (resolution.kind === "invalid") {
        throw new Error(resolution.summary);
    }
    if (resolution.kind === "found") {
        return {
            workflowState: resolution.workflowState,
            currentWorkflowStateCommentId: resolution.comment.id,
        };
    }
    if (state.runMode === types_1.WORKER_RUN_MODES.workflowExecute) {
        throw new Error((0, catalog_1.translate)(state.responseLanguage, "workflow.runContext.canonical.missingForExecution"));
    }
    if (state.workflowState === null) {
        throw new Error("Workflow state is required for same issue replan publish.");
    }
    return {
        workflowState: state.workflowState,
        currentWorkflowStateCommentId: null,
    };
}
function buildSameIssueReplanIntent(input) {
    const replanReason = input.state.continuation?.reason ??
        input.previousWorkflowState.pendingPlanningReason ??
        (input.kind === "preflight_template_drift" ? input.state.summary : null);
    const base = {
        issue: input.issue,
        previousWorkflowState: input.previousWorkflowState,
        publishPrecondition: (0, publish_precondition_support_1.buildWorkflowPublishPrecondition)({
            currentWorkflowStateCommentId: input.currentWorkflowStateCommentId,
            workflowState: input.previousWorkflowState,
        }),
        nextWorkflowState: (0, same_issue_replan_state_support_1.deriveSameIssueReplanTransitionWorkflowState)({
            kind: input.kind,
            previousWorkflowState: input.previousWorkflowState,
            workflowState: input.nextWorkflowState,
            consecutiveAiRuns: input.nextWorkflowState.consecutiveAiRuns,
            lastScannedCommentCursor: input.state.scannedInputCursor ??
                input.previousWorkflowState.lastScannedCommentCursor ??
                null,
            reason: replanReason,
        }),
        previousProjection: input.state.previousSnapshot,
        nextProjection: input.state.nextSnapshot,
        previousNeedsHumanReason: input.previousNeedsHumanReason,
        nextNeedsHumanReason: input.state.needsHumanReason,
        visibleUpdate: input.visibleUpdate,
        ...(input.state.labelProjection !== undefined
            ? { labelProjection: input.state.labelProjection }
            : {}),
    };
    if (input.kind === "worker_replan_same_issue") {
        return {
            ...base,
            kind: input.kind,
            reason: replanReason,
            scannedInputCursor: input.state.scannedInputCursor ??
                input.previousWorkflowState.lastScannedCommentCursor ??
                null,
        };
    }
    if (input.kind === "run_limit_downgrade") {
        return {
            ...base,
            kind: input.kind,
            reason: replanReason,
            scannedInputCursor: input.state.scannedInputCursor ??
                input.previousWorkflowState.lastScannedCommentCursor ??
                null,
        };
    }
    if (input.kind === "preflight_template_drift") {
        return {
            ...base,
            kind: input.kind,
            reason: replanReason ?? input.state.summary,
        };
    }
    return {
        ...base,
        kind: "replan_completion",
    };
}
async function buildSameIssueReplanVisibleUpdate(input) {
    const { state } = input.context;
    if (state.skipWorkflowUpdateComment === true) {
        return null;
    }
    const shouldPublishReplanQueued = input.intentKind === "worker_replan_same_issue" ||
        input.intentKind === "preflight_template_drift";
    if (!shouldPublishReplanQueued &&
        !shouldPublishWorkflowUpdateComment(state)) {
        return null;
    }
    const event = shouldPublishReplanQueued
        ? publisher_events_1.WORKFLOW_VISIBLE_EVENTS.replanQueued
        : resolveVisibleEventForTransition(state);
    return (0, visible_update_builders_1.buildWorkflowVisibleUpdate)({
        event,
        ...resolveWorkflowUpdateTitleForTransitionState(state),
        summary: shouldPublishReplanQueued
            ? state.summary
            : state.presentation.commentSummary,
        next: resolveCommentNextForWrite(state),
        ...(shouldAttachWorkerOutcomeToSameIssueReplanUpdate(input.intentKind)
            ? { workerOutcome: state.presentation.commentOutcome }
            : {}),
        ...(state.needsHumanReason !== null
            ? { needsHumanReason: state.needsHumanReason }
            : {}),
        ...(state.workflowTemplateName !== null
            ? { workflowTemplateLabel: state.workflowTemplateName }
            : {}),
    });
}
function resolveWorkflowUpdateTitleForTransitionState(state) {
    if (state.planningIntent === "revise_plan" &&
        state.needsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.startApproval) {
        return {
            title: (0, catalog_1.translate)(state.responseLanguage, "workflowUpdate.title.waiting.revisedStartApproval"),
        };
    }
    return {};
}
function shouldAttachWorkerOutcomeToSameIssueReplanUpdate(intentKind) {
    return (intentKind === "worker_replan_same_issue" ||
        intentKind === "run_limit_downgrade" ||
        intentKind === "replan_completion");
}
function shouldPublishWorkflowUpdateComment(state) {
    return (state.skipWorkflowUpdateComment !== true &&
        (state.finalOutcome === constants_1.WORKER_OUTCOMES.waitHuman ||
            state.finalOutcome === constants_1.WORKER_OUTCOMES.fail ||
            (state.finalOutcome === constants_1.WORKER_OUTCOMES.proceed &&
                (0, results_1.isTerminalWorkflowSuccess)(state))));
}
function resolveVisibleEventForTransition(state) {
    if ((0, results_1.isTerminalWorkflowSuccess)(state)) {
        return publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowCompleted;
    }
    if (state.finalOutcome === constants_1.WORKER_OUTCOMES.fail) {
        return publisher_events_1.WORKFLOW_VISIBLE_EVENTS.workflowFailed;
    }
    if (state.needsHumanReason === publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.reviewReady) {
        return state.issue.kind === "issue"
            ? publisher_events_1.WORKFLOW_VISIBLE_EVENTS.issueReviewReady
            : publisher_events_1.WORKFLOW_VISIBLE_EVENTS.prReviewReady;
    }
    if (state.finalOutcome === constants_1.WORKER_OUTCOMES.waitHuman) {
        return publisher_events_1.WORKFLOW_VISIBLE_EVENTS.humanAttentionRequested;
    }
    return publisher_events_1.WORKFLOW_VISIBLE_EVENTS.replanQueued;
}
function applyRunningPullRequestHandoffPresentation(state) {
    const next = (0, catalog_1.translate)(state.responseLanguage, "run.presentation.prHandoff.next.continue");
    state.presentation.commentOutcome = constants_1.WORKER_OUTCOMES.proceed;
    state.presentation.commentNext = next;
    state.presentation.cliNext = next;
}
function applyPullRequestHandoffSourcePresentation(input) {
    const key = input.mode === "continue_existing"
        ? "run.presentation.prHandoff.next.continue"
        : input.mode === "auto_merge"
            ? "run.presentation.prHandoff.next.autoMerge"
            : input.mode === "proceed"
                ? "run.presentation.prHandoff.next.queued"
                : "run.presentation.prHandoff.next.review";
    const next = (0, catalog_1.translate)(input.state.responseLanguage, key);
    input.state.presentation.commentNext = next;
    input.state.presentation.cliNext = next;
}
function buildPullRequestHandoffSourceWorkflowStateBase(input) {
    const baseWorkflowState = buildWorkflowStateForCanonicalComment(input.state, input.comments);
    const existingSourceWorkflowStateResolution = (0, canonical_workflow_state_1.resolveCanonicalWorkflowStateComment)(input.comments);
    if (existingSourceWorkflowStateResolution.kind === "invalid") {
        throw new Error(existingSourceWorkflowStateResolution.summary);
    }
    return {
        ...baseWorkflowState,
        lastScannedCommentCursor: existingSourceWorkflowStateResolution.kind === "found"
            ? existingSourceWorkflowStateResolution.workflowState
                .lastScannedCommentCursor
            : (input.state.workflowState?.lastScannedCommentCursor ?? null),
    };
}
function formatPullRequestHandoffSummary(input, responseLanguage) {
    const copy = resolvePullRequestHandoffCopy(responseLanguage);
    const flattenedGoal = (0, helpers_1.flattenMarkdownSummary)(input.goal);
    const goal = flattenedGoal?.trim().length ? flattenedGoal.trim() : null;
    const lines = [
        `**${copy.heading}**`,
        "",
        renderKeyValueBullet(copy.sourceIssueLabel, renderMarkdownLink(input.sourceIssueDisplayId, input.sourceIssueUrl)),
        renderKeyValueBullet(copy.sourceTitleLabel, renderMarkdownLink(input.sourceTitle, input.sourceIssueUrl)),
        renderKeyValueBullet(copy.currentStepLabel, input.currentStep),
        "",
        `**${copy.supplementHeading}**`,
        "",
        ...(goal === null ? [] : [renderKeyValueBullet(copy.goalLabel, goal)]),
        renderKeyValueBullet(copy.reviewBasisLabel, copy.reviewBasisValue),
    ];
    return lines.join("\n");
}
function resolvePullRequestHandoffCopy(responseLanguage) {
    return {
        heading: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.heading"),
        sourceIssueLabel: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.sourceIssueLabel"),
        sourceTitleLabel: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.sourceTitleLabel"),
        currentStepLabel: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.currentStepLabel"),
        supplementHeading: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.supplementHeading"),
        goalLabel: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.goalLabel"),
        reviewBasisLabel: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.reviewBasisLabel"),
        reviewBasisValue: (0, catalog_1.translate)(responseLanguage, "run.pullRequestHandoff.reviewBasisValue"),
    };
}
function renderKeyValueBullet(label, value) {
    return `- **${label}:** ${value}`;
}
function renderMarkdownLink(label, url) {
    return `[${escapeMarkdownLinkLabel(label)}](${url})`;
}
function escapeMarkdownLinkLabel(value) {
    return value
        .replaceAll("\\", "\\\\")
        .replaceAll("*", "\\*")
        .replaceAll("_", "\\_")
        .replaceAll("[", "\\[")
        .replaceAll("]", "\\]")
        .replaceAll("`", "\\`");
}
function buildWorkflowStateForCanonicalComment(state, comments) {
    const workflowState = state.workflowState;
    if (workflowState === null) {
        throw new Error("Workflow state is required for canonical comment writes.");
    }
    const lastScannedCommentCursor = state.scannedInputCursor;
    const consecutiveAiRuns = state.incrementsConsecutiveAiRuns
        ? (0, shared_1.resolveCurrentConsecutiveAiRuns)(comments) + 1
        : workflowState.consecutiveAiRuns;
    if (workflowState.plan === null) {
        return {
            ...workflowState,
            consecutiveAiRuns,
            lastScannedCommentCursor,
            finalResult: null,
        };
    }
    return {
        ...workflowState,
        plan: workflowState.plan,
        consecutiveAiRuns,
        lastScannedCommentCursor,
        finalResult: resolveWorkflowFinalResult(state),
    };
}
function resolveWorkflowFinalResult(state) {
    if (state.runMode === types_1.WORKER_RUN_MODES.workflowPlan) {
        return null;
    }
    if (!state.recordsRunOutcome) {
        return null;
    }
    if (state.continuation?.strategy === "replan_same_issue") {
        return state.workflowState?.finalResult ?? null;
    }
    if (state.finalOutcome === constants_1.WORKER_OUTCOMES.proceed &&
        (0, results_1.isTerminalWorkflowSuccess)(state)) {
        return (0, types_2.buildWorkflowFinalResultWithDefaults)({
            outcome: state.finalOutcome,
            ...resolveWorkflowResultFields(state),
        });
    }
    if (state.finalOutcome === constants_1.WORKER_OUTCOMES.fail) {
        return (0, types_2.buildWorkflowFinalResultWithDefaults)({
            outcome: state.finalOutcome,
            ...resolveWorkflowResultFields(state),
        });
    }
    if (state.finalOutcome !== constants_1.WORKER_OUTCOMES.waitHuman) {
        return null;
    }
    const workflowPlan = state.workflowState?.plan;
    if (workflowPlan === null ||
        workflowPlan === undefined ||
        !(0, tree_1.selectWorkflowPlanProgress)(workflowPlan).isCompleted) {
        return null;
    }
    return (0, types_2.buildWorkflowFinalResultWithDefaults)({
        outcome: state.finalOutcome,
        ...resolveWorkflowResultFields(state),
    });
}
function resolveWorkflowResultFields(state) {
    if (state.result !== null) {
        return (0, types_2.buildWorkflowResultFieldsWithDefaults)(state.result);
    }
    return (0, types_2.buildWorkflowResultFieldsWithDefaults)({
        resultSummary: state.summary,
        humanComment: state.comment ??
            (state.finalOutcome === constants_1.WORKER_OUTCOMES.proceed ? null : state.summary),
    });
}
function resolveCommentNextForWrite(state) {
    if (state.presentation.commentOutcome === constants_1.WORKER_OUTCOMES.waitHuman &&
        state.needsHumanReason === "foreign_approval") {
        return (0, approval_instructions_1.buildForeignApprovalNext)(state.responseLanguage, state.issue.id);
    }
    if (state.presentation.commentOutcome === constants_1.WORKER_OUTCOMES.waitHuman &&
        state.needsHumanReason === "start_approval") {
        return (0, approval_instructions_1.buildStartApprovalNext)(state.responseLanguage, state.issue.id);
    }
    return state.presentation.commentNext;
}
