"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runClaimedIssueLoop = runClaimedIssueLoop;
const catalog_1 = require("../../i18n/catalog");
const default_issue_workspace_manager_1 = require("../../workspaces/default-issue-workspace-manager");
const claimed_issue_pass_1 = require("./claimed-issue-pass");
const failure_recovery_1 = require("./failure-recovery");
const issue_branch_target_1 = require("./issue-branch-target");
const run_state_helpers_1 = require("./run-state-helpers");
const handoffs_1 = require("./handoffs");
const loop_heartbeat_1 = require("./loop-heartbeat");
const publish_1 = require("./publish");
const shared_1 = require("./shared");
async function runClaimedIssueLoop(input) {
    const { context, claimedIssue, logger, workflowLabels, dependencies } = input;
    let { failureSeed, continuationContext } = input;
    let workspace = null;
    let heartbeat = null;
    try {
        const workspacePreparation = await prepareWorkspaceForClaimedIssueLoop({
            context,
            claimedIssue,
            logger,
            workflowLabels,
            failureSeed,
        });
        if (workspacePreparation.summary !== null) {
            return workspacePreparation.summary;
        }
        if (workspacePreparation.workspace === null) {
            throw new Error("Workspace preparation did not return a workspace.");
        }
        workspace = workspacePreparation.workspace;
        heartbeat = (0, loop_heartbeat_1.startExecutionOwnershipHeartbeat)({
            context,
            claimedIssue,
            responseLanguage: logger.locale,
        });
        if (heartbeat === null) {
            throw new Error("Execution ownership heartbeat did not start.");
        }
        const activeHeartbeat = heartbeat;
        for (let freshnessPass = 1; freshnessPass <= shared_1.MAX_FRESHNESS_PASSES; freshnessPass += 1) {
            const passResult = await (0, claimed_issue_pass_1.runClaimedIssuePass)({
                context,
                claimedIssue,
                logger,
                workflowLabels,
                workspace,
                freshnessPass,
                failureSeed,
                continuationContext,
                suspendHeartbeat: async () => {
                    await activeHeartbeat.suspend();
                },
                resumeHeartbeat: () => {
                    activeHeartbeat.resume();
                },
                dependencies,
            });
            failureSeed = passResult.failureSeed;
            continuationContext = passResult.continuationContext;
            if (passResult.kind === "complete") {
                return passResult.summary;
            }
        }
    }
    catch (error) {
        await heartbeat?.suspend();
        return (0, failure_recovery_1.handleClaimedIssueFailure)(context, claimedIssue, logger, failureSeed, error, workflowLabels);
    }
    finally {
        await heartbeat?.stop();
    }
    throw new Error((0, catalog_1.translate)(context.config.i18n.defaultLanguage, "run.error.freshnessLoopExhausted"));
}
async function prepareWorkspaceForClaimedIssueLoop(input) {
    try {
        const workspace = await ensureIssueWorkspace(input.context, input.claimedIssue.originalIssue, input.failureSeed.workflowState);
        return {
            workspace,
            summary: null,
        };
    }
    catch (error) {
        if (!(0, run_state_helpers_1.isWorkspaceSyncBlockedError)(error)) {
            throw error;
        }
        return {
            workspace: null,
            summary: await (0, handoffs_1.handOffWorkspaceSyncBlockedIssueToHuman)({
                context: input.context,
                claimedIssue: input.claimedIssue,
                logger: input.logger,
                failureSeed: input.failureSeed,
                blockedError: error,
                workflowLabels: input.workflowLabels,
                dependencies: {
                    publishTransitionSummary: publish_1.publishTransitionSummary,
                },
            }),
        };
    }
}
async function ensureIssueWorkspace(context, issue, workflowState) {
    const branchName = (0, default_issue_workspace_manager_1.resolveIssueBranchName)(context.config.branchPrefix, issue);
    const baseBranch = (0, issue_branch_target_1.resolveIssueRunBaseBranch)(workflowState);
    if (!issue.sourceBranchName) {
        await context.linkedBranchService.ensureLinkedBranch({
            issueId: issue.id,
            branchName,
            baseBranch,
        });
    }
    const workspace = await context.issueWorkspaceManager.ensureWorkspace({
        repositoryRoot: context.cwd,
        repositoryHost: context.config.repositoryHost,
        ticketTracker: context.config.ticketTracker,
        issueId: issue.id,
        branchName,
        baseBranch,
    });
    return {
        path: workspace.path,
        branchName: workspace.branchName,
    };
}
