import { createClient, RedisClientType } from 'redis';
import { logger } from '../utils/logger';

class RedisService {
  private client: RedisClientType;
  private isConnected: boolean = false;

  constructor() {
    this.client = createClient({
      url: process.env.REDIS_URL || 'redis://localhost:6379'
    });

    this.client.on('error', (err) => {
      logger.error(`[RedisService] Error: ${err.message}`);
      this.isConnected = false;
    });

    this.client.on('connect', () => {
      logger.info('[RedisService] Connected to Redis');
      this.isConnected = true;
    });

    this.client.on('end', () => {
      logger.info('[RedisService] Disconnected from Redis');
      this.isConnected = false;
    });

    this.connect();
  }

  private async connect() {
    try {
      await this.client.connect();
      this.isConnected = true;
    } catch (error) {
      logger.error(`[RedisService] Failed to connect: ${(error as any).message}`);
      this.isConnected = false;
    }
  }

  /**
   * 检查Redis连接状态
   */
  public async checkConnection(): Promise<boolean> {
    if (!this.isConnected) {
      await this.connect();
    }
    return this.isConnected;
  }

  /**
   * 设置缓存
   */
  public async set(key: string, value: any, expireSeconds?: number): Promise<boolean> {
    try {
      if (!await this.checkConnection()) {
        return false;
      }

      const stringValue = typeof value === 'string' ? value : JSON.stringify(value);
      
      if (expireSeconds) {
        await this.client.set(key, stringValue, { EX: expireSeconds });
      } else {
        await this.client.set(key, stringValue);
      }

      return true;
    } catch (error) {
      logger.warn(`[RedisService] Failed to set key ${key}: ${(error as any).message}`);
      return false;
    }
  }

  /**
   * 获取缓存
   */
  public async get(key: string): Promise<any> {
    try {
      if (!await this.checkConnection()) {
        return null;
      }

      const value = await this.client.get(key);
      if (!value) {
        return null;
      }

      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      logger.warn(`[RedisService] Failed to get key ${key}: ${(error as any).message}`);
      return null;
    }
  }

  /**
   * 删除缓存
   */
  public async del(key: string): Promise<boolean> {
    try {
      if (!await this.checkConnection()) {
        return false;
      }

      await this.client.del(key);
      return true;
    } catch (error) {
      logger.warn(`[RedisService] Failed to delete key ${key}: ${(error as any).message}`);
      return false;
    }
  }

  /**
   * 批量删除缓存
   */
  public async delMultiple(keys: string[]): Promise<boolean> {
    try {
      if (!await this.checkConnection() || keys.length === 0) {
        return false;
      }

      await this.client.del(keys);
      return true;
    } catch (error) {
      logger.warn(`[RedisService] Failed to delete multiple keys: ${(error as any).message}`);
      return false;
    }
  }

  /**
   * 设置哈希表字段
   */
  public async hset(key: string, field: string, value: any): Promise<boolean> {
    try {
      if (!await this.checkConnection()) {
        return false;
      }

      const stringValue = typeof value === 'string' ? value : JSON.stringify(value);
      await this.client.hSet(key, field, stringValue);
      return true;
    } catch (error) {
      logger.warn(`[RedisService] Failed to hset key ${key}: ${(error as any).message}`);
      return false;
    }
  }

  /**
   * 获取哈希表字段
   */
  public async hget(key: string, field: string): Promise<any> {
    try {
      if (!await this.checkConnection()) {
        return null;
      }

      const value = await this.client.hGet(key, field);
      if (!value) {
        return null;
      }

      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      logger.warn(`[RedisService] Failed to hget key ${key}: ${(error as any).message}`);
      return null;
    }
  }

  /**
   * 获取哈希表所有字段
   */
  public async hgetall(key: string): Promise<Record<string, any>> {
    try {
      if (!await this.checkConnection()) {
        return {};
      }

      const values = await this.client.hGetAll(key);
      const result: Record<string, any> = {};

      for (const [field, value] of Object.entries(values)) {
        try {
          result[field] = JSON.parse(value);
        } catch {
          result[field] = value;
        }
      }

      return result;
    } catch (error) {
      logger.warn(`[RedisService] Failed to hgetall key ${key}: ${(error as any).message}`);
      return {};
    }
  }

  /**
   * 增加计数器
   */
  public async incr(key: string): Promise<number | null> {
    try {
      if (!await this.checkConnection()) {
        return null;
      }

      return await this.client.incr(key);
    } catch (error) {
      logger.warn(`[RedisService] Failed to incr key ${key}: ${(error as any).message}`);
      return null;
    }
  }

  /**
   * 根据模式删除缓存
   */
  public async deletePattern(pattern: string): Promise<boolean> {
    try {
      if (!await this.checkConnection()) {
        return false;
      }

      const keys = await this.client.keys(pattern);
      if (keys.length > 0) {
        await this.client.del(keys);
      }
      return true;
    } catch (error) {
      logger.warn(`[RedisService] Failed to delete pattern ${pattern}: ${(error as any).message}`);
      return false;
    }
  }

  /**
   * 关闭连接
   */
  public async close(): Promise<void> {
    try {
      await this.client.disconnect();
      this.isConnected = false;
    } catch (error) {
      logger.warn(`[RedisService] Failed to close connection: ${(error as any).message}`);
    }
  }
}

export default new RedisService();
