"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.recoverOpenGenerationAfterRestart = recoverOpenGenerationAfterRestart;
const dialog_1 = require("../dialog");
const dialog_generation_run_1 = require("../dialog-generation-run");
const dialog_global_registry_1 = require("../dialog-global-registry");
const dialog_instance_registry_1 = require("../dialog-instance-registry");
const log_1 = require("../log");
const persistence_1 = require("../persistence");
const persistence_errors_1 = require("../persistence-errors");
const log = (0, log_1.createLogger)('open-generation-recovery');
async function restoreDialogForOpenGenerationRecovery(dialogId) {
    const mainDialog = await (0, dialog_instance_registry_1.getOrRestoreMainDialog)(dialogId.rootId, 'running');
    if (!mainDialog) {
        return undefined;
    }
    if (dialogId.selfId === dialogId.rootId) {
        return mainDialog;
    }
    return await (0, dialog_instance_registry_1.ensureDialogLoaded)(mainDialog, dialogId, 'running');
}
async function recoverRootOpenGeneration(dialog) {
    const latest = await persistence_1.DialogPersistence.loadDialogLatest(dialog.id, dialog.status);
    const generationRunState = latest?.generationRunState;
    if (!generationRunState || generationRunState.kind !== 'open') {
        throw new Error(`open-generation recovery invariant violation: missing open generation state ` +
            `(rootId=${dialog.id.rootId}, selfId=${dialog.id.selfId})`);
    }
    await persistence_1.DialogPersistence.upsertNextStepTrigger(dialog.id, {
        triggerId: `open-generation-recovery:${dialog.id.selfId}:${generationRunState.course}:${generationRunState.genseq}`,
        kind: 'open_generation_recovery',
        course: generationRunState.course,
        genseq: generationRunState.genseq,
        createdAt: generationRunState.openedAt,
    }, dialog.status);
    dialog_global_registry_1.globalDialogRegistry.queueRootDrive(dialog.id.rootId, {
        source: 'restart_recovery',
        reason: 'persisted_open_generation_recovery',
    });
}
async function recoverSideDialogOpenGeneration(dialog) {
    const latest = await persistence_1.DialogPersistence.loadDialogLatest(dialog.id, dialog.status);
    if (latest) {
        await persistence_1.DialogPersistence.syncWakeQueueForDialogLatest(dialog.id, latest, dialog.status);
    }
    else {
        await persistence_1.DialogPersistence.removeWakeQueueEntriesForDialog(dialog.id, dialog.status);
    }
    const rootId = new dialog_1.DialogID(dialog.id.rootId);
    const rootHasPendingNextStepTriggers = await persistence_1.DialogPersistence.hasPendingNextStepTriggers(rootId, dialog.status);
    const wakeQueueEntries = await persistence_1.DialogPersistence.loadWakeQueueEntries(rootId, dialog.status);
    if (rootHasPendingNextStepTriggers || wakeQueueEntries.length > 0) {
        dialog_global_registry_1.globalDialogRegistry.queueRootDrive(dialog.id.rootId, {
            source: 'restart_recovery',
            reason: 'sideDialog_open_generation_recovered_more_work',
        });
    }
    else {
        dialog_global_registry_1.globalDialogRegistry.clearRootDriveQueue(dialog.id.rootId, {
            source: 'restart_recovery',
            reason: 'sideDialog_open_generation_recovered_idle',
        });
    }
}
async function recoverOpenGenerationAfterRestart() {
    const rootDialogIds = await persistence_1.DialogPersistence.listMainDialogIds('running');
    const dialogIds = [];
    for (const rootDialogId of rootDialogIds) {
        dialogIds.push(rootDialogId);
        const wakeQueueTargetDialogIds = await persistence_1.DialogPersistence.loadWakeQueueTargetDialogIds(rootDialogId, 'running');
        dialogIds.push(...wakeQueueTargetDialogIds);
    }
    const recoveredRootIds = new Set();
    const recoveredDialogKeys = new Set();
    for (const dialogId of dialogIds) {
        let latest;
        try {
            latest = await persistence_1.DialogPersistence.loadDialogLatest(dialogId, 'running');
        }
        catch (error) {
            if (!(0, persistence_errors_1.findDomindsPersistenceFileError)(error)) {
                throw error;
            }
            log.warn('Skipping malformed dialog during open-generation restart recovery', error, {
                dialogId: dialogId.valueOf(),
            });
            continue;
        }
        if ((0, dialog_generation_run_1.getRecoverableGenerationRunState)(latest) === undefined) {
            continue;
        }
        try {
            const dialog = await restoreDialogForOpenGenerationRecovery(dialogId);
            if (!dialog) {
                log.warn('Open-generation restart recovery could not restore dialog', undefined, {
                    rootId: dialogId.rootId,
                    selfId: dialogId.selfId,
                });
                continue;
            }
            const dialogKey = dialog.id.key();
            if (recoveredDialogKeys.has(dialogKey)) {
                continue;
            }
            recoveredDialogKeys.add(dialogKey);
            if (dialog.id.selfId === dialog.id.rootId) {
                if (recoveredRootIds.has(dialog.id.rootId)) {
                    continue;
                }
                recoveredRootIds.add(dialog.id.rootId);
                await recoverRootOpenGeneration(dialog);
            }
            else {
                await recoverSideDialogOpenGeneration(dialog);
            }
        }
        catch (error) {
            log.error('Failed to recover open generation after restart', error, {
                rootId: dialogId.rootId,
                selfId: dialogId.selfId,
            });
        }
    }
}
