import { OrderService } from '../OrderService';
import db from '../../config/database';
import { BullMQService } from '../BullMQService';

// 模拟依赖
jest.mock('../../config/database');
jest.mock('../BullMQService');
jest.mock('../../utils/logger');

describe('OrderService', () => {
  beforeAll(async () => {
    // 初始化测试环境
    await OrderService.initTables();
  });

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

  describe('createOrder', () => {
    it('should create a new order', async () => {
      const orderData = {
        tenant_id: 'test-tenant',
        shop_id: 'test-shop',
        platform: 'SHOPIFY' as const,
        platform_order_id: '12345',
        customer_name: 'Test Customer',
        customer_email: 'test@example.com',
        shipping_address: { street: '123 Test St', city: 'Test City' },
        items: [{ skuId: 'SKU001', title: 'Test Product', price: 100, quantity: 1 }],
        total_amount: 100,
        currency: 'USD',
        status: 'PAID' as const,
        payment_status: 'COMPLETED' as const,
        fulfillment_status: 'PENDING' as const,
        trace_id: 'test-trace-id',
      };

      const orderId = await OrderService.createOrder(orderData);
      expect(orderId).toMatch(/ORD-\d+-\d+/);
      expect(BullMQService.addJob).toHaveBeenCalledWith('order.created', {
        orderId,
        tenantId: 'test-tenant',
      });
    });
  });

  describe('getOrderById', () => {
    it('should return order by id', async () => {
      const orderId = 'ORD-12345-67890';
      const tenantId = 'test-tenant';

      // 模拟数据库查询
      (db as any).mockImplementation(() => ({
        where: jest.fn().mockReturnThis(),
        first: jest.fn().mockResolvedValue({
          id: orderId,
          tenant_id: tenantId,
          platform: 'SHOPIFY',
          platform_order_id: '12345',
          customer_name: 'Test Customer',
          shipping_address: JSON.stringify({ street: '123 Test St' }),
          items: JSON.stringify([{ skuId: 'SKU001', title: 'Test Product' }]),
          total_amount: 100,
          status: 'PAID',
        }),
      }));

      const order = await OrderService.getOrderById(orderId, tenantId);
      expect(order).toBeDefined();
      expect(order?.id).toBe(orderId);
    });

    it('should return null if order not found', async () => {
      const orderId = 'ORD-99999-99999';
      const tenantId = 'test-tenant';

      // 模拟数据库查询返回空
      (db as any).mockImplementation(() => ({
        where: jest.fn().mockReturnThis(),
        first: jest.fn().mockResolvedValue(null),
      }));

      const order = await OrderService.getOrderById(orderId, tenantId);
      expect(order).toBeNull();
    });
  });

  describe('updateOrder', () => {
    it('should update order', async () => {
      const orderId = 'ORD-12345-67890';
      const tenantId = 'test-tenant';
      const updates = {
        status: 'SHIPPED' as const,
        fulfillment_status: 'SHIPPED' as const,
      };

      // 模拟数据库更新
      (db as any).mockImplementation(() => ({
        where: jest.fn().mockReturnThis(),
        update: jest.fn().mockResolvedValue(1),
      }));

      await OrderService.updateOrder(orderId, tenantId, updates);
      expect(BullMQService.addJob).toHaveBeenCalledWith('order.updated', {
        orderId,
        tenantId,
        updates,
      });
    });
  });

  describe('deleteOrder', () => {
    it('should delete order', async () => {
      const orderId = 'ORD-12345-67890';
      const tenantId = 'test-tenant';

      // 模拟数据库删除
      (db as any).mockImplementation(() => ({
        where: jest.fn().mockReturnThis(),
        del: jest.fn().mockResolvedValue(1),
      }));

      await OrderService.deleteOrder(orderId, tenantId);
      expect(BullMQService.addJob).toHaveBeenCalledWith('order.deleted', {
        orderId,
        tenantId,
      });
    });
  });

  describe('getOrders', () => {
    it('should return orders with pagination', async () => {
      const tenantId = 'test-tenant';
      const params = {
        page: 1,
        pageSize: 20,
        status: 'PAID',
      };

      // 模拟数据库查询
      const mockOrders = [
        {
          id: 'ORD-1',
          tenant_id: tenantId,
          platform: 'SHOPIFY',
          status: 'PAID',
          shipping_address: JSON.stringify({ street: '123 Test St' }),
          items: JSON.stringify([{ skuId: 'SKU001' }]),
        },
      ];

      (db as any).mockImplementation(() => ({
        where: jest.fn().mockReturnThis(),
        count: jest.fn().mockResolvedValue([{ count: 1 }]),
        offset: jest.fn().mockReturnThis(),
        limit: jest.fn().mockReturnThis(),
        orderBy: jest.fn().mockResolvedValue(mockOrders),
      }));

      const result = await OrderService.getOrders(tenantId, params);
      expect(result.orders).toHaveLength(1);
      expect(result.total).toBe(1);
    });
  });

  describe('transitionOrderStatus', () => {
    it('should transition order status', async () => {
      const orderId = 'ORD-12345-67890';
      const tenantId = 'test-tenant';
      const nextStatus = 'SHIPPED' as const;
      const reason = 'Order shipped';

      // 模拟现有服务的状态流转
      const mockConsumerOrderService = {
        transitionStatus: jest.fn().mockResolvedValue(undefined),
      };

      // 模拟getOrderById
      (OrderService as any).getOrderById = jest.fn().mockResolvedValue({
        id: orderId,
        status: 'PAID',
      });

      // 模拟clearOrderCache
      (OrderService as any).clearOrderCache = jest.fn().mockResolvedValue(undefined);

      await OrderService.transitionOrderStatus(tenantId, orderId, nextStatus, reason);
      expect(BullMQService.addJob).toHaveBeenCalledWith('order.status.changed', expect.objectContaining({
        orderId,
        tenantId,
        newStatus: nextStatus,
        reason,
      }));
    });
  });

  describe('batchUpdateOrders', () => {
    it('should batch update orders', async () => {
      const tenantId = 'test-tenant';
      const orderIds = ['ORD-1', 'ORD-2'];
      const updates = {
        status: 'PAID' as const,
      };

      // 模拟updateOrder
      (OrderService as any).updateOrder = jest.fn().mockResolvedValue(undefined);

      const result = await OrderService.batchUpdateOrders(tenantId, orderIds, updates);
      expect(result.success).toBe(2);
      expect(result.failed).toBe(0);
    });
  });
});
