const Redis = require("ioredis");
const config = require(`../config/config.default.js`).config;
const REDIS_CONF = config.redis;

class RedisService {
  constructor() {
    this.redis = new Redis({
      host: REDIS_CONF.host,
      port: REDIS_CONF.port,
      password: REDIS_CONF.password,
      db: 0,
    });
  }

  /**
   * 设置字符串类型的值
   * @param {string} key 键名
   * @param {string} value 键值
   * @param {number} seconds 过期时间（秒），默认不过期
   */
  async set(key, value, seconds = 0) {
    if (typeof value === "object") {
      value = JSON.stringify(value);
    }
    if (seconds > 0) {
      return await this.redis.set(key, value, "EX", seconds);
    }
    return await this.redis.set(key, value);
  }

  /**
   * 获取字符串类型的值
   * @param {string} key 键名
   */
  async get(key) {
    return await this.redis.get(key);
  }

  /**
   * 设置对象类型的值
   * @param {string} key 键名
   * @param {object} value 键值（对象）
   * @param {number} seconds 过期时间（秒），默认不过期
   */
  async setObject(key, value, seconds = 0) {
    const hashValues = [];
    // 遍历对象的所有属性，将属性名和属性值分别存入数组
    for (const [propName, propValue] of Object.entries(value)) {
      hashValues.push(propName, JSON.stringify(propValue));
    }
    // 将数组作为参数，调用 Redis 的 HMSET 命令保存到 Redis 数据库中
   return await this.redis.hmset(key, ...hashValues);
  }

  /**
   * 获取对象类型的值
   * @param {string} key 键名
   */
  async getObject(key) {
    const hashValues = await this.redis.hgetall(key);

    // 如果没有找到对应的键，则返回 null
    if (!hashValues) {
      return null;
    }
    // 根据 Class 类型创建一个新的实例
    const obj = new Object();
    // 遍历 Redis 中存储的所有属性和值，将其赋值到新的实例上
    for (const [propName, propValue] of Object.entries(hashValues)) {
      obj[propName] = JSON.parse(propValue);
    }
    return obj;
  }

  /**
   * 删除一个或多个键
   * @param  {...string} keys 键名
   */
  async del(...keys) {
    return await this.redis.del(...keys);
  }
}

/**signleton */
exports.RedisService = new RedisService();
