import { Test, TestingModule } from '@nestjs/testing';
import { OperationAgentService } from './OperationAgentService';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Store } from '../../entities/Store';
import { PlatformAdapterFactory } from './adapters/PlatformAdapterFactory';
import { AmazonAdapter } from './adapters/AmazonAdapter';
import { ShopeeAdapter } from './adapters/ShopeeAdapter';
import { AliExpressAdapter } from './adapters/AliExpressAdapter';
import { TikTokAdapter } from './adapters/TikTokAdapter';
import { EbayAdapter } from './adapters/EbayAdapter';
import { GenericAdapter } from './adapters/GenericAdapter';
import { StoreBindingDto } from '../../api/dto/StoreBindingDto';
import { StoreStatus } from '../../types/enums/StoreStatus';
import { EventEmitter2 } from '@nestjs/event-emitter';

// 模拟Store实体
class MockStore {
  id: string;
  merchantId: string;
  name: string;
  platform: string;
  platformShopId: string;
  description: string;
  status: StoreStatus;
  created_at: Date;
  updated_at: Date;
}

// 模拟Repository
class MockRepository {
  findOne = jest.fn();
  find = jest.fn();
  create = jest.fn();
  save = jest.fn();
  findOneBy = jest.fn();
}

// 模拟平台适配器
class MockPlatformAdapter {
  authorize = jest.fn();
  getShopInfo = jest.fn();
  getProducts = jest.fn();
  getOrders = jest.fn();
  updateProductPrice = jest.fn();
  updateProductStock = jest.fn();
  listProduct = jest.fn();
  delistProduct = jest.fn();
  getApiStatus = jest.fn();
}

describe('OperationAgentIntegration', () => {
  let service: OperationAgentService;
  let storeRepository: Repository<Store>;
  let eventEmitter: EventEmitter2;
  let mockAdapter: MockPlatformAdapter;

  beforeEach(async () => {
    mockAdapter = new MockPlatformAdapter();

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        OperationAgentService,
        {
          provide: getRepositoryToken(Store),
          useClass: MockRepository,
        },
        {
          provide: PlatformAdapterFactory,
          useValue: {
            createAdapter: jest.fn().mockReturnValue(mockAdapter),
          },
        },
        {
          provide: EventEmitter2,
          useValue: {
            emit: jest.fn(),
          },
        },
        {
          provide: AmazonAdapter,
          useValue: new MockPlatformAdapter(),
        },
        {
          provide: ShopeeAdapter,
          useValue: new MockPlatformAdapter(),
        },
        {
          provide: AliExpressAdapter,
          useValue: new MockPlatformAdapter(),
        },
        {
          provide: TikTokAdapter,
          useValue: new MockPlatformAdapter(),
        },
        {
          provide: EbayAdapter,
          useValue: new MockPlatformAdapter(),
        },
        {
          provide: GenericAdapter,
          useValue: new MockPlatformAdapter(),
        },
      ],
    }).compile();

    service = module.get<OperationAgentService>(OperationAgentService);
    storeRepository = module.get<Repository<Store>>(getRepositoryToken(Store));
    eventEmitter = module.get<EventEmitter2>(EventEmitter2);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('完整的店铺绑定和同步流程', () => {
    it('应该成功绑定店铺并同步商品和订单', async () => {
      // 准备测试数据
      const dto: StoreBindingDto = {
        merchantId: 'merchant-1',
        platform: 'amazon',
        platformShopId: 'amazon-shop-1',
        name: 'Test Store',
        description: 'Test Store Description',
        authInfo: {
          accessKey: 'test-access-key',
          secretKey: 'test-secret-key',
          sellerId: 'test-seller-id',
          marketplaceId: 'test-marketplace-id',
        },
      };

      const store = {
        id: 'store-1',
        ...dto,
        status: StoreStatus.ACTIVE,
        created_at: new Date(),
        updated_at: new Date(),
      };

      const products = [
        {
          id: 'product-1',
          name: 'Product 1',
          sku: 'PROD-1',
          price: 100,
          stock: 10,
          description: 'Product 1 Description',
          images: ['image1.jpg'],
          categories: ['Category 1'],
          attributes: {},
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      ];

      const orders = [
        {
          id: 'order-1',
          customerId: 'customer-1',
          totalAmount: 200,
          status: 'shipped',
          items: [
            {
              productId: 'product-1',
              quantity: 1,
              price: 200,
            },
          ],
          shippingAddress: {
            name: 'Customer 1',
            address: '123 Main St',
            city: 'New York',
            state: 'NY',
            zip: '10001',
            country: 'US',
          },
          paymentMethod: 'credit_card',
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      ];

      // 模拟方法调用
      (storeRepository.findOne as jest.Mock).mockResolvedValue(null);
      (storeRepository.create as jest.Mock).mockReturnValue({
        id: 'store-1',
        ...dto,
        status: StoreStatus.PENDING,
        created_at: new Date(),
        updated_at: new Date(),
      });
      (storeRepository.save as jest.Mock).mockResolvedValueOnce({
        id: 'store-1',
        ...dto,
        status: StoreStatus.PENDING,
        created_at: new Date(),
        updated_at: new Date(),
      }).mockResolvedValueOnce({
        id: 'store-1',
        ...dto,
        status: StoreStatus.ACTIVE,
        created_at: new Date(),
        updated_at: new Date(),
      });
      (storeRepository.findOneBy as jest.Mock).mockResolvedValue(store);
      mockAdapter.authorize.mockResolvedValue(true);
      mockAdapter.getShopInfo.mockResolvedValue({
        id: 'amazon-shop-1',
        name: 'Test Store',
        description: 'Test Store Description',
        status: 'active',
        createdAt: new Date(),
        updatedAt: new Date(),
      });
      mockAdapter.getProducts.mockResolvedValue(products);
      mockAdapter.getOrders.mockResolvedValue(orders);

      // 步骤1: 绑定店铺
      const boundStore = await service.bindStore(dto);
      expect(boundStore.status).toBe(StoreStatus.ACTIVE);

      // 步骤2: 同步商品
      const syncProductsResult = await service.syncProducts(boundStore.id);
      expect(syncProductsResult.success).toBe(true);
      expect(syncProductsResult.count).toBe(products.length);

      // 步骤3: 同步订单
      const syncOrdersResult = await service.syncOrders(boundStore.id);
      expect(syncOrdersResult.success).toBe(true);
      expect(syncOrdersResult.count).toBe(orders.length);

      // 验证事件触发
      expect(eventEmitter.emit).toHaveBeenCalledWith('operation_agent.store.bound', expect.any(Object));
      expect(eventEmitter.emit).toHaveBeenCalledWith('operation_agent.products.synced', {
        storeId: boundStore.id,
        count: products.length,
      });
      expect(eventEmitter.emit).toHaveBeenCalledWith('operation_agent.orders.synced', {
        storeId: boundStore.id,
        count: orders.length,
      });
    });
  });

  describe('店铺状态管理流程', () => {
    it('应该成功停用和重新激活店铺', async () => {
      // 准备测试数据
      const store = {
        id: 'store-1',
        merchantId: 'merchant-1',
        name: 'Test Store',
        platform: 'amazon',
        platformShopId: 'amazon-shop-1',
        status: StoreStatus.ACTIVE,
        created_at: new Date(),
        updated_at: new Date(),
      };

      const deactivatedStore = {
        ...store,
        status: StoreStatus.INACTIVE,
      };

      const reactivatedStore = {
        ...store,
        status: StoreStatus.ACTIVE,
      };

      // 模拟方法调用
      (storeRepository.findOneBy as jest.Mock)
        .mockResolvedValueOnce(store) // 停用店铺时
        .mockResolvedValueOnce(deactivatedStore); // 重新激活时
      (storeRepository.save as jest.Mock)
        .mockResolvedValueOnce(deactivatedStore) // 停用店铺时
        .mockResolvedValueOnce(reactivatedStore); // 重新激活时

      // 步骤1: 停用店铺
      const result1 = await service.deactivateStore(store.id);
      expect(result1.status).toBe(StoreStatus.INACTIVE);

      // 步骤2: 重新激活店铺
      const result2 = await service.reactivateStore(store.id);
      expect(result2.status).toBe(StoreStatus.ACTIVE);

      // 验证事件触发
      expect(eventEmitter.emit).toHaveBeenCalledWith('operation_agent.store.deactivated', deactivatedStore);
      expect(eventEmitter.emit).toHaveBeenCalledWith('operation_agent.store.activated', reactivatedStore);
    });
  });

  describe('商品价格更新流程', () => {
    it('应该成功更新商品价格', async () => {
      // 准备测试数据
      const store = {
        id: 'store-1',
        merchantId: 'merchant-1',
        name: 'Test Store',
        platform: 'amazon',
        platformShopId: 'amazon-shop-1',
        status: StoreStatus.ACTIVE,
        created_at: new Date(),
        updated_at: new Date(),
      };

      const productId = 'product-1';
      const newPrice = 150;

      // 模拟方法调用
      (storeRepository.findOneBy as jest.Mock).mockResolvedValue(store);
      mockAdapter.updateProductPrice.mockResolvedValue(true);

      // 执行测试
      const result = await service.updateProductPrice(store.id, productId, newPrice);
      expect(result).toBe(true);

      // 验证事件触发
      expect(eventEmitter.emit).toHaveBeenCalledWith('operation_agent.product.price.updated', {
        storeId: store.id,
        productId,
        price: newPrice,
      });
    });
  });
});
