import { describe, it, expect, beforeEach } from 'vitest';
import { testClient } from 'hono/testing';
import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
import { JWTUtil } from '@d8d/shared-utils';
import { UserEntity, Role } from '@d8d/user-module';
import { File } from '@d8d/file-module';
import { AreaEntity } from '@d8d/geo-areas';
import salaryRoutes from '../../src/routes/salary.routes';
import { SalaryLevel } from '../../src/entities/salary-level.entity';

// 设置集成测试钩子
setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, AreaEntity, SalaryLevel])

describe('薪资管理API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof salaryRoutes>>;
  let testToken: string;
  let testUser: UserEntity;
  let testProvince: AreaEntity;
  let testCity: AreaEntity;
  let testDistrict: AreaEntity;
  let testProvince2: AreaEntity;
  let testCity2: AreaEntity;

  beforeEach(async () => {
    // 创建测试客户端
    client = testClient(salaryRoutes);

    // 获取数据源
    const dataSource = await IntegrationTestDatabase.getDataSource();

    // 创建测试用户
    const userRepository = dataSource.getRepository(UserEntity);
    testUser = userRepository.create({
      username: `test_user_${Date.now()}`,
      password: 'test_password',
      nickname: '测试用户',
      registrationSource: 'web'
    });
    await userRepository.save(testUser);

    // 生成测试用户的token
    testToken = JWTUtil.generateToken({
      id: testUser.id,
      username: testUser.username,
      roles: [{name:'user'}]
    });

    // 创建测试区域数据
    const areaRepository = dataSource.getRepository(AreaEntity);

    // 创建省份
    testProvince = areaRepository.create({
      code: '110000',
      name: '北京市',
      level: 1,
      parentId: null
    });
    await areaRepository.save(testProvince);

    // 创建城市
    testCity = areaRepository.create({
      code: '110100',
      name: '北京市',
      level: 2,
      parentId: testProvince.id
    });
    await areaRepository.save(testCity);

    // 创建区县
    testDistrict = areaRepository.create({
      code: '110101',
      name: '东城区',
      level: 3,
      parentId: testCity.id
    });
    await areaRepository.save(testDistrict);

    // 创建第二个省份
    testProvince2 = areaRepository.create({
      code: '120000',
      name: '天津市',
      level: 1,
      parentId: null
    });
    await areaRepository.save(testProvince2);

    // 创建第二个城市
    testCity2 = areaRepository.create({
      code: '120100',
      name: '天津市',
      level: 2,
      parentId: testProvince2.id
    });
    await areaRepository.save(testCity2);
  });

  describe('POST /salary/create', () => {
    it('应该成功创建薪资水平', async () => {
      const createData = {
        provinceId: testProvince.id,
        cityId: testCity.id,
        districtId: testDistrict.id,
        basicSalary: 5000.00
      };

      console.debug('发送的创建数据:', JSON.stringify(createData, null, 2));
      const response = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      if (response.status !== 200) {
        const error = await response.json();
        console.debug('创建薪资失败:', JSON.stringify(error, null, 2));
      }
      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data.id).toBeDefined();
        expect(data.provinceId).toBe(testProvince.id);
        expect(data.cityId).toBe(testCity.id);
        expect(data.districtId).toBe(testDistrict.id);
        expect(data.basicSalary).toBe(5000.00);
        expect(data.totalSalary).toBe(5000.00); // 只有基本工资
      }
    });

    it('应该验证区域层级关系', async () => {
      const createData = {
        provinceId: testProvince.id,
        cityId: testDistrict.id, // 错误的层级：城市ID使用了区县ID
        districtId: testCity.id, // 错误的层级：区县ID使用了城市ID
        basicSalary: 5000.00
      };

      const response = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400);
    });

    it('应该验证中文错误消息 - 缺少必填字段', async () => {
      const createData = {
        provinceId: 0, // 发送0而不是null
        cityId: 0, // 发送0而不是null
        basicSalary: 5000.00
      };

      const response = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400);

      if (response.status === 400) {
        const errorData = await response.json() as any;
        console.debug('缺少必填字段错误响应:', JSON.stringify(errorData, null, 2));

        // 验证错误响应格式 - 根据实际响应调整
        if ('success' in errorData) {
          // 格式: { success: boolean; error: { name: string; message: string } }
          expect(errorData.success).toBe(false);
          expect(errorData.error).toHaveProperty('name');
          expect(errorData.error.name).toBe('ZodError');
          expect(errorData.error).toHaveProperty('message');

          // 解析错误消息
          const errorMessages = JSON.parse(errorData.error.message);
          expect(Array.isArray(errorMessages)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorMessages.map((err: any) => err.message);
          expect(errorTexts).toContain('请选择省份');
          expect(errorTexts).toContain('请选择城市');
        } else {
          // 格式: { code: number; message: string; errors?: any }
          expect(errorData.code).toBe(400);
          expect(errorData.message).toBe('参数错误');
          expect(errorData).toHaveProperty('errors');
          expect(Array.isArray(errorData.errors)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorData.errors.map((err: any) => err.message);
          expect(errorTexts).toContain('请选择省份');
          expect(errorTexts).toContain('请选择城市');
        }
      }
    });

    it('应该验证中文错误消息 - 基本工资为0', async () => {
      const createData = {
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: 0 // 基本工资为0，应该触发错误
      };

      const response = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400);

      if (response.status === 400) {
        const errorData = await response.json() as any;
        console.debug('基本工资为0错误响应:', JSON.stringify(errorData, null, 2));

        // 验证错误响应格式 - 支持两种格式
        if (errorData.success !== undefined) {
          // 格式: { success: false, error: { name: 'ZodError', message: '...' } }
          expect(errorData.success).toBe(false);
          expect(errorData).toHaveProperty('error');
          expect(errorData.error).toHaveProperty('name');
          expect(errorData.error.name).toBe('ZodError');
          expect(errorData.error).toHaveProperty('message');

          // 解析错误消息
          const errorMessages = JSON.parse(errorData.error.message);
          expect(Array.isArray(errorMessages)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorMessages.map((err: any) => err.message);
          expect(errorTexts).toContain('基本工资必须大于0');
        } else {
          // 格式: { code: number; message: string; errors?: any }
          expect(errorData.code).toBe(400);
          expect(errorData.message).toBe('参数错误');
          expect(errorData).toHaveProperty('errors');
          expect(Array.isArray(errorData.errors)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorData.errors.map((err: any) => err.message);
          expect(errorTexts).toContain('基本工资必须大于0');
        }
      }
    });

    it('应该验证中文错误消息 - 津贴补贴为负数', async () => {
      const createData = {
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: 5000.00,
        allowance: -100 // 津贴补贴为负数，应该触发错误
      };

      const response = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400);

      if (response.status === 400) {
        const errorData = await response.json() as any;
        console.debug('津贴补贴为负数错误响应:', JSON.stringify(errorData, null, 2));

        // 验证错误响应格式 - 支持两种格式
        if (errorData.success !== undefined) {
          // 格式: { success: false, error: { name: 'ZodError', message: '...' } }
          expect(errorData.success).toBe(false);
          expect(errorData).toHaveProperty('error');
          expect(errorData.error).toHaveProperty('name');
          expect(errorData.error.name).toBe('ZodError');
          expect(errorData.error).toHaveProperty('message');

          // 解析错误消息
          const errorMessages = JSON.parse(errorData.error.message);
          expect(Array.isArray(errorMessages)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorMessages.map((err: any) => err.message);
          expect(errorTexts).toContain('津贴补贴不能为负数');
        } else {
          // 格式: { code: number; message: string; errors?: any }
          expect(errorData.code).toBe(400);
          expect(errorData.message).toBe('参数错误');
          expect(errorData).toHaveProperty('errors');
          expect(Array.isArray(errorData.errors)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorData.errors.map((err: any) => err.message);
          expect(errorTexts).toContain('津贴补贴不能为负数');
        }
      }
    });

    it('应该验证中文错误消息 - 类型转换错误', async () => {
      const createData = {
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: '不是数字' as any, // 字符串，应该触发类型转换错误
        allowance: 100
      };

      const response = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400);

      if (response.status === 400) {
        const errorData = await response.json() as any;
        console.debug('类型转换错误响应:', JSON.stringify(errorData, null, 2));

        // 验证错误响应格式 - 支持两种格式
        if (errorData.success !== undefined) {
          // 格式: { success: false, error: { name: 'ZodError', message: '...' } }
          expect(errorData.success).toBe(false);
          expect(errorData).toHaveProperty('error');
          expect(errorData.error).toHaveProperty('name');
          expect(errorData.error.name).toBe('ZodError');
          expect(errorData.error).toHaveProperty('message');

          // 解析错误消息
          const errorMessages = JSON.parse(errorData.error.message);
          expect(Array.isArray(errorMessages)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorMessages.map((err: any) => err.message);
          console.debug('类型转换错误消息:', errorTexts);
          // 类型转换错误显示我们设置的中文错误消息
          expect(errorTexts).toContain('基本工资必须大于0');
        } else {
          // 格式: { code: number; message: string; errors?: any }
          expect(errorData.code).toBe(400);
          expect(errorData.message).toBe('参数错误');
          expect(errorData).toHaveProperty('errors');
          expect(Array.isArray(errorData.errors)).toBe(true);

          // 验证具体的错误消息
          const errorTexts = errorData.errors.map((err: any) => err.message);
          console.debug('类型转换错误消息:', errorTexts);
          expect(errorTexts).toContain('基本工资必须大于0');
        }
      }
    });

    it('应该验证区域唯一性约束', async () => {
      // 第一次创建
      const createData = {
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: 5000.00
      };

      const firstResponse = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });
      expect(firstResponse.status).toBe(200);

      // 第二次创建相同区域
      const secondResponse = await client.create.$post({
        json: createData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(secondResponse.status).toBe(400);
    });
  });

  describe('GET /salary/list', () => {
    beforeEach(async () => {
      // 创建测试数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const salaryRepository = dataSource.getRepository(SalaryLevel);

      const salary1 = salaryRepository.create({
        provinceId: testProvince.id,
        cityId: testCity.id,
        districtId: testDistrict.id,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 7300.00
      });
      await salaryRepository.save(salary1);

      const salary2 = salaryRepository.create({
        provinceId: testProvince2.id, // 使用不同的省份
        cityId: testCity2.id, // 使用不同的城市
        basicSalary: 6000.00,
        allowance: 1200.00,
        insurance: 600.00,
        housingFund: 900.00,
        totalSalary: 8700.00
      });
      await salaryRepository.save(salary2);
    });

    it('应该返回所有薪资水平列表', async () => {
      const response = await client.list.$get({
        query: {}
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data).toHaveProperty('data');
        expect(data).toHaveProperty('total');
        expect(data.data).toHaveLength(2);
        expect(data.total).toBe(2);
      }
    });

    it('应该支持按区域ID过滤', async () => {
      const response = await client.list.$get({
        query: {
          provinceId: testProvince.id,
          cityId: testCity.id
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data.data).toHaveLength(1);
      }
    });

    it('应该支持分页查询', async () => {
      const response = await client.list.$get({
        query: {
          skip: 0,
          take: 1
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data.data).toHaveLength(1);
        expect(data.total).toBe(2);
      }
    });
  });

  describe('GET /salary/detail/:id', () => {
    let testSalary: SalaryLevel;

    beforeEach(async () => {
      // 创建测试薪资数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const salaryRepository = dataSource.getRepository(SalaryLevel);

      testSalary = salaryRepository.create({
        provinceId: testProvince.id,
        cityId: testCity.id,
        districtId: testDistrict.id,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 7300.00,
      });
      await salaryRepository.save(testSalary);
    });

    it('应该返回指定ID的薪资详情', async () => {
      const response = await client.detail[':id'].$get({
        param: { id: testSalary.id.toString() }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data?.id).toBe(testSalary.id);
        expect(data?.provinceId).toBe(testProvince.id);
        expect(data?.cityId).toBe(testCity.id);
      }
    });

    it('应该处理不存在的薪资ID', async () => {
      const response = await client.detail[':id'].$get({
        param: { id: 999999 }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(404);
    });
  });

  describe('GET /salary/byProvinceCity', () => {
    let testSalary: SalaryLevel;

    beforeEach(async () => {
      // 创建测试薪资数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const salaryRepository = dataSource.getRepository(SalaryLevel);

      testSalary = salaryRepository.create({
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 7300.00,
      });
      await salaryRepository.save(testSalary);
    });

    it('应该按省份城市查询薪资', async () => {
      const response = await client.byProvinceCity.$get({
        query: {
          provinceId: testProvince.id,
          cityId: testCity.id
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data?.id).toBe(testSalary.id);
        expect(data?.provinceId).toBe(testProvince.id);
        expect(data?.cityId).toBe(testCity.id);
      }
    });

    it('应该处理不存在的区域组合', async () => {
      const response = await client.byProvinceCity.$get({
        query: {
          provinceId: 999999,
          cityId: 999999
        }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(404);
    });
  });

  describe('PUT /salary/update/:id', () => {
    let testSalary: SalaryLevel;

    beforeEach(async () => {
      // 创建测试薪资数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const salaryRepository = dataSource.getRepository(SalaryLevel);

      testSalary = salaryRepository.create({
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 7300.00,
      });
      await salaryRepository.save(testSalary);
    });

    it('应该成功更新薪资水平', async () => {
      const updateData = {
        basicSalary: 5500.00,
        allowance: 1200.00
      };

      const response = await client.update[':id'].$put({
        param: { id: testSalary.id.toString() },
        json: updateData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data.id).toBe(testSalary.id);
        expect(data.basicSalary).toBe(5500.00);
        expect(data.allowance).toBe(1200.00);
        expect(data.totalSalary).toBe(8000.00); // 5500 + 1200 + 500 + 800
      }
    });

    it('应该验证更新后的区域数据', async () => {
      const updateData = {
        provinceId: 999999 // 不存在的区域ID
      };

      const response = await client.update[':id'].$put({
        param: { id: testSalary.id.toString() },
        json: updateData
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(400);
    });
  });

  describe('DELETE /salary/delete/:id', () => {
    let testSalary: SalaryLevel;

    beforeEach(async () => {
      // 创建测试薪资数据
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const salaryRepository = dataSource.getRepository(SalaryLevel);

      testSalary = salaryRepository.create({
        provinceId: testProvince.id,
        cityId: testCity.id,
        basicSalary: 5000.00,
        allowance: 1000.00,
        insurance: 500.00,
        housingFund: 800.00,
        totalSalary: 7300.00,
      });
      await salaryRepository.save(testSalary);
    });

    it('应该成功删除薪资水平', async () => {
      const response = await client.delete[':id'].$delete({
        param: { id: testSalary.id.toString() }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data).toEqual({ success: true });

        // 验证数据已删除
        const dataSource = await IntegrationTestDatabase.getDataSource();
        const salaryRepository = dataSource.getRepository(SalaryLevel);
        const deletedSalary = await salaryRepository.findOne({
          where: { id: testSalary.id }
        });
        expect(deletedSalary).toBeNull();
      }
    });

    it('应该处理不存在的薪资ID', async () => {
      const response = await client.delete[':id'].$delete({
        param: { id: 999999 }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(404);
    });
  });

  describe('认证测试', () => {
    it('应该要求认证', async () => {
      const response = await client.list.$get({
        query: {}
        // 不提供Authorization header
      });

      expect(response.status).toBe(401);
    });

    it('应该验证无效token', async () => {
      const response = await client.list.$get({
        query: {}
      }, {
        headers: {
          'Authorization': 'Bearer invalid_token'
        }
      });

      expect(response.status).toBe(401);
    });
  });
});