import { TestBed } from '@angular/core/testing';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { CheckoutPrintFacade } from './checkout-print.facade';
import { CheckoutPrintService } from '../services';
import { ResponseArgs } from '@generated/swagger/print-api';

describe('CheckoutPrintFacade', () => {
  let facade: CheckoutPrintFacade;
  let mockCheckoutPrintService: {
    printOrderConfirmation: ReturnType<typeof vi.fn>;
  };

  beforeEach(() => {
    // Arrange: Create mock
    mockCheckoutPrintService = {
      printOrderConfirmation: vi.fn(),
    };

    TestBed.configureTestingModule({
      providers: [
        CheckoutPrintFacade,
        { provide: CheckoutPrintService, useValue: mockCheckoutPrintService },
      ],
    });

    facade = TestBed.inject(CheckoutPrintFacade);
  });

  it('should be created', () => {
    expect(facade).toBeTruthy();
  });

  it('should call printOrderConfirmation on service', async () => {
    // Arrange
    const params = {
      printer: 'printer-1',
      data: [123, 456],
    };
    const mockResponse: ResponseArgs = {
      error: false,
    };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      mockResponse,
    );

    // Act
    const result = await facade.printOrderConfirmation(params);

    // Assert
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenCalledWith(params);
    expect(result).toEqual(mockResponse);
  });

  it('should forward params correctly to service', async () => {
    // Arrange
    const params = {
      printer: 'label-printer',
      data: [789],
    };
    const mockResponse: ResponseArgs = {
      error: false,
    };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      mockResponse,
    );

    // Act
    await facade.printOrderConfirmation(params);

    // Assert
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenCalledWith(
      expect.objectContaining({
        printer: 'label-printer',
        data: [789],
      }),
    );
  });

  it('should handle empty order data array', async () => {
    // Arrange
    const params = {
      printer: 'printer-2',
      data: [],
    };
    const mockResponse: ResponseArgs = {
      error: false,
    };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      mockResponse,
    );

    // Act
    const result = await facade.printOrderConfirmation(params);

    // Assert
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenCalledWith(params);
    expect(result.error).toBe(false);
  });

  it('should handle multiple order IDs', async () => {
    // Arrange
    const params = {
      printer: 'main-printer',
      data: [1, 2, 3, 4, 5],
    };
    const mockResponse: ResponseArgs = {
      error: false,
    };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      mockResponse,
    );

    // Act
    const result = await facade.printOrderConfirmation(params);

    // Assert
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenCalledWith(params);
    expect(result).toEqual(mockResponse);
  });

  it('should return response from service', async () => {
    // Arrange
    const params = {
      printer: 'test-printer',
      data: [100, 200],
    };
    const expectedResponse: ResponseArgs = {
      error: false,
    };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      expectedResponse,
    );

    // Act
    const result = await facade.printOrderConfirmation(params);

    // Assert
    expect(result).toEqual(expectedResponse);
    expect(result.error).toBe(false);
  });

  it('should handle different printer types', async () => {
    // Arrange
    const labelParams = { printer: 'label-printer', data: [1] };
    const documentParams = { printer: 'document-printer', data: [2] };
    const mockResponse: ResponseArgs = { error: false };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      mockResponse,
    );

    // Act
    await facade.printOrderConfirmation(labelParams);
    await facade.printOrderConfirmation(documentParams);

    // Assert
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenCalledTimes(2);
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenNthCalledWith(1, labelParams);
    expect(
      mockCheckoutPrintService.printOrderConfirmation,
    ).toHaveBeenNthCalledWith(2, documentParams);
  });

  it('should propagate service response with all fields', async () => {
    // Arrange
    const params = {
      printer: 'printer-1',
      data: [123],
    };
    const detailedResponse: ResponseArgs = {
      error: false,
      message: 'Print job completed',
      requestId: 12345,
    };
    mockCheckoutPrintService.printOrderConfirmation.mockResolvedValue(
      detailedResponse,
    );

    // Act
    const result = await facade.printOrderConfirmation(params);

    // Assert
    expect(result).toMatchObject({
      error: false,
      message: 'Print job completed',
      requestId: 12345,
    });
  });
});
