"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserbotManager = void 0;
const logger_js_1 = require("../../utils/logger.js");
const file_ops_js_1 = require("../data-store/file-ops.js");
const config_js_1 = require("../../utils/config.js");
const path_1 = require("path");
const client_js_1 = require("./client.js");
const log = (0, logger_js_1.createModuleLogger)('userbot-manager');
class UserbotManager {
    clients = new Map();
    sessionsPath;
    messageHandler;
    dataStore;
    constructor(dataStore) {
        this.sessionsPath = (0, path_1.resolve)(config_js_1.config.dataDir, 'config', 'userbot-sessions.json');
        this.dataStore = dataStore;
    }
    setMessageHandler(handler) {
        this.messageHandler = handler;
        // Update existing clients
        for (const client of this.clients.values()) {
            client.onMessage(handler);
        }
    }
    /**
     * Login a new userbot. Requires interactive code input.
     * Returns session string for persistence.
     * Uses character-based apiCredentials from CharacterDNA when available.
     */
    async login(characterId, phoneNumber, codeCallback, passwordCallback) {
        log.info({ characterId, phoneNumber }, 'Logging in userbot');
        // Load character-based API credentials
        const { telegramApiId, telegramApiHash } = await this.getCharacterCredentials(characterId);
        const client = new client_js_1.UserbotClient({ characterId, phoneNumber, telegramApiId, telegramApiHash });
        if (this.messageHandler) {
            client.onMessage(this.messageHandler);
        }
        const sessionString = await client.start(codeCallback, passwordCallback);
        // Save session
        const sessions = await this.loadSessions();
        const existing = sessions.findIndex(s => s.characterId === characterId);
        const entry = {
            characterId,
            phoneNumber,
            session: sessionString,
            active: true,
            createdAt: new Date().toISOString(),
        };
        if (existing >= 0) {
            sessions[existing] = entry;
        }
        else {
            sessions.push(entry);
        }
        await this.saveSessions(sessions);
        this.clients.set(characterId, client);
        log.info({ characterId }, 'Userbot logged in and session saved');
        return { sessionString };
    }
    /**
     * Reconnect all saved sessions on startup
     */
    async reconnectAll() {
        const sessions = await this.loadSessions();
        const activeSessions = sessions.filter(s => s.active);
        log.info({ count: activeSessions.length }, 'Reconnecting saved userbot sessions');
        for (const sess of activeSessions) {
            try {
                // Load character-based API credentials (fall back to global config if unavailable)
                let telegramApiId;
                let telegramApiHash;
                try {
                    const creds = await this.getCharacterCredentials(sess.characterId);
                    telegramApiId = creds.telegramApiId;
                    telegramApiHash = creds.telegramApiHash;
                }
                catch {
                    log.warn({ characterId: sess.characterId }, 'Could not load character credentials for reconnect, falling back to global config');
                }
                const client = new client_js_1.UserbotClient({
                    characterId: sess.characterId,
                    phoneNumber: sess.phoneNumber,
                    session: sess.session,
                    telegramApiId,
                    telegramApiHash,
                });
                if (this.messageHandler) {
                    client.onMessage(this.messageHandler);
                }
                await client.reconnect();
                this.clients.set(sess.characterId, client);
                log.info({ characterId: sess.characterId }, 'Userbot reconnected');
            }
            catch (err) {
                log.error({ characterId: sess.characterId, error: err.message }, 'Failed to reconnect userbot');
            }
        }
    }
    async disconnect(characterId) {
        const client = this.clients.get(characterId);
        if (client) {
            await client.disconnect();
            this.clients.delete(characterId);
        }
        // Mark session as inactive
        const sessions = await this.loadSessions();
        const sess = sessions.find(s => s.characterId === characterId);
        if (sess) {
            sess.active = false;
            await this.saveSessions(sessions);
        }
        log.info({ characterId }, 'Userbot disconnected');
    }
    async disconnectAll() {
        for (const [characterId, client] of this.clients) {
            try {
                await client.disconnect();
            }
            catch (err) {
                log.warn({ characterId, error: err.message }, 'Error disconnecting userbot');
            }
        }
        this.clients.clear();
        log.info('All userbots disconnected');
    }
    getClient(characterId) {
        return this.clients.get(characterId);
    }
    getActiveClients() {
        return new Map(this.clients);
    }
    async getSessions() {
        return this.loadSessions();
    }
    async loadSessions() {
        try {
            const data = await (0, file_ops_js_1.readJSON)(this.sessionsPath);
            return Array.isArray(data) ? data : [];
        }
        catch {
            return [];
        }
    }
    async saveSessions(sessions) {
        await (0, file_ops_js_1.ensureDir)((0, path_1.resolve)(config_js_1.config.dataDir, 'config'));
        await (0, file_ops_js_1.atomicWriteJSON)(this.sessionsPath, sessions);
    }
    /**
     * Load character-based API credentials from DataStore.
     * Throws a meaningful error if credentials are missing.
     */
    async getCharacterCredentials(characterId) {
        if (!this.dataStore) {
            throw new Error(`API credentials for character "${characterId}" cannot be loaded: DataStore is not available`);
        }
        const character = await this.dataStore.getCharacter(characterId);
        if (!character) {
            throw new Error(`Character "${characterId}" not found. Cannot load API credentials.`);
        }
        const creds = character.apiCredentials;
        if (!creds || !creds.telegramApiId || !creds.telegramApiHash) {
            throw new Error(`API credentials are not configured for character "${characterId}" (${character.identity?.name || characterId}). ` +
                `Please set telegramApiId and telegramApiHash in the character's API credentials settings.`);
        }
        return { telegramApiId: creds.telegramApiId, telegramApiHash: creds.telegramApiHash };
    }
}
exports.UserbotManager = UserbotManager;
//# sourceMappingURL=manager.js.map