import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { OrderRewardCollectFacade } from './order-reward-collect.facade';
import { OrderRewardCollectService } from '../services';
import { DBHOrderItemListItemDTO } from '@generated/swagger/oms-api';

describe('OrderRewardCollectFacade', () => {
  let spectator: SpectatorService<OrderRewardCollectFacade>;
  const createService = createServiceFactory({
    service: OrderRewardCollectFacade,
    mocks: [OrderRewardCollectService],
  });

  beforeEach(() => {
    spectator = createService();
  });

  describe('collect', () => {
    it('should delegate to OrderRewardCollectService.collect', async () => {
      // Arrange
      const mockParams = {
        orderId: 123,
        orderItemId: 456,
        orderItemSubsetId: 789,
        collectType: 1 as const, // Valid LoyaltyCollectType.Collect
        quantity: 2,
      };
      const mockResult: DBHOrderItemListItemDTO[] = [
        { orderItemType: 1 } as DBHOrderItemListItemDTO,
      ];
      const rewardItemService = spectator.inject(OrderRewardCollectService);
      (rewardItemService.collect as jest.Mock).mockResolvedValue(mockResult);

      // Act
      const result = await spectator.service.collect(mockParams);

      // Assert
      expect(result).toEqual(mockResult);
      expect(rewardItemService.collect).toHaveBeenCalledWith({
        orderId: mockParams.orderId,
        orderItemId: mockParams.orderItemId,
        orderItemSubsetId: mockParams.orderItemSubsetId,
        collectType: mockParams.collectType,
        quantity: mockParams.quantity,
      });
      expect(rewardItemService.collect).toHaveBeenCalledTimes(1);
    });

    it('should propagate errors from OrderRewardCollectService', async () => {
      // Arrange
      const mockParams = {
        orderId: 123,
        orderItemId: 456,
        orderItemSubsetId: 789,
        collectType: 1 as const, // Valid LoyaltyCollectType.Collect
        quantity: 2,
      };
      const errorMessage = 'Failed to collect reward item';
      const rewardItemService = spectator.inject(OrderRewardCollectService);
      (rewardItemService.collect as jest.Mock).mockRejectedValue(
        new Error(errorMessage),
      );

      // Act & Assert
      await expect(spectator.service.collect(mockParams)).rejects.toThrow(
        errorMessage,
      );
      expect(rewardItemService.collect).toHaveBeenCalledWith({
        orderId: mockParams.orderId,
        orderItemId: mockParams.orderItemId,
        orderItemSubsetId: mockParams.orderItemSubsetId,
        collectType: mockParams.collectType,
        quantity: mockParams.quantity,
      });
    });
  });

  describe('getOrderItemSubset', () => {
    it('should delegate to OrderRewardCollectService.fetchOrderItemSubset', async () => {
      // Arrange
      const mockParams = {
        orderItemSubsetId: 789,
      };
      const mockResult = {
        id: 789,
        quantity: 2,
        name: 'Test Subset',
      };
      const rewardItemService = spectator.inject(OrderRewardCollectService);
      (rewardItemService.fetchOrderItemSubset as jest.Mock).mockResolvedValue(
        mockResult,
      );

      // Act
      const result = await spectator.service.getOrderItemSubset(mockParams);

      // Assert
      expect(result).toEqual(mockResult);
      expect(rewardItemService.fetchOrderItemSubset).toHaveBeenCalledWith(
        mockParams,
        undefined,
      );
      expect(rewardItemService.fetchOrderItemSubset).toHaveBeenCalledTimes(1);
    });
  });
});
