"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssistantApplicationService = void 0;
/**
 * Thin application service for assistant session lifecycle and in-memory state.
 * Routes/controllers should avoid direct Map manipulation.
 */
class AssistantApplicationService {
    constructor() {
        this.sessions = new Map();
    }
    getSession(sessionId) {
        return this.sessions.get(sessionId);
    }
    setSession(sessionId, session) {
        this.sessions.set(sessionId, session);
    }
    deleteSession(sessionId) {
        return this.sessions.delete(sessionId);
    }
    entries() {
        return this.sessions.entries();
    }
    touchSession(sessionId) {
        const session = this.sessions.get(sessionId);
        if (!session)
            return undefined;
        session.lastActivityAt = Date.now();
        return session;
    }
    addSseClient(sessionId, client) {
        const session = this.touchSession(sessionId);
        if (!session)
            return undefined;
        session.sseClients.push(client);
        return session;
    }
    removeSseClient(sessionId, client) {
        const session = this.sessions.get(sessionId);
        if (!session)
            return undefined;
        const idx = session.sseClients.indexOf(client);
        if (idx !== -1) {
            session.sseClients.splice(idx, 1);
        }
        session.lastActivityAt = Date.now();
        return session;
    }
    markSessionFailed(sessionId, errorMessage) {
        const session = this.sessions.get(sessionId);
        if (!session)
            return undefined;
        session.status = 'failed';
        session.error = errorMessage;
        session.lastActivityAt = Date.now();
        return session;
    }
    cleanupIdleSessions(options) {
        const now = options.now ?? Date.now();
        const removed = [];
        for (const [sessionId, session] of this.sessions.entries()) {
            const idle = now - (session.lastActivityAt || session.createdAt);
            const isTerminal = session.status === 'completed' ||
                session.status === 'failed' ||
                session.status === 'quota_exceeded';
            const isAbandonedNonTerminal = (session.status === 'pending' || session.status === 'running') &&
                session.sseClients.length === 0;
            if ((isTerminal && idle > options.terminalMaxIdleMs) ||
                (isAbandonedNonTerminal && idle > options.nonTerminalMaxIdleMs)) {
                if (options.shouldCleanup?.(sessionId, session, {
                    now,
                    idleMs: idle,
                    isTerminal,
                    isAbandonedNonTerminal,
                }) === false) {
                    continue;
                }
                options.onCleanup?.(sessionId, session);
                this.sessions.delete(sessionId);
                removed.push(sessionId);
            }
        }
        return removed;
    }
}
exports.AssistantApplicationService = AssistantApplicationService;
//# sourceMappingURL=assistantApplicationService.js.map