/**
 * 武术比赛报名系统API自动化测试脚本
 * 运行方式：node test/api-test.js
 * 需要先安装axios: npm install axios
 */

const axios = require('axios');

// 配置
const config = {
  baseURL: 'http://your-api-domain.com', // 修改为你的API地址
  timeout: 10000,
  testUser: {
    username: 'test_user',
    password: 'test_password'
  }
};

// 创建axios实例
const api = axios.create({
  baseURL: config.baseURL,
  timeout: config.timeout,
  headers: {
    'Content-Type': 'application/json'
  }
});

// 测试结果统计
const testResults = {
  total: 0,
  passed: 0,
  failed: 0,
  errors: []
};

// 全局变量存储测试数据
let token = '';
let testCompetitionId = '';
let testAthleteId = '';
let testRegistrationId = '';

// 工具函数：断言
function assert(condition, testName, message) {
  testResults.total++;
  if (condition) {
    testResults.passed++;
    console.log(`✓ ${testName}`);
    return true;
  } else {
    testResults.failed++;
    console.error(`✗ ${testName}: ${message}`);
    testResults.errors.push({ test: testName, message });
    return false;
  }
}

// 工具函数：设置Token
function setToken(newToken) {
  token = newToken;
  api.defaults.headers['Blade-Auth'] = `Bearer ${token}`;
}

// 测试用例
const tests = {
  // 1. 用户登录测试
  async testLogin() {
    console.log('\n【测试1】用户登录');
    try {
      const res = await api.post('/martial/auth/login', config.testUser);
      assert(res.status === 200, '登录请求HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '登录业务状态码', `期望200，实际${res.data.code}`);
      assert(res.data.data && res.data.data.token, '返回Token', '未返回token');

      if (res.data.data && res.data.data.token) {
        setToken(res.data.data.token);
        console.log(`  Token: ${token.substring(0, 20)}...`);
      }
      return true;
    } catch (err) {
      assert(false, '登录请求', err.message);
      return false;
    }
  },

  // 2. 获取轮播图列表
  async testBannerList() {
    console.log('\n【测试2】获取轮播图列表');
    try {
      const res = await api.get('/martial/banner/list');
      assert(res.status === 200, '轮播图请求HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '轮播图业务状态码', `期望200，实际${res.data.code}`);
      assert(Array.isArray(res.data.data), '返回数据格式', '期望数组格式');
      console.log(`  轮播图数量: ${res.data.data ? res.data.data.length : 0}`);
    } catch (err) {
      assert(false, '轮播图请求', err.message);
    }
  },

  // 3. 获取赛事列表
  async testCompetitionList() {
    console.log('\n【测试3】获取赛事列表');
    try {
      const res = await api.get('/martial/competition/list', {
        params: { current: 1, size: 20 }
      });
      assert(res.status === 200, '赛事列表HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '赛事列表业务状态码', `期望200，实际${res.data.code}`);

      const hasRecords = res.data.data && res.data.data.records && res.data.data.records.length > 0;
      const isArray = Array.isArray(res.data.data) && res.data.data.length > 0;

      assert(hasRecords || isArray, '返回赛事数据', '未返回赛事数据');

      if (hasRecords) {
        testCompetitionId = res.data.data.records[0].id;
        console.log(`  赛事数量: ${res.data.data.records.length}`);
        console.log(`  测试赛事ID: ${testCompetitionId}`);
      } else if (isArray) {
        testCompetitionId = res.data.data[0].id;
        console.log(`  赛事数量: ${res.data.data.length}`);
        console.log(`  测试赛事ID: ${testCompetitionId}`);
      }
    } catch (err) {
      assert(false, '赛事列表请求', err.message);
    }
  },

  // 4. 获取赛事详情
  async testCompetitionDetail() {
    console.log('\n【测试4】获取赛事详情');
    if (!testCompetitionId) {
      console.log('  跳过：未获取到测试赛事ID');
      return;
    }

    try {
      const res = await api.get('/martial/competition/detail', {
        params: { id: testCompetitionId }
      });
      assert(res.status === 200, '赛事详情HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '赛事详情业务状态码', `期望200，实际${res.data.code}`);
      assert(res.data.data && res.data.data.id, '返回赛事详情', '未返回详情数据');

      if (res.data.data) {
        console.log(`  赛事名称: ${res.data.data.name || res.data.data.title || '未知'}`);
        console.log(`  赛事地点: ${res.data.data.location || res.data.data.address || '未知'}`);
      }
    } catch (err) {
      assert(false, '赛事详情请求', err.message);
    }
  },

  // 5. 获取选手列表
  async testAthleteList() {
    console.log('\n【测试5】获取选手列表');
    try {
      const res = await api.get('/martial/athlete/list', {
        params: { current: 1, size: 100 }
      });
      assert(res.status === 200, '选手列表HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '选手列表业务状态码', `期望200，实际${res.data.code}`);

      const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0;
      const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0;
      console.log(`  选手数量: ${records || arrayLength}`);
    } catch (err) {
      assert(false, '选手列表请求', err.message);
    }
  },

  // 6. 新增选手
  async testCreateAthlete() {
    console.log('\n【测试6】新增选手');
    try {
      const res = await api.post('/martial/athlete/submit', {
        name: '测试选手_' + Date.now(),
        idCard: '110101199001011234',
        team: '测试队伍',
        gender: '男',
        phone: '13800138000'
      });
      assert(res.status === 200, '新增选手HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '新增选手业务状态码', `期望200，实际${res.data.code}`);

      if (res.data.data && res.data.data.id) {
        testAthleteId = res.data.data.id;
        console.log(`  新增选手ID: ${testAthleteId}`);
      } else if (res.data.data) {
        testAthleteId = res.data.data;
        console.log(`  新增选手ID: ${testAthleteId}`);
      }
    } catch (err) {
      assert(false, '��增选手请求', err.message);
    }
  },

  // 7. 获取选手详情
  async testAthleteDetail() {
    console.log('\n【测试7】获取选手详情');
    if (!testAthleteId) {
      console.log('  跳过：未获取到测试选手ID');
      return;
    }

    try {
      const res = await api.get('/martial/athlete/detail', {
        params: { id: testAthleteId }
      });
      assert(res.status === 200, '选手详情HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '选手详情业务状态码', `期望200，实际${res.data.code}`);
      assert(res.data.data && res.data.data.name, '返回选手详情', '未返回详情数据');

      if (res.data.data) {
        console.log(`  选手姓名: ${res.data.data.name}`);
      }
    } catch (err) {
      assert(false, '选手详情请求', err.message);
    }
  },

  // 8. 获取报名项目列表
  async testProjectList() {
    console.log('\n【测试8】获取报名项目列表');
    if (!testCompetitionId) {
      console.log('  跳过：未获取到测试赛事ID');
      return;
    }

    try {
      const res = await api.get('/martial/project/list', {
        params: { competitionId: testCompetitionId }
      });
      assert(res.status === 200, '项目列表HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '项目列表业务状态码', `期望200，实际${res.data.code}`);

      const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0;
      const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0;
      console.log(`  项目数量: ${records || arrayLength}`);
    } catch (err) {
      assert(false, '项目列表请求', err.message);
    }
  },

  // 9. 获取我的报名列表
  async testRegistrationList() {
    console.log('\n【测试9】获取我的报名列表');
    try {
      const res = await api.get('/martial/registration/list', {
        params: { current: 1, size: 20 }
      });
      assert(res.status === 200, '报名列表HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '报名列表业务状态码', `期望200，实际${res.data.code}`);

      const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0;
      const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0;
      console.log(`  报名记录数量: ${records || arrayLength}`);
    } catch (err) {
      assert(false, '报名列表请求', err.message);
    }
  },

  // 10. 获取用户信息
  async testUserInfo() {
    console.log('\n【测试10】获取用户信息');
    try {
      const res = await api.get('/martial/user/info');
      assert(res.status === 200, '用户信息HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '用户信息业务状态码', `期望200，实际${res.data.code}`);
      assert(res.data.data, '返回用户信息', '未返回用户数据');

      if (res.data.data) {
        console.log(`  用户名: ${res.data.data.name || res.data.data.username || '未知'}`);
      }
    } catch (err) {
      assert(false, '用户信息请求', err.message);
    }
  },

  // 11. 获取赛事信息公告
  async testInfoList() {
    console.log('\n【测试11】获取赛事信息公告');
    if (!testCompetitionId) {
      console.log('  跳过：未获取到测试赛事ID');
      return;
    }

    try {
      const res = await api.get('/martial/info/list', {
        params: { competitionId: testCompetitionId }
      });
      assert(res.status === 200, '信息公告HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '信息公告业务状态码', `期望200，实际${res.data.code}`);

      const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0;
      const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0;
      console.log(`  公告数量: ${records || arrayLength}`);
    } catch (err) {
      assert(false, '信息公告请求', err.message);
    }
  },

  // 12. 获取成绩列表
  async testResultList() {
    console.log('\n【测试12】获取成绩列表');
    if (!testCompetitionId) {
      console.log('  跳过：未获取到测试赛事ID');
      return;
    }

    try {
      const res = await api.get('/martial/result/list', {
        params: { competitionId: testCompetitionId, current: 1, size: 100 }
      });
      assert(res.status === 200, '成绩列表HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '成绩列表业务状态码', `期望200，实际${res.data.code}`);

      const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0;
      const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0;
      console.log(`  成绩记录数量: ${records || arrayLength}`);
    } catch (err) {
      assert(false, '成绩列表请求', err.message);
    }
  },

  // 13. 获取奖牌榜
  async testMedalsList() {
    console.log('\n【测试13】获取奖牌榜');
    if (!testCompetitionId) {
      console.log('  跳过：未获取到测试赛事ID');
      return;
    }

    try {
      const res = await api.get('/martial/medal/list', {
        params: { competitionId: testCompetitionId }
      });
      assert(res.status === 200, '奖牌榜HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '奖牌榜业务状态码', `期望200，实际${res.data.code}`);

      const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0;
      const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0;
      console.log(`  奖牌榜队伍数: ${records || arrayLength}`);
    } catch (err) {
      assert(false, '奖牌榜请求', err.message);
    }
  },

  // 14. 删除测试选手（清理数据）
  async testDeleteAthlete() {
    console.log('\n【测试14】删除测试选手（清理数据）');
    if (!testAthleteId) {
      console.log('  跳过：未创建测试选手');
      return;
    }

    try {
      const res = await api.delete('/martial/athlete/remove', {
        params: { ids: testAthleteId }
      });
      assert(res.status === 200, '删除选手HTTP状态码', `期望200，实际${res.status}`);
      assert(res.data.code === 200, '删除选手业务状态码', `期望200，实际${res.data.code}`);
      console.log(`  成功删除测试选手: ${testAthleteId}`);
    } catch (err) {
      assert(false, '删除选手请求', err.message);
    }
  }
};

// 运行所有测试
async function runAllTests() {
  console.log('='.repeat(60));
  console.log('武术比赛报名系统 - API自动化测试');
  console.log('='.repeat(60));
  console.log(`测试开始时间: ${new Date().toLocaleString()}`);
  console.log(`API地址: ${config.baseURL}`);

  const startTime = Date.now();

  // 按顺序执行所有测试
  for (const [name, testFn] of Object.entries(tests)) {
    try {
      await testFn();
    } catch (err) {
      console.error(`\n测试执行异常 [${name}]:`, err.message);
    }
  }

  const duration = ((Date.now() - startTime) / 1000).toFixed(2);

  // 输出测试结果
  console.log('\n' + '='.repeat(60));
  console.log('测试结果汇总');
  console.log('='.repeat(60));
  console.log(`总测试数: ${testResults.total}`);
  console.log(`通过: ${testResults.passed} ✓`);
  console.log(`失败: ${testResults.failed} ✗`);
  console.log(`成功率: ${testResults.total > 0 ? ((testResults.passed / testResults.total) * 100).toFixed(2) : 0}%`);
  console.log(`耗时: ${duration}秒`);
  console.log(`测试结束时间: ${new Date().toLocaleString()}`);

  if (testResults.failed > 0) {
    console.log('\n失败的测试:');
    testResults.errors.forEach((err, index) => {
      console.log(`${index + 1}. ${err.test}: ${err.message}`);
    });
  }

  console.log('='.repeat(60));

  // 退出进程，返回状态码
  process.exit(testResults.failed > 0 ? 1 : 0);
}

// 执行测试
runAllTests().catch(err => {
  console.error('测试执行失败:', err);
  process.exit(1);
});
