import { logger } from '@goodgo/logger';
import Redis from 'ioredis';

import { appConfig } from './app.config';

// EN: Redis connection instance
// VI: Instance kết nối Redis
let redisClient: Redis | undefined;

/**
 * EN: Get or create Redis client
 * VI: Lấy hoặc tạo Redis client
 */
export const getRedisClient = (): Redis => {
    if (!redisClient) {
        redisClient = new Redis(appConfig.redisUrl, {
            // EN: Connection options for stability
            // VI: Tùy chọn kết nối để ổn định
            enableOfflineQueue: true,
            connectTimeout: 10000, // 10s timeout
            keepAlive: 30000, // Keep connection alive every 30s

            // EN: Retry strategy with exponential backoff
            // VI: Chiến lược thử lại với exponential backoff
            retryStrategy(times) {
                if (times > 10) {
                    // EN: Stop retrying after 10 attempts
                    // VI: Dừng thử lại sau 10 lần
                    logger.error('Redis max retries reached, giving up');
                    return null;
                }
                const delay = Math.min(times * 100, 3000);
                return delay;
            },

            // EN: Max retries per request
            // VI: Số lần thử lại tối đa mỗi request
            maxRetriesPerRequest: 3,

            // EN: Reconnect on error
            // VI: Tự động kết nối lại khi lỗi
            reconnectOnError(err) {
                const targetErrors = ['READONLY', 'ECONNRESET', 'EPIPE'];
                return targetErrors.some(targetError => err.message.includes(targetError));
            },
        });

        redisClient.on('error', (err) => {
            logger.error('Redis connection error', { error: err.message });
        });

        redisClient.on('connect', () => {
            logger.info('Redis connected successfully');
        });

        redisClient.on('ready', () => {
            logger.info('Redis ready to accept commands');
        });

        redisClient.on('reconnecting', () => {
            logger.warn('Redis reconnecting...');
        });
    }

    return redisClient;
};
