import Redis from 'ioredis';
import debug from 'debug';
import type { Answer } from '@/client/mobile/components/Exam/types';

const log = debug('socket:redis');

export class RedisService {
  private client: Redis;
  private isConnected = false;

  constructor() {
    this.client = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');

    this.client.on('error', (err: Error) => {
      log('Redis Client Error:', err);
    });

    this.client.on('connect', () => {
      log('Redis Client Connected');
      this.isConnected = true;
    });

    this.client.on('disconnect', () => {
      log('Redis Client Disconnected');
      this.isConnected = false;
    });
  }

  // 考试相关的方法
  async storeCurrentQuestion(roomId: string, question: { date: string; price: string; gain?: number }) {
    const key = `exam:${roomId}:current_question`;
    await this.client.hset(key, {
      date: question.date,
      price: question.price,
      gain: question.gain ? question.gain.toString() : '0',
      updated_at: new Date().toISOString(),
    });
    // 设置过期时间，24小时
    await this.client.expire(key, 24 * 60 * 60);
  }

  async getCurrentQuestion(roomId: string): Promise<{ date: string; price: string; gain?: number } | null> {
    const key = `exam:${roomId}:current_question`;
    const data = await this.client.hgetall(key);
    
    if (!data.date || !data.price) {
      return null;
    }

    return {
      date: data.date,
      price: data.price,
      gain: data.gain ? parseFloat(data.gain) : undefined,
    };
  }

  async storePrice(roomId: string, date: string, price: string) {
    const key = `exam:${roomId}:prices`;
    await this.client.hset(key, date, price);
    // 设置过期时间，7天
    await this.client.expire(key, 7 * 24 * 60 * 60);
  }

  async getPrice(roomId: string, date: string): Promise<string | null> {
    const key = `exam:${roomId}:prices`;
    return await this.client.hget(key, date);
  }

  async getAllPrices(roomId: string): Promise<Record<string, number>> {
    const key = `exam:${roomId}:prices`;
    const prices = await this.client.hgetall(key);
    
    const result: Record<string, number> = {};
    for (const [date, price] of Object.entries(prices)) {
      const numPrice = parseFloat(price);
      if (!isNaN(numPrice)) {
        result[date] = numPrice;
      }
    }
    
    return result;
  }

  async storeAnswer(
    roomId: string,
    userId: number,
    questionId: string,
    answer: Answer
  ) {
    const key = `exam:${roomId}:answers:${userId}:${questionId}`;
    // 确保username字段被正确存储
    const answerWithUsername = {
      ...answer,
      username: answer.username || ''
    };
    await this.client.hset(key, 'data', JSON.stringify(answerWithUsername));
    // 设置过期时间，30天
    await this.client.expire(key, 30 * 24 * 60 * 60);
  }

  async getAnswers(roomId: string, questionId?: string): Promise<Answer[]> {
    const pattern = questionId
      ? `exam:${roomId}:answers:*:${questionId}`
      : `exam:${roomId}:answers:*`;
    
    const keys = await this.client.keys(pattern);
    const answers: Answer[] = [];

    for (const key of keys) {
      const data = await this.client.hget(key, 'data');
      if (data) {
        try {
          const answer = JSON.parse(data);
          // 从 key 中提取 userId
          const parts = key.split(':');
          const userId = parts[3];
          answers.push({
            ...answer,
            userId,
          });
        } catch (error) {
          log('解析答案数据失败:', error);
        }
      }
    }

    return answers;
  }

  async getUserAnswers(roomId: string, userId: number): Promise<Answer[]> {
    const pattern = `exam:${roomId}:answers:${userId}:*`;
    const keys = await this.client.keys(pattern);
    const answers: Answer[] = [];

    for (const key of keys) {
      const data = await this.client.hget(key, 'data');
      if (data) {
        try {
          const answer = JSON.parse(data);
          answers.push(answer);
        } catch (error) {
          log('解析用户答案数据失败:', error);
        }
      }
    }

    return answers;
  }

  async cleanupRoomData(roomId: string, questionId?: string) {
    if (questionId) {
      // 清理特定问题的数据
      const pattern = `exam:${roomId}:${questionId}:*`;
      const keys = await this.client.keys(pattern);
      
      if (keys.length > 0) {
        await this.client.del(keys);
      }
    } else {
      // 清理整个房间的数据
      const pattern = `exam:${roomId}:*`;
      const keys = await this.client.keys(pattern);
      
      if (keys.length > 0) {
        await this.client.del(keys);
      }
    }
  }

  // 房间成员管理
  async addRoomMember(roomId: string, userId: number, username: string) {
    const key = `exam:${roomId}:members`;
    await this.client.hset(key, userId.toString(), username);
    await this.client.expire(key, 24 * 60 * 60);
  }

  async removeRoomMember(roomId: string, userId: number) {
    const key = `exam:${roomId}:members`;
    await this.client.hdel(key, userId.toString());
  }

  async getRoomMembers(roomId: string): Promise<Record<string, string>> {
    const key = `exam:${roomId}:members`;
    return await this.client.hgetall(key);
  }

  // 通用方法
  async ping(): Promise<boolean> {
    try {
      const result = await this.client.ping();
      return result === 'PONG';
    } catch (error) {
      log('Redis ping failed:', error);
      return false;
    }
  }

  async disconnect() {
    await this.client.disconnect();
  }
}

// 单例实例
export const redisService = new RedisService();