import { describe, it, expect, beforeEach, vi, afterEach } 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 { AreaEntity, AreaLevel } from '@d8d/geo-areas';
import deliveryAddressRoutes from '../../src/routes';
import { DeliveryAddress } from '../../src/entities';

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

describe('配送地址管理API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof deliveryAddressRoutes>>;
  let testToken: string;
  let testUser: UserEntity;
  let testProvince: AreaEntity;
  let testCity: AreaEntity;
  let testDistrict: AreaEntity;

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

    // 获取数据源
    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);

    // 创建测试地区数据 - 省
    const areaRepository = dataSource.getRepository(AreaEntity);
    testProvince = areaRepository.create({
      name: '北京市',
      code: '110000',
      level: AreaLevel.PROVINCE,
      parentId: null
    });
    await areaRepository.save(testProvince);

    // 创建测试地区数据 - 市
    testCity = areaRepository.create({
      name: '北京市',
      code: '110100',
      level: AreaLevel.CITY,
      parentId: testProvince.id
    });
    await areaRepository.save(testCity);

    // 创建测试地区数据 - 区
    testDistrict = areaRepository.create({
      name: '朝阳区',
      code: '110105',
      level: AreaLevel.DISTRICT,
      parentId: testCity.id
    });
    await areaRepository.save(testDistrict);

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

  describe('GET /delivery-address', () => {
    it('应该返回配送地址列表', async () => {
      const response = await client.index.$get({
        query: {}
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      console.debug('配送地址列表响应状态:', response.status);
      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data).toHaveProperty('data');
        expect(Array.isArray(data.data)).toBe(true);
      }
    });

    it('应该拒绝未认证用户的访问', async () => {
      const response = await client.index.$get({
        query: {}
      });
      expect(response.status).toBe(401);
    });
  });

  describe('POST /delivery-address', () => {
    it('应该成功创建配送地址', async () => {
      const createData = {
        name: '张三',
        phone: '13800138000',
        address: '朝阳区建国路88号',
        receiverProvince: testProvince.id,
        receiverCity: testCity.id,
        receiverDistrict: testDistrict.id,
        receiverTown: 0,
        state: 1,
        isDefault: 1
      };

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

      console.debug('创建配送地址响应状态:', response.status);
      expect(response.status).toBe(201);

      if (response.status === 201) {
        const data = await response.json();
        expect(data).toHaveProperty('id');
        expect(data.name).toBe(createData.name);
        expect(data.phone).toBe(createData.phone);
        expect(data.address).toBe(createData.address);
        expect(data.receiverProvince).toBe(createData.receiverProvince);
        expect(data.receiverCity).toBe(createData.receiverCity);
        expect(data.receiverDistrict).toBe(createData.receiverDistrict);
        expect(data.isDefault).toBe(createData.isDefault);
      }
    });

    it('应该验证创建配送地址的必填字段', async () => {
      const invalidData = {
        // 缺少必填字段
        name: '',
        phone: '',
        address: '',
        receiverProvince: 0,
        receiverCity: 0,
        receiverDistrict: 0
      };

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

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

    it('应该验证地区层级关系', async () => {
      // 使用不存在的地区ID
      const invalidAreaData = {
        name: '李四',
        phone: '13900139000',
        address: '测试地址',
        receiverProvince: 999999, // 不存在的省份
        receiverCity: testCity.id,
        receiverDistrict: testDistrict.id,
        receiverTown: 0,
        state: 1,
        isDefault: 0
      };

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

      console.debug('地区验证响应状态:', response.status);
      expect(response.status).toBe(400);
    });
  });

  describe('GET /delivery-address/:id', () => {
    it('应该返回指定配送地址的详情', async () => {
      // 先创建一个配送地址
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const deliveryAddressRepository = dataSource.getRepository(DeliveryAddress);
      const testDeliveryAddress = deliveryAddressRepository.create({
        userId: testUser.id,
        name: '王五',
        phone: '13600136000',
        address: '海淀区中关村大街1号',
        receiverProvince: testProvince.id,
        receiverCity: testCity.id,
        receiverDistrict: testDistrict.id,
        receiverTown: 0,
        state: 1,
        isDefault: 0,
        createdBy: testUser.id
      });
      await deliveryAddressRepository.save(testDeliveryAddress);

      const response = await client[':id'].$get({
        param: { id: testDeliveryAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      console.debug('配送地址详情响应状态:', response.status);
      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data.id).toBe(testDeliveryAddress.id);
        expect(data.name).toBe(testDeliveryAddress.name);
        expect(data.phone).toBe(testDeliveryAddress.phone);
        expect(data.address).toBe(testDeliveryAddress.address);

        // 验证地区数据关联
        expect(data.province).toBeDefined();
        expect(data.province.id).toBe(testProvince.id);
        expect(data.city).toBeDefined();
        expect(data.city.id).toBe(testCity.id);
        expect(data.district).toBeDefined();
        expect(data.district.id).toBe(testDistrict.id);
      }
    });

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

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

  describe('PUT /delivery-address/:id', () => {
    it('应该成功更新配送地址', async () => {
      // 先创建一个配送地址
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const deliveryAddressRepository = dataSource.getRepository(DeliveryAddress);
      const testDeliveryAddress = deliveryAddressRepository.create({
        userId: testUser.id,
        name: '原始姓名',
        phone: '13500135000',
        address: '原始地址',
        receiverProvince: testProvince.id,
        receiverCity: testCity.id,
        receiverDistrict: testDistrict.id,
        receiverTown: 0,
        state: 1,
        isDefault: 0,
        createdBy: testUser.id
      });
      await deliveryAddressRepository.save(testDeliveryAddress);

      const updateData = {
        name: '更新后的姓名',
        phone: '13700137000',
        address: '更新后的地址',
        isDefault: 1
      };

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

      console.debug('更新配送地址响应状态:', response.status);
      expect(response.status).toBe(200);

      if (response.status === 200) {
        const data = await response.json();
        expect(data.name).toBe(updateData.name);
        expect(data.phone).toBe(updateData.phone);
        expect(data.address).toBe(updateData.address);
        expect(data.isDefault).toBe(updateData.isDefault);
      }
    });
  });

  describe('DELETE /delivery-address/:id', () => {
    it('应该成功删除配送地址', async () => {
      // 先创建一个配送地址
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const deliveryAddressRepository = dataSource.getRepository(DeliveryAddress);
      const testDeliveryAddress = deliveryAddressRepository.create({
        userId: testUser.id,
        name: '待删除地址',
        phone: '13400134000',
        address: '待删除地址',
        receiverProvince: testProvince.id,
        receiverCity: testCity.id,
        receiverDistrict: testDistrict.id,
        receiverTown: 0,
        state: 1,
        isDefault: 0,
        createdBy: testUser.id
      });
      await deliveryAddressRepository.save(testDeliveryAddress);

      const response = await client[':id'].$delete({
        param: { id: testDeliveryAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      console.debug('删除配送地址响应状态:', response.status);
      expect(response.status).toBe(204);

      // 验证配送地址确实被删除
      const deletedDeliveryAddress = await deliveryAddressRepository.findOne({
        where: { id: testDeliveryAddress.id }
      });
      expect(deletedDeliveryAddress).toBeNull();
    });
  });

  describe('省市区关联测试', () => {
    it('应该正确关联省市区数据', async () => {
      // 创建配送地址
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const deliveryAddressRepository = dataSource.getRepository(DeliveryAddress);
      const testDeliveryAddress = deliveryAddressRepository.create({
        userId: testUser.id,
        name: '关联测试',
        phone: '13300133000',
        address: '关联测试地址',
        receiverProvince: testProvince.id,
        receiverCity: testCity.id,
        receiverDistrict: testDistrict.id,
        receiverTown: 0,
        state: 1,
        isDefault: 0,
        createdBy: testUser.id
      });
      await deliveryAddressRepository.save(testDeliveryAddress);

      // 查询配送地址详情，验证地区关联
      const response = await client[':id'].$get({
        param: { id: testDeliveryAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${testToken}`
        }
      });

      expect(response.status).toBe(200);
      const data = await response.json();

      // 验证省市区关联数据
      expect(data.province).toBeDefined();
      expect(data.province.name).toBe('北京市');
      expect(data.province.level).toBe(AreaLevel.PROVINCE);

      expect(data.city).toBeDefined();
      expect(data.city.name).toBe('北京市');
      expect(data.city.level).toBe(AreaLevel.CITY);

      expect(data.district).toBeDefined();
      expect(data.district.name).toBe('朝阳区');
      expect(data.district.level).toBe(AreaLevel.DISTRICT);
    });

    it('应该验证地区层级关系', async () => {
      // 创建另一个区级地区，但父级不是市级
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const areaRepository = dataSource.getRepository(AreaEntity);

      const invalidDistrict = areaRepository.create({
        name: '无效区',
        code: '999999',
        level: AreaLevel.DISTRICT,
        parentId: testProvince.id // 父级是省，不是市
      });
      await areaRepository.save(invalidDistrict);

      // 尝试使用无效的地区层级关系创建地址
      const createData = {
        name: '层级测试',
        phone: '13200132000',
        address: '层级测试地址',
        receiverProvince: testProvince.id,
        receiverCity: testCity.id,
        receiverDistrict: invalidDistrict.id, // 这个区的父级不是testCity
        receiverTown: 0,
        state: 1,
        isDefault: 0
      };

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

      console.debug('地区层级验证响应状态:', response.status);
      // 这里期望返回400，因为地区层级关系不匹配
      expect(response.status).toBe(400);
    });
  });
});