import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
import request from 'supertest';
import { app } from '../api/app';
import { initDatabase } from '../api/database';

// 测试数据
const testUser = {
  name: '测试用户',
  phone: '13800138000',
  password: 'test123'
};

const testCategory = {
  name: '测试类别',
  description: '测试类别描述'
};

const testSubject = {
  name: '测试科目',
  totalScore: 100,
  timeLimitMinutes: 60,
  typeRatios: { single: 40, multiple: 30, judgment: 30 },
  categoryRatios: { '通用': 100 }
};

const testQuestion = {
  content: '测试题目内容',
  type: 'single',
  options: ['选项A', '选项B', '选项C', '选项D'],
  answer: '选项A',
  score: 10,
  category: '通用'
};

describe('OpenSpec 1.1.0 功能测试', () => {
  let server: any;
  let userId: string;
  let categoryId: string;
  let subjectId: string;
  let questionId: string;
  let taskId: string;
  let adminToken: string;

  beforeAll(async () => {
    // 初始化数据库
    await initDatabase();
    
    // 启动测试服务器
    server = app.listen(0);
    
    // 创建管理员用户并获取token
    const adminLogin = await request(server)
      .post('/api/admin/login')
      .send({ username: 'admin', password: 'admin123' });
    
    adminToken = adminLogin.body.data.token;
  });

  afterAll(async () => {
    if (server) {
      server.close();
    }
  });

  describe('1. 题目类别管理', () => {
    it('应该创建题目类别', async () => {
      const response = await request(server)
        .post('/api/admin/question-categories')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(testCategory);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe(testCategory.name);
      
      categoryId = response.body.data.id;
    });

    it('应该获取题目类别列表', async () => {
      const response = await request(server)
        .get('/api/question-categories');

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data)).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
    });

    it('应该更新题目类别', async () => {
      const updatedData = { ...testCategory, name: '更新后的类别' };
      
      const response = await request(server)
        .put(`/api/admin/question-categories/${categoryId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send(updatedData);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe('更新后的类别');
    });
  });

  describe('2. 考试科目管理', () => {
    it('应该创建考试科目', async () => {
      const response = await request(server)
        .post('/api/admin/subjects')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(testSubject);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe(testSubject.name);
      
      subjectId = response.body.data.id;
    });

    it('应该获取考试科目列表', async () => {
      const response = await request(server)
        .get('/api/exam-subjects');

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data)).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
    });

    it('应该更新考试科目', async () => {
      const updatedData = { ...testSubject, name: '更新后的科目' };
      
      const response = await request(server)
        .put(`/api/admin/subjects/${subjectId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send(updatedData);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe('更新后的科目');
    });
  });

  describe('3. 题目管理（带类别）', () => {
    it('应该创建带类别的题目', async () => {
      const questionWithCategory = {
        ...testQuestion,
        category: testCategory.name
      };

      const response = await request(server)
        .post('/api/questions')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(questionWithCategory);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.category).toBe(testCategory.name);
      
      questionId = response.body.data.id;
    });

    it('应该按类别筛选题目', async () => {
      const response = await request(server)
        .get('/api/questions')
        .query({ category: testCategory.name });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
      expect(response.body.data[0].category).toBe(testCategory.name);
    });
  });

  describe('4. 用户管理', () => {
    it('应该创建用户', async () => {
      const response = await request(server)
        .post('/api/users')
        .send(testUser);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe(testUser.name);
      
      userId = response.body.data.id;
    });

    it('应该验证用户密码', async () => {
      const response = await request(server)
        .post('/api/users/validate')
        .send({ name: testUser.name, phone: testUser.phone, password: testUser.password });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    it('应该拒绝错误的密码', async () => {
      const response = await request(server)
        .post('/api/users/validate')
        .send({ name: testUser.name, phone: testUser.phone, password: 'wrongpassword' });

      expect(response.status).toBe(400);
      expect(response.body.success).toBe(false);
    });

    it('应该获取用户列表（管理员）', async () => {
      const response = await request(server)
        .get('/api/admin/users')
        .set('Authorization', `Bearer ${adminToken}`);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data)).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
    });
  });

  describe('5. 考试任务管理', () => {
    it('应该创建考试任务', async () => {
      const taskData = {
        name: '测试任务',
        subjectId: subjectId,
        startAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), // 昨天
        endAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), // 明天
        userIds: [userId]
      };

      const response = await request(server)
        .post('/api/admin/tasks')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(taskData);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe('测试任务');
      
      taskId = response.body.data.id;
    });

    it('应该获取用户任务列表', async () => {
      const response = await request(server)
        .get(`/api/exam-tasks/user/${userId}`);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data)).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
    });
  });

  describe('6. 基于科目的答题', () => {
    it('应该基于科目生成试卷', async () => {
      const response = await request(server)
        .post('/api/quiz/generate')
        .send({
          userId: userId,
          subjectId: subjectId
        });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data.questions)).toBe(true);
      expect(response.body.data.questions.length).toBeGreaterThan(0);
      expect(response.body.data.totalScore).toBe(testSubject.totalScore);
      expect(response.body.data.timeLimit).toBe(testSubject.timeLimitMinutes);
    });

    it('应该基于任务生成试卷', async () => {
      const response = await request(server)
        .post('/api/quiz/generate')
        .send({
          userId: userId,
          taskId: taskId
        });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data.questions)).toBe(true);
      expect(response.body.data.questions.length).toBeGreaterThan(0);
    });
  });

  describe('7. 答题提交（带科目/任务信息）', () => {
    let questions: any[];

    beforeAll(async () => {
      // 获取题目用于测试
      const response = await request(server)
        .post('/api/quiz/generate')
        .send({ userId: userId, subjectId: subjectId });
      
      questions = response.body.data.questions;
    });

    it('应该提交带科目信息的答案', async () => {
      const answers = questions.map((q: any) => ({
        questionId: q.id,
        userAnswer: q.answer,
        score: q.score,
        isCorrect: true
      }));

      const response = await request(server)
        .post('/api/quiz/submit')
        .send({
          userId: userId,
          subjectId: subjectId,
          answers: answers
        });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.recordId).toBeDefined();
    });

    it('应该提交带任务信息的答案', async () => {
      const answers = questions.map((q: any) => ({
        questionId: q.id,
        userAnswer: q.answer,
        score: q.score,
        isCorrect: true
      }));

      const response = await request(server)
        .post('/api/quiz/submit')
        .send({
          userId: userId,
          taskId: taskId,
          answers: answers
        });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.recordId).toBeDefined();
    });
  });

  describe('8. 数据清理', () => {
    it('应该删除考试任务', async () => {
      const response = await request(server)
        .delete(`/api/admin/tasks/${taskId}`)
        .set('Authorization', `Bearer ${adminToken}`);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    it('应该删除考试科目', async () => {
      const response = await request(server)
        .delete(`/api/admin/subjects/${subjectId}`)
        .set('Authorization', `Bearer ${adminToken}`);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    it('应该删除题目类别', async () => {
      const response = await request(server)
        .delete(`/api/admin/question-categories/${categoryId}`)
        .set('Authorization', `Bearer ${adminToken}`);

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });
  });
});