/**
 * Redis Client - опциональное подключение
 * Если Redis недоступен, работает без БД
 */

let redisClient = null;
let redisAvailable = false;
let redisClientInstance = null; // Для connect-redis

async function initRedis() {
  // Проверяем, нужно ли использовать Redis
  const useRedis = process.env.USE_REDIS === 'true' || process.env.REDIS_URL;
  
  if (!useRedis) {
    console.log('📦 Redis отключен (USE_REDIS=false или REDIS_URL не установлен)');
    return;
  }

  try {
    const redis = require('redis');
    const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
    
    redisClient = redis.createClient({
      url: redisUrl,
      socket: {
        reconnectStrategy: (retries) => {
          if (retries > 10) {
            console.log('⚠️  Redis: слишком много попыток переподключения, отключаемся');
            redisAvailable = false;
            return false; // Остановить переподключение
          }
          return Math.min(retries * 100, 3000);
        }
      }
    });

    redisClient.on('error', (err) => {
      console.error('❌ Redis ошибка:', err.message);
      redisAvailable = false;
    });

    redisClient.on('connect', () => {
      console.log('🔌 Redis: подключение установлено');
      redisAvailable = true;
    });

    redisClient.on('ready', () => {
      console.log('✅ Redis: готов к работе');
      redisAvailable = true;
    });

    redisClient.on('end', () => {
      console.log('🔌 Redis: соединение закрыто');
      redisAvailable = false;
    });

    await redisClient.connect();
    redisClientInstance = redisClient; // Сохраняем для connect-redis
    redisAvailable = true;
    console.log('✅ Redis подключен успешно');
    
    // Экспортируем клиент для connect-redis
    module.exports.redisClientInstance = redisClient;
  } catch (error) {
    console.warn('⚠️  Redis недоступен, работаем без БД:', error.message);
    redisAvailable = false;
    redisClient = null;
  }
}

async function closeRedis() {
  if (redisClient && redisAvailable) {
    try {
      await redisClient.quit();
      console.log('🔌 Redis: соединение закрыто');
    } catch (error) {
      console.error('Ошибка при закрытии Redis:', error);
    }
  }
}

// Проверка доступности Redis
function isRedisAvailable() {
  return redisAvailable && redisClient !== null;
}

// Получить значение
async function get(key) {
  if (!isRedisAvailable()) return null;
  try {
    return await redisClient.get(key);
  } catch (error) {
    console.error('Redis get error:', error);
    return null;
  }
}

// Установить значение
async function set(key, value, expireSeconds = null) {
  if (!isRedisAvailable()) return false;
  try {
    if (expireSeconds) {
      await redisClient.setEx(key, expireSeconds, value);
    } else {
      await redisClient.set(key, value);
    }
    return true;
  } catch (error) {
    console.error('Redis set error:', error);
    return false;
  }
}

// Удалить ключ
async function del(key) {
  if (!isRedisAvailable()) return false;
  try {
    await redisClient.del(key);
    return true;
  } catch (error) {
    console.error('Redis del error:', error);
    return false;
  }
}

// Получить все ключи по паттерну
async function keys(pattern) {
  if (!isRedisAvailable()) return [];
  try {
    return await redisClient.keys(pattern);
  } catch (error) {
    console.error('Redis keys error:', error);
    return [];
  }
}

// Получить хеш
async function hGet(key, field) {
  if (!isRedisAvailable()) return null;
  try {
    return await redisClient.hGet(key, field);
  } catch (error) {
    console.error('Redis hGet error:', error);
    return null;
  }
}

// Установить поле в хеше
async function hSet(key, field, value) {
  if (!isRedisAvailable()) return false;
  try {
    await redisClient.hSet(key, field, value);
    return true;
  } catch (error) {
    console.error('Redis hSet error:', error);
    return false;
  }
}

// Получить все поля хеша
async function hGetAll(key) {
  if (!isRedisAvailable()) return {};
  try {
    return await redisClient.hGetAll(key);
  } catch (error) {
    console.error('Redis hGetAll error:', error);
    return {};
  }
}

// Увеличить значение
async function incr(key) {
  if (!isRedisAvailable()) return 0;
  try {
    return await redisClient.incr(key);
  } catch (error) {
    console.error('Redis incr error:', error);
    return 0;
  }
}

// Получить список (добавить в конец)
async function rPush(key, ...values) {
  if (!isRedisAvailable()) return 0;
  try {
    return await redisClient.rPush(key, values);
  } catch (error) {
    console.error('Redis rPush error:', error);
    return 0;
  }
}

// Получить элементы списка
async function lRange(key, start, stop) {
  if (!isRedisAvailable()) return [];
  try {
    return await redisClient.lRange(key, start, stop);
  } catch (error) {
    console.error('Redis lRange error:', error);
    return [];
  }
}

// Получить клиент Redis для connect-redis
function getRedisClient() {
  return redisClientInstance;
}

module.exports = {
  initRedis,
  closeRedis,
  isRedisAvailable,
  getRedisClient,
  get,
  set,
  del,
  keys,
  hGet,
  hSet,
  hGetAll,
  incr,
  rPush,
  lRange
};
