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 { UserEntityMt, RoleMt } from '@d8d/user-module-mt';
import { FileMt } from '@d8d/file-module-mt';
import { SupplierMt } from '@d8d/supplier-module-mt';
import { MerchantMt } from '@d8d/merchant-module-mt';
import { adminGoodsRoutesMt } from '../../src/routes/index.mt';
import { GoodsMt, GoodsCategoryMt } from '../../src/entities/index.mt';
import { GoodsTestFactory } from '../factories/goods-test-factory';

// 设置集成测试钩子
setupIntegrationDatabaseHooksWithEntities([
  UserEntityMt, RoleMt, GoodsMt, GoodsCategoryMt, FileMt, SupplierMt, MerchantMt
])

describe('管理员父子商品管理API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof adminGoodsRoutesMt>>;
  let adminToken: string;
  let testUser: UserEntityMt;
  let testAdmin: UserEntityMt;
  let testCategory: GoodsCategoryMt;
  let testSupplier: SupplierMt;
  let testMerchant: MerchantMt;
  let testFactory: GoodsTestFactory;
  let parentGoods: GoodsMt;
  let childGoods1: GoodsMt;
  let childGoods2: GoodsMt;

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

    // 获取数据源并创建测试工厂
    const dataSource = await IntegrationTestDatabase.getDataSource();
    testFactory = new GoodsTestFactory(dataSource);

    // 使用测试工厂创建测试数据
    testUser = await testFactory.createTestUser();
    testAdmin = await testFactory.createTestAdmin();
    testCategory = await testFactory.createTestCategory(testUser.id);
    testSupplier = await testFactory.createTestSupplier(testUser.id);
    testMerchant = await testFactory.createTestMerchant(testUser.id);

    // 生成测试管理员的token
    adminToken = JWTUtil.generateToken({
      id: testAdmin.id,
      username: testAdmin.username,
      roles: [{name:'admin'}]
    });

    // 创建父商品
    parentGoods = await testFactory.createTestGoods(testUser.id, {
      name: '父商品测试',
      price: 200.00,
      costPrice: 150.00,
      categoryId1: testCategory.id,
      categoryId2: testCategory.id,
      categoryId3: testCategory.id,
      supplierId: testSupplier.id,
      merchantId: testMerchant.id,
      stock: 100,
      spuId: 0, // 父商品
      spuName: null
    });

    // 创建子商品1
    childGoods1 = await testFactory.createTestGoods(testUser.id, {
      name: '子商品1 - 红色',
      price: 210.00,
      costPrice: 160.00,
      categoryId1: testCategory.id,
      categoryId2: testCategory.id,
      categoryId3: testCategory.id,
      supplierId: testSupplier.id,
      merchantId: testMerchant.id,
      stock: 50,
      spuId: parentGoods.id, // 父商品ID
      spuName: parentGoods.name
    });

    // 创建子商品2
    childGoods2 = await testFactory.createTestGoods(testUser.id, {
      name: '子商品2 - 蓝色',
      price: 220.00,
      costPrice: 170.00,
      categoryId1: testCategory.id,
      categoryId2: testCategory.id,
      categoryId3: testCategory.id,
      supplierId: testSupplier.id,
      merchantId: testMerchant.id,
      stock: 60,
      spuId: parentGoods.id, // 父商品ID
      spuName: parentGoods.name
    });
  });

  describe('GET /goods/:id/children', () => {
    it('应该成功获取父商品的子商品列表', async () => {
      const response = await client[':id']['children'].$get({
        param: { id: parentGoods.id },
        query: { page: 1, pageSize: 10 }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

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

        expect(data.data).toHaveLength(2);
        expect(data.total).toBe(2);
        expect(data.page).toBe(1);
        expect(data.pageSize).toBe(10);
        expect(data.totalPages).toBe(1);

        // 验证子商品数据
        const childIds = data.data.map((item) => item.id);
        expect(childIds).toContain(childGoods1.id);
        expect(childIds).toContain(childGoods2.id);
      }
    });

    it('应该验证父商品是否存在', async () => {
      const response = await client[':id']['children'].$get({
        param: { id: 99999 }, // 不存在的商品ID
        query: { page: 1, pageSize: 10 }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(404);
      if (response.status === 404) {
        const data = await response.json();
        expect(data.code).toBe(404);
        expect(data.message).toContain('父商品不存在');
      }
    });

    it('应该支持搜索关键词过滤', async () => {
      const response = await client[':id']['children'].$get({
        param: { id: parentGoods.id },
        query: { page: 1, pageSize: 10, keyword: '红色' }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(200);
      if (response.status === 200) {
        const data = await response.json();
        expect(data.data).toHaveLength(1);
        expect(data.data[0].name).toBe('子商品1 - 红色');
      }
    });

    it('应该支持排序', async () => {
      const response = await client[':id']['children'].$get({
        param: { id: parentGoods.id },
        query: { page: 1, pageSize: 10, sortBy: 'price', sortOrder: 'DESC' }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(200);
      if (response.status === 200) {
        const data = await response.json();
        expect(data.data).toHaveLength(2);
        // 价格降序排列：220 > 210
        expect(data.data[0].price).toBe(220.00);
        expect(data.data[1].price).toBe(210.00);
      }
    });
  });

  describe('POST /goods/:id/set-as-parent', () => {
    it('应该成功将普通商品设为父商品', async () => {
      // 创建一个普通商品（不是子商品）
      const normalGoods = await testFactory.createTestGoods(testUser.id, {
        name: '普通商品',
        price: 300.00,
        costPrice: 250.00,
        categoryId1: testCategory.id,
        categoryId2: testCategory.id,
        categoryId3: testCategory.id,
        supplierId: testSupplier.id,
        merchantId: testMerchant.id,
        stock: 80,
        spuId: 0,
        spuName: null
      });

      const response = await client[':id']['set-as-parent'].$post({
        param: { id: normalGoods.id }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(200);
      if (response.status === 200) {
        const data = await response.json();
        expect(data.id).toBe(normalGoods.id);
                expect(data.spuId).toBe(0);
        expect(data.spuName).toBeUndefined(); // spuName字段已从API响应中移除
      }
    });

    it('应该拒绝将子商品设为父商品', async () => {
      const response = await client[':id']['set-as-parent'].$post({
        param: { id: childGoods1.id }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(400);
      if (response.status === 400) {
        const data = await response.json();
        expect(data.code).toBe(400);
        expect(data.message).toContain('子商品不能设为父商品');
      }
    });

    it('应该验证商品是否存在', async () => {
      const response = await client[':id']['set-as-parent'].$post({
        param: { id: 99999 }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(404);
      if (response.status === 404) {
        const data = await response.json();
        expect(data.code).toBe(404);
        expect(data.message).toContain('商品不存在');
      }
    });
  });

  describe('DELETE /goods/:id/parent', () => {
    it('应该成功解除子商品的父子关系', async () => {
      const response = await client[':id']['parent'].$delete({
        param: { id: childGoods1.id }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(200);
      if (response.status === 200) {
        const data = await response.json();
        expect(data.id).toBe(childGoods1.id);
        expect(data.spuId).toBe(0);
        expect(data.spuName).toBeUndefined(); // spuName字段已从API响应中移除
      }
    });

    it('应该拒绝解除非子商品的父子关系', async () => {
      const response = await client[':id']['parent'].$delete({
        param: { id: parentGoods.id }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(400);
      if (response.status === 400) {
        const data = await response.json();
        expect(data.code).toBe(400);
      expect(data.message).toContain('该商品不是子商品');
      }
    });

    it('应该验证商品是否存在', async () => {
      const response = await client[':id']['parent'].$delete({
        param: { id: 99999 }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(404);
      if (response.status === 404) {
        const data = await response.json();
        expect(data.code).toBe(404);
      expect(data.message).toContain('商品不存在');
      }
    });
  });

  describe('POST /goods/batchCreateChildren', () => {
    it('应该成功批量创建子商品', async () => {
      const specs = [
        { name: '规格1 - 黑色', price: 230.00, costPrice: 180.00, stock: 50, sort: 1 },
        { name: '规格2 - 白色', price: 240.00, costPrice: 190.00, stock: 60, sort: 2 },
        { name: '规格3 - 金色', price: 250.00, costPrice: 200.00, stock: 70, sort: 3 }
      ];

      const response = await client.batchCreateChildren.$post({
        json: {
          parentGoodsId: parentGoods.id,
          specs
        }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(200);
      if (response.status === 200) {
        const data = await response.json();
        expect(data.success).toBe(true);
      expect(data.count).toBe(3);
      expect(data.children).toHaveLength(3);

      // 验证子商品数据
      data.children.forEach((child: any, index: number) => {
        expect(child.name).toBe(specs[index].name);
        expect(child.price).toBe(specs[index].price);
        expect(child.costPrice).toBe(specs[index].costPrice);
        expect(child.stock).toBe(specs[index].stock);
        expect(child.sort).toBe(specs[index].sort);
        expect(child.spuId).toBe(parentGoods.id);
        // spuName字段已从API响应中移除，改为通过parent对象获取父商品名称
        // expect(child.spuName).toBe(parentGoods.name);
      });
      }
    });

    it('应该验证父商品是否存在', async () => {
      const specs = [
        { name: '测试规格', price: 100.00, costPrice: 80.00, stock: 10, sort: 1 }
      ];

      const response = await client.batchCreateChildren.$post({
        json: {
          parentGoodsId: 99999,
          specs
        }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(404);
      if (response.status === 404) {
        const data = await response.json();
        expect(data.code).toBe(404);
      expect(data.message).toContain('父商品不存在');
      }
    });

    it('应该验证父商品必须是父商品', async () => {
      // 尝试为子商品创建子商品
      const specs = [
        { name: '测试规格', price: 100.00, costPrice: 80.00, stock: 10, sort: 1 }
      ];

      const response = await client.batchCreateChildren.$post({
        json: {
          parentGoodsId: childGoods1.id,
          specs
        }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(400);
      if (response.status === 400) {
        const data = await response.json();
        expect(data.code).toBe(400);
      expect(data.message).toContain('只能为父商品创建子商品');
      }
    });

    it('应该验证规格数据有效性', async () => {
      const specs = [
        { name: '', price: -100, costPrice: -80, stock: -10, sort: 1 } // 无效数据
      ];

      const response = await client.batchCreateChildren.$post({
        json: {
          parentGoodsId: parentGoods.id,
          specs
        }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(400);
      if (response.status === 400) {
        const data = await response.json();
        console.debug('验证规格数据有效性测试 - 响应状态:', response.status);
        console.debug('验证规格数据有效性测试 - 响应数据:', data);

        // Zod验证错误返回 { success: false, error: { name: 'ZodError', message: '...' } } 格式
        // 业务逻辑错误返回 { code: 400, message: '...' } 格式
        if ('success' in data && data.success === false) {
          expect(data.error.message).toMatch(/规格名称不能为空/);
        } else if ('code' in data) {
          expect(data.code).toBe(400);
          expect(data.message).toContain('规格名称不能为空');
        }
      }
    });

    it('应该继承父商品的分类和其他信息', async () => {
      const specs = [
        { name: '继承测试规格', price: 100.00, costPrice: 80.00, stock: 10, sort: 1 }
      ];

      const response = await client.batchCreateChildren.$post({
        json: {
          parentGoodsId: parentGoods.id,
          specs
        }
      }, {
        headers: {
          'Authorization': `Bearer ${adminToken}`
        }
      });

      expect(response.status).toBe(200);
      if (response.status === 200) {
        const data = await response.json();
        expect(data.success).toBe(true);
      expect(data.count).toBe(1);

      const child = data.children[0];
      expect(child.categoryId1).toBe(parentGoods.categoryId1);
      expect(child.categoryId2).toBe(parentGoods.categoryId2);
      expect(child.categoryId3).toBe(parentGoods.categoryId3);
      expect(child.supplierId).toBe(parentGoods.supplierId);
      expect(child.merchantId).toBe(parentGoods.merchantId);
      expect(child.goodsType).toBe(parentGoods.goodsType);
      }
    });
  });

  describe('认证和授权', () => {
    it('应该要求认证', async () => {
      const response = await client[':id']['children'].$get({
        param: { id: parentGoods.id },
        query: { page: 1, pageSize: 10 }
      });

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

    it('应该验证租户隔离', async () => {
      // 创建另一个租户的用户
      const dataSource = await IntegrationTestDatabase.getDataSource();
      const otherTenantUser = await testFactory.createTestUser(2); // 不同租户

      const otherTenantToken = JWTUtil.generateToken({
        id: otherTenantUser.id,
        username: otherTenantUser.username,
        roles: [{name:'admin'}]
      });

      const response = await client[':id']['children'].$get({
        param: { id: parentGoods.id },
        query: { page: 1, pageSize: 10 }
      }, {
        headers: {
          'Authorization': `Bearer ${otherTenantToken}`
        }
      });

      // 不同租户应该看不到其他租户的数据
      expect(response.status).toBe(404);
    });
  });
});
