"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.continuePullRequestAutoMerge = continuePullRequestAutoMerge;
const constants_1 = require("../../worker/constants");
const auto_merge_state_1 = require("../../workflows/auto-merge-state");
const visible_update_builders_1 = require("../../workflows/visible-update-builders");
const publisher_events_1 = require("../../workflows/publisher-events");
const constants_2 = require("../constants");
const log_text_1 = require("../log-text");
const effect_log_1 = require("./effect-log");
const needs_human_merge_1 = require("./needs-human-merge");
const needs_human_merge_state_1 = require("./needs-human-merge-state");
const publisher_factory_1 = require("./publisher-factory");
const pull_request_completion_1 = require("./pull-request-completion");
const results_1 = require("./results");
const issue_branch_target_1 = require("./issue-branch-target");
async function continuePullRequestAutoMerge(input) {
    const currentAutoMergeState = input.workflowState?.autoMergeState;
    const pullRequest = await resolveAutoMergePullRequest(input);
    const pullRequestNumber = input.issue.pullRequestNumber ?? null;
    const automationState = input.automationState ??
        (pullRequestNumber !== null
            ? await input.context.repositoryHost.getPullRequestAutomationState(pullRequestNumber)
            : null);
    const earlySummary = await resolveEarlyAutoMergeSummary({
        context: input.context,
        issue: input.issue,
        logger: input.logger,
        branchName: input.branchName,
        responseLanguage: input.responseLanguage,
        workflowState: input.workflowState,
        pullRequest,
        automationState,
    });
    if (earlySummary !== null) {
        return earlySummary;
    }
    if (automationState === null) {
        throw new Error("Expected pull request automation state.");
    }
    const dependencyMergeSummary = await prepareAutoMergeDependencyPreflight({
        context: input.context,
        issue: input.issue,
        logger: input.logger,
        branchName: input.branchName,
        automationState,
        responseLanguage: input.responseLanguage,
        workflowState: input.workflowState,
    });
    if (dependencyMergeSummary !== null) {
        return dependencyMergeSummary;
    }
    if (isAutoMergeReviewBlocked(automationState)) {
        return handleAutoMergeWaitingForState({
            request: input,
            currentAutoMergeState,
            automationStateUrl: automationState.url,
        });
    }
    if (isAutoMergeConflictBlocked(automationState)) {
        return publishAutoMergeConflictReplan({
            request: input,
            automationStateUrl: automationState.url,
        });
    }
    if (!(0, needs_human_merge_1.canAutoMergePullRequestNow)(automationState)) {
        return handleAutoMergeWaitingForState({
            request: input,
            currentAutoMergeState,
            automationStateUrl: automationState.url,
        });
    }
    return (0, needs_human_merge_1.mergeReadyPullRequest)({
        context: input.context,
        issue: input.issue,
        logger: input.logger,
        branchName: input.branchName,
        automationState,
        responseLanguage: input.responseLanguage,
        workflowState: input.workflowState,
        previousNeedsHumanReason: null,
        onPushRejected: async () => (0, needs_human_merge_1.publishAutoMergePendingUpdate)({
            context: input.context,
            issue: input.issue,
            logger: input.logger,
            responseLanguage: input.responseLanguage,
            workflowState: (0, needs_human_merge_state_1.resolveAutoMergeWorkflowState)({
                workflowState: input.workflowState,
                autoMergeState: auto_merge_state_1.WORKFLOW_AUTO_MERGE_STATES.pending,
            }),
            summary: (0, needs_human_merge_1.buildNeedsHumanMergeRaceMessage)(input.responseLanguage),
            nextStep: (0, needs_human_merge_1.buildNeedsHumanMergeRaceNextMessage)(input.responseLanguage),
            prUrl: automationState.url,
        }),
        onRetryableMergeFailure: async (error) => {
            const nextAutoMergeState = (0, auto_merge_state_1.resolveNextRetryAutoMergeState)(currentAutoMergeState);
            if (nextAutoMergeState === null) {
                return publishAutoMergeNeedsHumanFailure({
                    context: input.context,
                    issue: input.issue,
                    logger: input.logger,
                    responseLanguage: input.responseLanguage,
                    workflowState: input.workflowState,
                    automationStateUrl: automationState.url,
                    error,
                });
            }
            const publication = await syncAutoMergeState({
                context: input.context,
                issue: input.issue,
                responseLanguage: input.responseLanguage,
                workflowState: input.workflowState,
                autoMergeState: nextAutoMergeState,
            });
            await (0, effect_log_1.appendEffectFailureLog)(input.logger, [
                (0, log_text_1.issueLogField)("effect", "merge_pull_request"),
                (0, log_text_1.issueLogField)("pr", automationState.url),
                (0, log_text_1.issueLogField)("note", `retryable_failure_next_cycle:${nextAutoMergeState}`),
                (0, results_1.renderFailureDetails)(error, input.logger.locale),
            ]);
            return (0, results_1.buildRunCliSummary)({
                issue: input.issue,
                outcome: constants_2.RUN_ISSUE_OUTCOMES.queuedAi,
                responseLanguage: input.responseLanguage,
                summary: (0, needs_human_merge_1.buildAutoMergePendingMessage)(input.responseLanguage),
                commentUrl: publication.workflowStateComment?.url ?? null,
                prUrl: automationState.url,
                nextStep: (0, needs_human_merge_1.buildAutoMergePendingNextMessage)(input.responseLanguage),
            });
        },
        onMergeFailure: async (error) => {
            return publishAutoMergeNeedsHumanFailure({
                context: input.context,
                issue: input.issue,
                logger: input.logger,
                responseLanguage: input.responseLanguage,
                workflowState: input.workflowState,
                automationStateUrl: automationState.url,
                error,
            });
        },
    });
}
async function resolveAutoMergePullRequest(input) {
    if (input.pullRequest !== undefined) {
        return input.pullRequest;
    }
    if (input.workflowState === null) {
        return null;
    }
    return (0, results_1.filterPullRequestByBase)(await input.context.repositoryHost.findPullRequestByBranch(input.branchName), (0, issue_branch_target_1.resolveIssueRunBaseBranch)(input.workflowState));
}
function isAutoMergeReviewBlocked(automationState) {
    return (automationState.reviewDecision === "CHANGES_REQUESTED" ||
        automationState.isDraft);
}
function isAutoMergeConflictBlocked(automationState) {
    return (automationState.mergeability === "CONFLICTING" ||
        automationState.mergeStateStatus === "DIRTY");
}
function handleAutoMergeWaitingForState(input) {
    return handleAutoMergeWaiting({
        context: input.request.context,
        issue: input.request.issue,
        logger: input.request.logger,
        responseLanguage: input.request.responseLanguage,
        workflowState: input.request.workflowState,
        currentAutoMergeState: input.currentAutoMergeState,
        publishAutoMergePendingUpdateWhenWaiting: input.request.publishAutoMergePendingUpdateWhenWaiting,
        automationStateUrl: input.automationStateUrl,
    });
}
async function publishAutoMergeConflictReplan(input) {
    const summary = (0, needs_human_merge_1.buildAutoMergeConflictReplanMessage)(input.request.responseLanguage);
    const nextStep = (0, needs_human_merge_1.buildAutoMergeConflictReplanNextMessage)(input.request.responseLanguage);
    const publication = await (0, needs_human_merge_1.publishAutoMergeState)({
        context: input.request.context,
        issue: input.request.issue,
        responseLanguage: input.request.responseLanguage,
        workflowState: resolveAutoMergeConflictReplanWorkflowState({
            workflowState: input.request.workflowState,
            pendingPlanningReason: summary,
        }),
        appendCanonicalWorkflowStateComment: true,
        visibleUpdate: (0, visible_update_builders_1.buildWorkflowVisibleUpdate)({
            event: publisher_events_1.WORKFLOW_VISIBLE_EVENTS.replanQueued,
            summary,
            next: nextStep,
            workerOutcome: constants_1.WORKER_OUTCOMES.proceed,
        }),
    });
    if (publication.targetWorkflowProjection !== null) {
        input.request.issue.workflowState = {
            ...publication.targetWorkflowProjection,
        };
    }
    await (0, effect_log_1.appendEffectResultLog)(input.request.logger, [
        (0, log_text_1.issueLogField)("effect", "auto_merge_conflict_replan"),
        (0, log_text_1.issueLogField)("pr", input.automationStateUrl),
    ]);
    return (0, results_1.buildRunCliSummary)({
        issue: input.request.issue,
        outcome: constants_2.RUN_ISSUE_OUTCOMES.queuedAi,
        responseLanguage: input.request.responseLanguage,
        summary,
        commentUrl: (0, publisher_factory_1.resolveRunWorkflowPublicationCommentUrl)(publication),
        prUrl: input.automationStateUrl,
        nextStep,
    });
}
function resolveAutoMergeConflictReplanWorkflowState(input) {
    return input.workflowState === null
        ? null
        : (0, needs_human_merge_state_1.resolvePullRequestMergeReplanWorkflowState)({
            workflowState: input.workflowState,
            pendingPlanningReason: input.pendingPlanningReason,
        });
}
async function resolveEarlyAutoMergeSummary(input) {
    const completion = await (0, pull_request_completion_1.resolvePullRequestCompletion)({
        repositoryHost: input.context.repositoryHost,
        pullRequest: input.pullRequest,
        logger: input.logger,
        branchName: input.branchName,
    });
    if (completion.status === "completed") {
        return (0, needs_human_merge_1.retryMergedPullRequestFinalization)(input.context, input.issue, input.logger, input.branchName, completion.pullRequest, input.responseLanguage, input.workflowState, null, completion.reason);
    }
    if (input.automationState === null) {
        return publishAutoMergeUnavailableSummary({
            context: input.context,
            issue: input.issue,
            logger: input.logger,
            responseLanguage: input.responseLanguage,
            workflowState: input.workflowState,
            pullRequestUrl: input.pullRequest?.url ?? null,
        });
    }
    return null;
}
async function handleAutoMergeWaiting(input) {
    if ((0, auto_merge_state_1.isRetryAutoMergeState)(input.currentAutoMergeState) &&
        !input.publishAutoMergePendingUpdateWhenWaiting) {
        await syncAutoMergeState({
            context: input.context,
            issue: input.issue,
            responseLanguage: input.responseLanguage,
            workflowState: input.workflowState,
            autoMergeState: auto_merge_state_1.WORKFLOW_AUTO_MERGE_STATES.pending,
        });
    }
    if (!input.publishAutoMergePendingUpdateWhenWaiting) {
        return null;
    }
    return (0, needs_human_merge_1.publishAutoMergePendingUpdate)({
        context: input.context,
        issue: input.issue,
        logger: input.logger,
        responseLanguage: input.responseLanguage,
        workflowState: (0, needs_human_merge_state_1.resolveAutoMergeWorkflowState)({
            workflowState: input.workflowState,
            autoMergeState: auto_merge_state_1.WORKFLOW_AUTO_MERGE_STATES.pending,
        }),
        summary: (0, needs_human_merge_1.buildAutoMergePendingMessage)(input.responseLanguage),
        nextStep: (0, needs_human_merge_1.buildAutoMergePendingNextMessage)(input.responseLanguage),
        prUrl: input.automationStateUrl,
    });
}
async function prepareAutoMergeDependencyPreflight(input) {
    const dependencyMergePreflight = await (0, needs_human_merge_1.preparePullRequestDependenciesBeforeMerge)({
        context: input.context,
        issue: input.issue,
        logger: input.logger,
        branchName: input.branchName,
        automationState: input.automationState,
        responseLanguage: input.responseLanguage,
        workflowState: input.workflowState,
    });
    return dependencyMergePreflight.action === "stop"
        ? dependencyMergePreflight.summary
        : null;
}
async function publishAutoMergeUnavailableSummary(input) {
    const publication = await (0, needs_human_merge_1.publishAutoMergeNeedsHumanUpdate)({
        context: input.context,
        issue: input.issue,
        responseLanguage: input.responseLanguage,
        workflowState: (0, needs_human_merge_state_1.resolveAutoMergeWorkflowState)({
            workflowState: input.workflowState,
            autoMergeState: null,
        }),
        summary: (0, needs_human_merge_1.buildAutoMergeUnavailableMessage)(input.responseLanguage),
        next: (0, needs_human_merge_1.buildAutoMergeUnavailableNextMessage)(input.responseLanguage),
        needsHumanReason: publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.question,
    });
    await (0, effect_log_1.appendEffectFailureLog)(input.logger, [
        (0, log_text_1.issueLogField)("effect", "auto_merge_pull_request"),
        (0, log_text_1.issueLogField)("pr", input.pullRequestUrl ?? "-"),
        (0, log_text_1.issueLogField)("reason", "pull_request_not_open"),
    ]);
    return (0, results_1.buildRunCliSummary)({
        issue: input.issue,
        outcome: constants_2.RUN_ISSUE_OUTCOMES.queuedHuman,
        responseLanguage: input.responseLanguage,
        summary: (0, needs_human_merge_1.buildAutoMergeUnavailableMessage)(input.responseLanguage),
        commentUrl: (0, publisher_factory_1.resolveRunWorkflowPublicationCommentUrl)(publication),
        prUrl: input.pullRequestUrl,
        nextStep: (0, needs_human_merge_1.buildAutoMergeUnavailableNextMessage)(input.responseLanguage),
    });
}
async function syncAutoMergeState(input) {
    const publication = await (0, needs_human_merge_1.publishAutoMergeState)({
        context: input.context,
        issue: input.issue,
        responseLanguage: input.responseLanguage,
        workflowState: (0, needs_human_merge_state_1.resolveAutoMergeWorkflowState)({
            workflowState: input.workflowState,
            autoMergeState: input.autoMergeState,
        }),
    });
    if (publication.targetWorkflowProjection !== null) {
        input.issue.workflowState = { ...publication.targetWorkflowProjection };
    }
    return publication;
}
async function publishAutoMergeNeedsHumanFailure(input) {
    const publication = await (0, needs_human_merge_1.publishAutoMergeNeedsHumanUpdate)({
        context: input.context,
        issue: input.issue,
        responseLanguage: input.responseLanguage,
        workflowState: (0, needs_human_merge_state_1.resolveAutoMergeWorkflowState)({
            workflowState: input.workflowState,
            autoMergeState: null,
        }),
        summary: (0, needs_human_merge_1.buildNeedsHumanMergeFailureMessage)(input.responseLanguage),
        next: (0, needs_human_merge_1.buildNeedsHumanFailureNextMessage)(input.responseLanguage),
        needsHumanReason: publisher_events_1.WORKFLOW_NEEDS_HUMAN_REASONS.systemError,
    });
    await (0, effect_log_1.appendEffectFailureLog)(input.logger, [
        (0, log_text_1.issueLogField)("effect", "merge_pull_request"),
        (0, log_text_1.issueLogField)("pr", input.automationStateUrl),
        (0, results_1.renderFailureDetails)(input.error, input.logger.locale),
    ]);
    return (0, results_1.buildRunCliSummary)({
        issue: input.issue,
        outcome: constants_2.RUN_ISSUE_OUTCOMES.queuedHuman,
        responseLanguage: input.responseLanguage,
        summary: (0, needs_human_merge_1.buildNeedsHumanMergeFailureMessage)(input.responseLanguage),
        commentUrl: (0, publisher_factory_1.resolveRunWorkflowPublicationCommentUrl)(publication),
        prUrl: input.automationStateUrl,
        nextStep: (0, needs_human_merge_1.buildNeedsHumanFailureNextMessage)(input.responseLanguage),
    });
}
