import { Server } from 'socket.io';
import { AuthenticatedSocket } from '../middleware/auth.middleware';
import { redisService } from './redis.service';
import { AppDataSource } from '@/server/data-source';
import { SubmissionRecords } from '@/server/modules/submission/submission-records.entity';
import { ClassroomData } from '@/server/modules/classroom/classroom-data.entity';
import { calculateCumulativeResults } from '@/share/utils/calculateCumulativeResults';
import debug from 'debug';
import type { Answer } from '@/client/mobile/components/Exam/types';

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

export class ExamService {
  private io: Server;

  constructor(io: Server) {
    this.io = io;
  }

  async joinRoom(socket: AuthenticatedSocket, roomId: string) {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      const user = socket.user;
      socket.join(roomId);
      await redisService.addRoomMember(roomId, user.id, user.username);
      
      socket.emit('exam:joined', { roomId, message: `成功加入考试房间: ${roomId}` });
      socket.to(roomId).emit('exam:memberJoined', { roomId, userId: user.id, username: user.username });
      
      log(`用户 ${user.username} 加入考试房间 ${roomId}`);
    } catch (error) {
      log('加入考试房间失败:', error);
      socket.emit('error', '加入考试房间失败');
    }
  }

  async leaveRoom(socket: AuthenticatedSocket, roomId: string) {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      const user = socket.user;
      socket.leave(roomId);
      await redisService.removeRoomMember(roomId, user.id);
      
      socket.emit('exam:left', { roomId, message: `已离开考试房间: ${roomId}` });
      socket.to(roomId).emit('exam:memberLeft', { roomId, userId: user.id, username: user.username });
      
      log(`用户 ${user.username} 离开考试房间 ${roomId}`);
    } catch (error) {
      log('离开考试房间失败:', error);
      socket.emit('error', '离开考试房间失败');
    }
  }

  async pushQuestion(socket: AuthenticatedSocket, roomId: string, question: { date: string; price: string; gain?: number }) {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      await redisService.storeCurrentQuestion(roomId, question);
      await redisService.storePrice(roomId, question.date, question.price);
      
      const quizState = { id: question.date, date: question.date, price: question.price, gain: question.gain };
      socket.to(roomId).emit('exam:question', quizState);
      
      log(`用户 ${socket.user.username} 在房间 ${roomId} 推送题目`);
    } catch (error) {
      log('推送题目失败:', error);
      socket.emit('error', '推送题目失败');
    }
  }

  async storeAnswer(socket: AuthenticatedSocket, roomId: string, questionId: string, answer: Answer): Promise<boolean> {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      const user = socket.user;
      await redisService.storeAnswer(roomId, user.id, questionId, answer);
      
      socket.to(roomId).emit('exam:answerUpdated', {
        roomId, questionId, userId: user.id, username: user.username
      });
      
      log(`用户 ${user.username} 在房间 ${roomId} 存储答案`);
      return true;
    } catch (error) {
      log('存储答案失败:', error);
      socket.emit('error', '存储答案失败');
      return false;
    }
  }

  async getAnswers(roomId: string, questionId?: string): Promise<Answer[]> {
    try {
      return await redisService.getAnswers(roomId, questionId);
    } catch (error) {
      log('获取答案失败:', error);
      return [];
    }
  }

  async getUserAnswers(roomId: string, userId: number): Promise<Answer[]> {
    try {
      return await redisService.getUserAnswers(roomId, userId);
    } catch (error) {
      log('获取用户答案失败:', error);
      return [];
    }
  }

  async storePrice(socket: AuthenticatedSocket, roomId: string, date: string, price: string) {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      await redisService.storePrice(roomId, date, price);
      log(`用户 ${socket.user.username} 存储房间 ${roomId} 的价格历史: ${date} - ${price}`);
    } catch (error) {
      log('存储价格历史失败:', error);
      socket.emit('error', '存储价格历史失败');
    }
  }

  async getPrice(roomId: string, date: string): Promise<string | null> {
    try {
      return await redisService.getPrice(roomId, date);
    } catch (error) {
      log('获取历史价格失败:', error);
      return null;
    }
  }

  async getAllPrices(roomId: string): Promise<Record<string, number>> {
    try {
      return await redisService.getAllPrices(roomId);
    } catch (error) {
      log('获取所有价格历史失败:', error);
      return {};
    }
  }

  async getCurrentQuestion(roomId: string) {
    try {
      return await redisService.getCurrentQuestion(roomId);
    } catch (error) {
      log('获取当前题目失败:', error);
      return null;
    }
  }

  async cleanupRoomData(socket: AuthenticatedSocket, roomId: string, questionId?: string) {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      const user = socket.user;
      
      // 在清理Redis数据前，先保存答题结果到数据库
      await this.saveAnswersToSubmissionRecords(roomId, questionId);
      
      await redisService.cleanupRoomData(roomId, questionId);
      
      socket.to(roomId).emit('exam:cleaned', {
        roomId,
        message: questionId
          ? `已清理房间 ${roomId} 的问题 ${questionId} 数据`
          : `已清理房间 ${roomId} 的所有数据`
      });

      log(`用户 ${user.username} 清理房间 ${roomId} 数据`);
    } catch (error) {
      log('清理房间数据失败:', error);
      socket.emit('error', '清理房间数据失败');
    }
  }

  async broadcastSettle(socket: AuthenticatedSocket, roomId: string) {
    try {
      if (!socket.user) throw new Error('用户未认证');
      
      const user = socket.user;
      socket.to(roomId).emit('exam:settle');
      
      log(`用户 ${user.username} 在房间 ${roomId} 广播结算消息`);
    } catch (error) {
      log('广播结算消息失败:', error);
      socket.emit('error', '广播结算消息失败');
    }
  }

  /**
   * 保存答题结果到提交记录表（保存累计结果）
   */
  private async saveAnswersToSubmissionRecords(roomId: string, questionId?: string): Promise<void> {
    try {
      // 获取所有答题数据
      const answers = await redisService.getAnswers(roomId, questionId);
      
      if (answers.length === 0) {
        log(`房间 ${roomId} 没有答题数据需要保存`);
        return;
      }

      const submissionRecordsRepository = AppDataSource.getRepository(SubmissionRecords);
      const classroomDataRepository = AppDataSource.getRepository(ClassroomData);
      const recordsToSave: SubmissionRecords[] = [];

      // 查询ClassroomData获取code字段
      const classroomData = await classroomDataRepository.findOne({
        where: { classroomNo: roomId }
      });
      const code = classroomData?.code || null;

      // 使用共享工具函数计算累计结果
      const cumulativeResults = calculateCumulativeResults(answers);

      // 为每个用户创建一条累计结果记录
      for (const cumulativeResult of cumulativeResults) {
        const submissionRecord = new SubmissionRecords();
        submissionRecord.classroomNo = roomId;
        submissionRecord.userId = cumulativeResult.userId;
        submissionRecord.score = this.calculateScoreFromCumulative(cumulativeResult);
        submissionRecord.code = code;
        submissionRecord.trainingDate = new Date(); // 使用当前日期作为训练日期
        submissionRecord.mark = null;
        submissionRecord.status = 1;
        submissionRecord.holdingStock = null; // 累计结果不保存具体的持股信息
        submissionRecord.holdingCash = null;  // 累计结果不保存具体的持币信息
        submissionRecord.price = null;        // 累计结果不保存具体的价格
        submissionRecord.profitAmount = null; // 累计结果不保存单日收益
        submissionRecord.profitPercent = null; // 累计结果不保存单日收益率
        submissionRecord.totalProfitAmount = cumulativeResult.totalProfitAmount;
        submissionRecord.totalProfitPercent = cumulativeResult.totalProfitPercent;

        recordsToSave.push(submissionRecord);
      }

      // 批量保存到数据库
      if (recordsToSave.length > 0) {
        await submissionRecordsRepository.save(recordsToSave);
        log(`成功保存 ${recordsToSave.length} 条累计结果记录到数据库，房间: ${roomId}`);
      }
    } catch (error) {
      log('保存累计结果记录到数据库失败:', error);
      // 不抛出错误，避免影响正常的清理操作
    }
  }

  /**
   * 计算得分（可根据业务需求自定义评分逻辑）
   */
  private calculateScore(answer: Answer): number | null {
    // 这里可以根据答题内容计算得分
    // 示例：根据收益率计算得分，收益率越高得分越高
    if (answer.profitPercent !== undefined && answer.profitPercent !== null) {
      return Math.max(0, Math.min(100, 50 + (answer.profitPercent * 2)));
    }
    return null;
  }

  /**
   * 根据累计结果计算得分
   */
  private calculateScoreFromCumulative(result: { totalProfitAmount: number; totalProfitPercent: number }): number | null {
    // 根据累计收益率计算得分，收益率越高得分越高
    if (result.totalProfitPercent !== undefined && result.totalProfitPercent !== null) {
      return Math.max(0, Math.min(100, 50 + (result.totalProfitPercent * 2)));
    }
    return null;
  }
}