import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import { testClient } from 'hono/testing';
import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities, TestDataFactory } from '@d8d/shared-test-util';
import { JWTUtil } from '@d8d/shared-utils';
import { UserEntityMt, RoleMt } from '@d8d/user-module-mt';
import { AreaEntityMt, AreaLevel } from '@d8d/geo-areas-mt';
import { FileMt } from '@d8d/file-module-mt';
import { userDeliveryAddressRoutesMt } from '../../src/routes';
import { DeliveryAddressMt } from '../../src/entities';

// 设置集成测试钩子
setupIntegrationDatabaseHooksWithEntities([UserEntityMt, RoleMt, AreaEntityMt, DeliveryAddressMt, FileMt])

describe('用户配送地址管理API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof userDeliveryAddressRoutesMt>>;
  let userToken: string;
  let otherUserToken: string;
  let testUser: UserEntityMt;
  let otherUser: UserEntityMt;
  let testProvince: AreaEntityMt;
  let testCity: AreaEntityMt;
  let testDistrict: AreaEntityMt;

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

    // 使用测试数据工厂创建完整测试数据集
    const testData = await TestDataFactory.createTestDataSet(1);
    testUser = testData.user;
    otherUser = testData.otherUser;
    testProvince = testData.province;
    testCity = testData.city;
    testDistrict = testData.district;

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

    // 生成其他用户的token
    otherUserToken = JWTUtil.generateToken({
      id: otherUser.id,
      username: otherUser.username,
      roles: [{name:'user'}]
    });
  });

  describe('GET /delivery-address', () => {
    it('应该返回当前用户的配送地址列表', async () => {
      // 为测试用户创建一些地址
      const userAddress1 = await TestDataFactory.createTestDeliveryAddress(
        testUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '用户地址1',
          phone: '13800138001',
          address: '用户地址1'
        }
      );

      const userAddress2 = await TestDataFactory.createTestDeliveryAddress(
        testUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '用户地址2',
          phone: '13800138002',
          address: '用户地址2'
        }
      );

      // 为其他用户创建一个地址，确保不会返回
      const otherUserAddress = await TestDataFactory.createTestDeliveryAddress(
        otherUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '其他用户地址',
          phone: '13800138003',
          address: '其他用户地址'
        }
      );

      const response = await client.index.$get({
        query: {}
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });

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

      if (response.status === 200) {
        const data = await response.json();
        if (data && 'data' in data) {
          expect(Array.isArray(data.data)).toBe(true);
          // 应该只返回当前用户的地址
          data.data.forEach((address: any) => {
            expect(address.user?.id).toBe(testUser.id);
          });
        }
      }
    });

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

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

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

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

      if (response.status === 201) {
        const data = await response.json();
        console.debug('用户创建地址响应数据:', JSON.stringify(data, null, 2));
        expect(data).toHaveProperty('id');
        expect(data.userId).toBe(testUser.id); // 自动使用当前用户ID
        expect(data.name).toBe(createData.name);
        expect(data.phone).toBe(createData.phone);
        expect(data.address).toBe(createData.address);
      }
    });

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

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

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

  describe('GET /delivery-address/:id', () => {
    it('应该返回当前用户的配送地址详情', async () => {
      // 先为当前用户创建一个配送地址
      const testDeliveryAddress = await TestDataFactory.createTestDeliveryAddress(
        testUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '王五',
          phone: '13600136000',
          address: '海淀区中关村大街1号'
        }
      );

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

      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.user?.id).toBe(testUser.id);
        expect(data.name).toBe(testDeliveryAddress.name);
        expect(data.phone).toBe(testDeliveryAddress.phone);
        expect(data.address).toBe(testDeliveryAddress.address);
      }
    });

    it('应该拒绝访问其他用户的配送地址', async () => {
      // 为其他用户创建一个配送地址
      const otherUserAddress = await TestDataFactory.createTestDeliveryAddress(
        otherUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '其他用户地址',
          phone: '13600136001',
          address: '其他用户地址'
        }
      );

      // 当前用户尝试访问其他用户的地址
      const response = await client[':id'].$get({
        param: { id: otherUserAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });

      console.debug('用户访问其他用户地址响应状态:', response.status);
      expect(response.status).toBe(403); // 数据权限控制返回403
    });

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

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

  describe('PUT /delivery-address/:id', () => {
    it('应该成功更新当前用户的配送地址', async () => {
      // 先为当前用户创建一个配送地址
      const testDeliveryAddress = await TestDataFactory.createTestDeliveryAddress(
        testUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '原始姓名',
          phone: '13500135000',
          address: '原始地址'
        }
      );

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

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

      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);
      }
    });

    it('应该拒绝更新其他用户的配送地址', async () => {
      // 为其他用户创建一个配送地址
      const otherUserAddress = await TestDataFactory.createTestDeliveryAddress(
        otherUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '其他用户地址',
          phone: '13500135001',
          address: '其他用户地址'
        }
      );

      const updateData = {
        name: '尝试更新的姓名',
        phone: '13700137001',
        address: '尝试更新的地址'
      };

      // 当前用户尝试更新其他用户的地址
      const response = await client[':id'].$put({
        param: { id: otherUserAddress.id },
        json: updateData
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });

      console.debug('用户更新其他用户地址响应状态:', response.status);
      expect(response.status).toBe(403); // 数据权限控制返回403
    });
  });

  describe('DELETE /delivery-address/:id', () => {
    it('应该成功删除当前用户的配送地址', async () => {
      // 先为当前用户创建一个配送地址
      const testDeliveryAddress = await TestDataFactory.createTestDeliveryAddress(
        testUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '待删除地址',
          phone: '13400134000',
          address: '待删除地址'
        }
      );

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

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

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

    it('应该拒绝删除其他用户的配送地址', async () => {
      // 为其他用户创建一个配送地址
      const otherUserAddress = await TestDataFactory.createTestDeliveryAddress(
        otherUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '其他用户地址',
          phone: '13400134001',
          address: '其他用户地址'
        }
      );

      // 当前用户尝试删除其他用户的地址
      const response = await client[':id'].$delete({
        param: { id: otherUserAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });

      console.debug('用户删除其他用户地址响应状态:', response.status);
      expect(response.status).toBe(403); // 数据权限控制返回403
    });
  });

  describe('数据权限验证', () => {
    it('用户应该只能访问和操作自己的数据', async () => {
      // 为两个用户都创建地址
      const userAddress = await TestDataFactory.createTestDeliveryAddress(
        testUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '用户地址',
          phone: '13800138004',
          address: '用户地址'
        }
      );

      const otherUserAddress = await TestDataFactory.createTestDeliveryAddress(
        otherUser.id,
        testProvince.id,
        testCity.id,
        testDistrict.id,
        {
          name: '其他用户地址',
          phone: '13800138005',
          address: '其他用户地址'
        }
      );

      // 当前用户应该只能看到自己的地址
      const listResponse = await client.index.$get({
        query: {}
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });

      expect(listResponse.status).toBe(200);
      const listData = await listResponse.json();
      if (listData && 'data' in listData) {
        expect(Array.isArray(listData.data)).toBe(true);
        // 应该只包含当前用户的地址
        listData.data.forEach((address: any) => {
          expect(address.user?.id).toBe(testUser.id);
        });
      }

      // 当前用户应该无法访问其他用户的地址详情
      const getResponse = await client[':id'].$get({
        param: { id: otherUserAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });
      expect(getResponse.status).toBe(403);

      // 当前用户应该无法更新其他用户的地址
      const updateResponse = await client[':id'].$put({
        param: { id: otherUserAddress.id },
        json: { name: '尝试更新' }
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });
      expect(updateResponse.status).toBe(403);

      // 当前用户应该无法删除其他用户的地址
      const deleteResponse = await client[':id'].$delete({
        param: { id: otherUserAddress.id }
      }, {
        headers: {
          'Authorization': `Bearer ${userToken}`
        }
      });
      expect(deleteResponse.status).toBe(403);
    });
  });
});