"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisService = void 0;
const redis_1 = require("redis");
const Logger_1 = require("./Logger");
class RedisService {
    constructor() {
        this.isConnected = false;
        const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
        this.client = (0, redis_1.createClient)({
            url: redisUrl,
            socket: {
                reconnectStrategy: (retries) => Math.min(retries * 50, 500)
            }
        });
        this.client.on('error', (err) => {
            (0, Logger_1.logError)('Redis connection error', err);
            this.isConnected = false;
        });
        this.client.on('connect', () => {
            (0, Logger_1.logStartup)('Redis client connected successfully');
            this.isConnected = true;
        });
        this.client.on('disconnect', () => {
            (0, Logger_1.logWarning)('Redis client disconnected');
            this.isConnected = false;
        });
    }
    static getInstance() {
        if (!RedisService.instance) {
            RedisService.instance = new RedisService();
        }
        return RedisService.instance;
    }
    async connect() {
        try {
            if (!this.isConnected) {
                await this.client.connect();
            }
        }
        catch (error) {
            (0, Logger_1.logError)('Failed to connect to Redis', error);
            throw error;
        }
    }
    async disconnect() {
        try {
            if (this.isConnected) {
                await this.client.disconnect();
            }
        }
        catch (error) {
            (0, Logger_1.logError)('Failed to disconnect from Redis', error);
        }
    }
    async setActiveChat(chatId, chatData) {
        try {
            const key = `active_chat:${chatId}`;
            await this.client.hSet(key, {
                chatId: chatData.chatId,
                participants: JSON.stringify(chatData.participants),
                lastActivity: chatData.lastActivity.toISOString(),
                messageCount: chatData.messageCount.toString(),
                chatType: chatData.chatType,
                gameId: chatData.gameId || '',
                name: chatData.name || ''
            });
            // Set expiration for 1 hour of inactivity
            await this.client.expire(key, 3600);
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to set active chat ${chatId}`, error);
        }
    }
    async getActiveChat(chatId) {
        try {
            const key = `active_chat:${chatId}`;
            const data = await this.client.hGetAll(key);
            if (!data.chatId) {
                return null;
            }
            return {
                chatId: data.chatId,
                participants: JSON.parse(data.participants),
                lastActivity: new Date(data.lastActivity),
                messageCount: parseInt(data.messageCount, 10),
                chatType: data.chatType,
                gameId: data.gameId || undefined,
                name: data.name || undefined
            };
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to get active chat ${chatId}`, error);
            return null;
        }
    }
    async removeActiveChat(chatId) {
        try {
            const key = `active_chat:${chatId}`;
            await this.client.del(key);
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to remove active chat ${chatId}`, error);
        }
    }
    async getAllActiveChats() {
        try {
            const pattern = 'active_chat:*';
            const keys = await this.client.keys(pattern);
            const chats = [];
            for (const key of keys) {
                const data = await this.client.hGetAll(key);
                if (data.chatId) {
                    chats.push({
                        chatId: data.chatId,
                        participants: JSON.parse(data.participants),
                        lastActivity: new Date(data.lastActivity),
                        messageCount: parseInt(data.messageCount, 10),
                        chatType: data.chatType,
                        gameId: data.gameId || undefined,
                        name: data.name || undefined
                    });
                }
            }
            return chats;
        }
        catch (error) {
            (0, Logger_1.logError)('Failed to get all active chats', error);
            return [];
        }
    }
    async setActiveUser(userId, userData) {
        try {
            const key = `active_user:${userId}`;
            await this.client.hSet(key, {
                userId: userData.userId,
                activeChatIds: JSON.stringify(userData.activeChatIds),
                lastActivity: userData.lastActivity.toISOString(),
                isOnline: userData.isOnline.toString()
            });
            // Set expiration for 2 hours
            await this.client.expire(key, 7200);
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to set active user ${userId}`, error);
        }
    }
    async getActiveUser(userId) {
        try {
            const key = `active_user:${userId}`;
            const data = await this.client.hGetAll(key);
            if (!data.userId) {
                return null;
            }
            return {
                userId: data.userId,
                activeChatIds: JSON.parse(data.activeChatIds),
                lastActivity: new Date(data.lastActivity),
                isOnline: data.isOnline === 'true'
            };
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to get active user ${userId}`, error);
            return null;
        }
    }
    async removeActiveUser(userId) {
        try {
            const key = `active_user:${userId}`;
            await this.client.del(key);
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to remove active user ${userId}`, error);
        }
    }
    async addUserToChat(userId, chatId) {
        try {
            const userData = await this.getActiveUser(userId) || {
                userId,
                activeChatIds: [],
                lastActivity: new Date(),
                isOnline: true
            };
            if (!userData.activeChatIds.includes(chatId)) {
                userData.activeChatIds.push(chatId);
                userData.lastActivity = new Date();
                await this.setActiveUser(userId, userData);
            }
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to add user ${userId} to chat ${chatId}`, error);
        }
    }
    async removeUserFromChat(userId, chatId) {
        try {
            const userData = await this.getActiveUser(userId);
            if (userData) {
                userData.activeChatIds = userData.activeChatIds.filter(id => id !== chatId);
                userData.lastActivity = new Date();
                await this.setActiveUser(userId, userData);
            }
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to remove user ${userId} from chat ${chatId}`, error);
        }
    }
    async getUserActiveChats(userId) {
        try {
            const userData = await this.getActiveUser(userId);
            return userData?.activeChatIds || [];
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to get active chats for user ${userId}`, error);
            return [];
        }
    }
    async updateChatActivity(chatId, messageCount) {
        try {
            const chatData = await this.getActiveChat(chatId);
            if (chatData) {
                chatData.lastActivity = new Date();
                if (messageCount !== undefined) {
                    chatData.messageCount = messageCount;
                }
                await this.setActiveChat(chatId, chatData);
            }
        }
        catch (error) {
            (0, Logger_1.logError)(`Failed to update chat activity ${chatId}`, error);
        }
    }
    async getInactiveChats(inactivityMinutes) {
        try {
            const cutoffTime = new Date(Date.now() - inactivityMinutes * 60 * 1000);
            const allChats = await this.getAllActiveChats();
            return allChats
                .filter(chat => chat.lastActivity < cutoffTime)
                .map(chat => chat.chatId);
        }
        catch (error) {
            (0, Logger_1.logError)('Failed to get inactive chats', error);
            return [];
        }
    }
    async cleanupInactiveChats(inactivityMinutes) {
        try {
            const inactiveChats = await this.getInactiveChats(inactivityMinutes);
            for (const chatId of inactiveChats) {
                await this.removeActiveChat(chatId);
            }
            return inactiveChats;
        }
        catch (error) {
            (0, Logger_1.logError)('Failed to cleanup inactive chats', error);
            return [];
        }
    }
    async ping() {
        try {
            const result = await this.client.ping();
            return result === 'PONG';
        }
        catch (error) {
            (0, Logger_1.logError)('Redis ping failed', error);
            return false;
        }
    }
    isRedisConnected() {
        return this.isConnected;
    }
}
exports.RedisService = RedisService;
//# sourceMappingURL=RedisService.js.map