"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startExecutionOwnershipHeartbeat = startExecutionOwnershipHeartbeat;
const canonical_workflow_state_1 = require("../../comments/canonical-workflow-state");
const publisher_shared_1 = require("../../workflows/publisher-shared");
const execution_ownership_1 = require("../execution-ownership");
const publisher_factory_1 = require("./publisher-factory");
const shared_1 = require("./shared");
function startExecutionOwnershipHeartbeat(input) {
    let stopped = false;
    let suspended = false;
    let writeChain = Promise.resolve();
    let timer = null;
    const expectedAssignee = (0, shared_1.resolveSingleAssignee)(input.claimedIssue.originalIssue);
    const runHeartbeatPass = () => {
        writeChain = writeChain
            .then(async () => {
            if (stopped) {
                return;
            }
            const [latestIssue, comments] = await Promise.all([
                input.context.freshTicketTracker.getIssue(input.claimedIssue.originalIssue.id),
                (0, shared_1.loadSortedIssueComments)(input.context.freshTicketTracker, input.claimedIssue.originalIssue.id, {
                    timeline: "issue-only",
                }),
            ]);
            const workflowStateResolution = (0, canonical_workflow_state_1.resolveCanonicalWorkflowStateComment)(comments, input.responseLanguage);
            if (workflowStateResolution.kind !== "found") {
                return;
            }
            const workflowState = workflowStateResolution.workflowState;
            if (latestIssue.workflowState.status !==
                input.claimedIssue.aiRunningSnapshot.status ||
                !(0, execution_ownership_1.isExecutionOwnershipOwnedBy)(workflowState.executionOwnership, input.claimedIssue.executionOwnership) ||
                (expectedAssignee !== null &&
                    (latestIssue.assignees.length !== 1 ||
                        latestIssue.assignees[0] !== expectedAssignee))) {
                return;
            }
            if (stopped) {
                return;
            }
            const nextOwnership = (0, execution_ownership_1.refreshExecutionOwnership)(input.claimedIssue.executionOwnership, input.context.config.pollIntervalSec);
            const publication = await (0, publisher_factory_1.createRunWorkflowPublisher)({
                ...input.context,
                ticketTracker: input.context.freshTicketTracker,
            }).publishWorkflow({
                target: {
                    kind: "existing_issue",
                    issueId: input.claimedIssue.originalIssue.id,
                    preloadedIssue: latestIssue,
                },
                workflowState: (0, execution_ownership_1.withExecutionOwnership)(workflowState, nextOwnership),
                publishPrecondition: {
                    expectedCanonicalCommentId: workflowStateResolution.comment.id,
                    expectedLastScannedCommentCursor: workflowStateResolution.workflowState.lastScannedCommentCursor ??
                        null,
                    expectedExecutionOwner: input.claimedIssue.executionOwnership,
                },
                commentCursorPolicy: {
                    mode: publisher_shared_1.WORKFLOW_COMMENT_CURSOR_POLICY_MODES.preserve,
                },
                responseLanguage: input.responseLanguage,
            });
            if (publication.currentWorkflowState !== null &&
                (0, execution_ownership_1.isExecutionOwnershipOwnedBy)(publication.currentWorkflowState.executionOwnership, nextOwnership)) {
                input.claimedIssue.executionOwnership = nextOwnership;
            }
        })
            .catch(() => { });
    };
    const clearHeartbeatTimer = () => {
        if (timer !== null) {
            clearInterval(timer);
            timer = null;
        }
    };
    const scheduleHeartbeat = () => {
        if (stopped || suspended || timer !== null) {
            return;
        }
        timer = setInterval(runHeartbeatPass, input.context.config.pollIntervalSec * 1_000);
        timer.unref?.();
    };
    scheduleHeartbeat();
    return {
        async suspend() {
            suspended = true;
            clearHeartbeatTimer();
            await writeChain;
        },
        resume() {
            if (stopped) {
                return;
            }
            suspended = false;
            scheduleHeartbeat();
        },
        async stop() {
            stopped = true;
            suspended = true;
            clearHeartbeatTimer();
            await writeChain;
        },
    };
}
