"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalGatewayRegistry = void 0;
const nanoid_1 = require("nanoid");
const local_gateway_1 = require("./local-gateway");
const INITIAL_GRACE_MS = 10_000;
const MAX_GRACE_MS = 120_000;
const PAIRING_TOKEN_TTL_MS = 5 * 60 * 1000;
class LocalGatewayRegistry {
    constructor() {
        this.userGateways = new Map();
        this.apiKeyToUserId = new Map();
    }
    generateUniqueKey(prefix) {
        let key;
        do {
            key = `${prefix}_${(0, nanoid_1.nanoid)(32)}`;
        } while (this.apiKeyToUserId.has(key));
        return key;
    }
    getOrCreate(userId) {
        if (!this.userGateways.has(userId)) {
            this.userGateways.set(userId, {
                gateway: new local_gateway_1.LocalGateway(),
                pairingToken: null,
                activeSessionKey: null,
                disconnectTimer: null,
                reconnectCount: 0,
            });
        }
        return this.userGateways.get(userId);
    }
    getUserIdForApiKey(key) {
        return this.apiKeyToUserId.get(key);
    }
    generatePairingToken(userId) {
        const state = this.getOrCreate(userId);
        if (state.activeSessionKey)
            return state.activeSessionKey;
        const existing = this.getPairingToken(userId);
        if (existing)
            return existing;
        const token = this.generateUniqueKey('gw');
        state.pairingToken = { token, createdAt: Date.now() };
        this.apiKeyToUserId.set(token, userId);
        return token;
    }
    getPairingToken(userId) {
        const state = this.userGateways.get(userId);
        if (!state?.pairingToken)
            return null;
        if (Date.now() - state.pairingToken.createdAt > PAIRING_TOKEN_TTL_MS) {
            this.apiKeyToUserId.delete(state.pairingToken.token);
            state.pairingToken = null;
            return null;
        }
        return state.pairingToken.token;
    }
    consumePairingToken(userId, token) {
        const state = this.userGateways.get(userId);
        const valid = this.getPairingToken(userId);
        if (!state || !valid || valid !== token)
            return null;
        this.apiKeyToUserId.delete(token);
        state.pairingToken = null;
        const sessionKey = this.generateUniqueKey('sess');
        state.activeSessionKey = sessionKey;
        this.apiKeyToUserId.set(sessionKey, userId);
        return sessionKey;
    }
    getActiveSessionKey(userId) {
        return this.userGateways.get(userId)?.activeSessionKey ?? null;
    }
    clearActiveSessionKey(userId) {
        const state = this.userGateways.get(userId);
        if (!state?.activeSessionKey)
            return;
        this.apiKeyToUserId.delete(state.activeSessionKey);
        state.activeSessionKey = null;
    }
    getGateway(userId) {
        return this.getOrCreate(userId).gateway;
    }
    findGateway(userId) {
        return this.userGateways.get(userId)?.gateway;
    }
    initGateway(userId, data) {
        const state = this.getOrCreate(userId);
        this.clearDisconnectTimer(userId);
        state.reconnectCount = 0;
        state.gateway.init(data);
    }
    resolveGatewayRequest(userId, requestId, result, error) {
        return this.userGateways.get(userId)?.gateway.resolveRequest(requestId, result, error) ?? false;
    }
    disconnectGateway(userId) {
        this.userGateways.get(userId)?.gateway.disconnect();
    }
    getGatewayStatus(userId) {
        return (this.userGateways.get(userId)?.gateway.getStatus() ?? {
            connected: false,
            connectedAt: null,
            directory: null,
            hostIdentifier: null,
            toolCategories: [],
        });
    }
    startDisconnectTimer(userId, onDisconnect) {
        const state = this.getOrCreate(userId);
        this.clearDisconnectTimer(userId);
        const graceMs = Math.min(INITIAL_GRACE_MS * Math.pow(2, state.reconnectCount), MAX_GRACE_MS);
        state.reconnectCount++;
        state.disconnectTimer = setTimeout(() => {
            state.disconnectTimer = null;
            this.disconnectGateway(userId);
            onDisconnect();
        }, graceMs);
    }
    clearDisconnectTimer(userId) {
        const state = this.userGateways.get(userId);
        if (!state?.disconnectTimer)
            return;
        clearTimeout(state.disconnectTimer);
        state.disconnectTimer = null;
    }
    disconnectAll() {
        for (const state of this.userGateways.values()) {
            if (state.disconnectTimer)
                clearTimeout(state.disconnectTimer);
            state.gateway.disconnect();
        }
        this.userGateways.clear();
        this.apiKeyToUserId.clear();
    }
}
exports.LocalGatewayRegistry = LocalGatewayRegistry;
//# sourceMappingURL=local-gateway-registry.js.map