import { QuizController } from './quiz.controller';

describe('QuizController', () => {
  let controller: QuizController;
  let mockService: any;

  beforeEach(() => {
    mockService = {
      create: jest.fn(),
      findAll: jest.fn(),
      findOne: jest.fn(),
      start: jest.fn(),
      getAttemptQuestions: jest.fn(),
      submit: jest.fn(),
      getResults: jest.fn(),
      getHistory: jest.fn(),
    };
    controller = new QuizController(mockService);
  });

  // @CurrentUser() 在单元测试中直接接收参数值，不需要嵌套 { user: { id } }
  const user = (id = 'u1') => ({ id }) as any;

  // ═══════════════════════════════════════════════
  // POST /quizzes/:id/attempts
  // ═══════════════════════════════════════════════

  describe('POST :id/attempts', () => {
    it('创建独立 Attempt 并返回', async () => {
      mockService.start.mockResolvedValue({ id: 'a1', quizId: 'q1', userId: 'u1', totalQuestions: 5 });
      const result = await controller.startAttempt(user(), 'q1');
      expect(result.id).toBe('a1');
      expect(mockService.start).toHaveBeenCalledWith('u1', 'q1');
    });
  });

  // ═══════════════════════════════════════════════
  // GET /quizzes/attempts/:id/questions
  // ═══════════════════════════════════════════════

  describe('GET attempts/:id/questions', () => {
    it('按 Attempt 加载题目', async () => {
      const questions = [
        { id: 'qq1', type: 'choice', stem: 'Q1?', options: ['A', 'B'], orderIndex: 0 },
      ];
      mockService.getAttemptQuestions.mockResolvedValue(questions);

      const result = await controller.getAttemptQuestions(user(), 'a1');
      expect(result).toEqual(questions);
      expect(mockService.getAttemptQuestions).toHaveBeenCalledWith('u1', 'a1');
    });
  });

  // ═══════════════════════════════════════════════
  // GET /quizzes/:id（修改后）
  // ═══════════════════════════════════════════════

  describe('GET :id', () => {
    it('传入 userId 查询 Quiz 详情', async () => {
      mockService.findOne.mockResolvedValue({ id: 'q1', title: 'Test' });
      const result = await controller.findOne(user(), 'q1');
      expect(result).toEqual({ id: 'q1', title: 'Test' });
      expect(mockService.findOne).toHaveBeenCalledWith('u1', 'q1');
    });
  });

  // ═══════════════════════════════════════════════
  // POST /quizzes/:id/start（旧端点兼容）
  // ═══════════════════════════════════════════════

  describe('POST :id/start（兼容旧端点）', () => {
    it('创建 Attempt 并返回', async () => {
      mockService.start.mockResolvedValue({ id: 'a1', quizId: 'q1', userId: 'u1' });
      const result = await controller.start(user(), 'q1');
      expect(result.id).toBe('a1');
      expect(mockService.start).toHaveBeenCalledWith('u1', 'q1');
    });
  });

  // ═══════════════════════════════════════════════
  // GET /quizzes/:id/results（修改后）
  // ═══════════════════════════════════════════════

  describe('GET :id/results', () => {
    it('传入 userId 查询结果', async () => {
      const attempt = { id: 'a1', quizId: 'q1', userId: 'u1', answers: [] };
      mockService.getResults.mockResolvedValue(attempt);

      const result = await controller.getResults(user(), 'q1', 'a1');
      expect(result).toEqual(attempt);
      expect(mockService.getResults).toHaveBeenCalledWith('u1', 'a1');
    });
  });

  // ═══════════════════════════════════════════════
  // GET /quizzes（未修改但验证不变）
  // ═══════════════════════════════════════════════

  describe('GET quizzes list', () => {
    it('返回用户自己的 Quiz 列表', async () => {
      mockService.findAll.mockResolvedValue([{ id: 'q1' }]);
      const result = await controller.findAll(user(), 'kb1');
      expect(result).toEqual([{ id: 'q1' }]);
      expect(mockService.findAll).toHaveBeenCalledWith('u1', 'kb1');
    });
  });

  // ═══════════════════════════════════════════════
  // GET /quizzes/history/list
  // ═══════════════════════════════════════════════

  describe('GET history/list', () => {
    it('返回用户自己的 Attempt 历史', async () => {
      mockService.getHistory.mockResolvedValue([{ id: 'a1' }]);
      const result = await controller.getHistory(user());
      expect(result).toEqual([{ id: 'a1' }]);
      expect(mockService.getHistory).toHaveBeenCalledWith('u1');
    });
  });
});
