import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator';
import { CustomerService, ListResponseArgsOfCustomerInfoDTO } from '@swagger/crm';
import { UiFilter } from '@ui/filter';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { cold, hot } from 'jasmine-marbles';
import { CustomerSearchStateSearchService } from './customer.search-state-search-service';

describe('CustomerSearchStateSearchService', () => {
  let spectator: SpectatorService<CustomerSearchStateSearchService>;
  let customerServiceMock: SpyObject<CustomerService>;
  let modalServiceMock: SpyObject<UiModalService>;
  const createService = createServiceFactory({
    service: CustomerSearchStateSearchService,
    mocks: [CustomerService, UiModalService],
  });

  beforeEach(() => {
    spectator = createService();
    customerServiceMock = spectator.inject(CustomerService);
    modalServiceMock = spectator.inject(UiModalService);
  });

  it('should create the service', () => {
    expect(spectator.service).toBeTruthy();
  });

  describe('search()', () => {
    it('should call _customerService.CustomerListCustomers with the query token and options', () => {
      customerServiceMock.CustomerListCustomers.and.returnValue(cold('-(a|)', { a: { hits: 5 } }));

      const filter = new UiFilter();
      spyOn(filter, 'getQueryToken').and.returnValue({ input: { qs: 'test' } });
      expect(spectator.service.search(filter, { skip: 10 })).toBeObservable(
        hot('-(a|)', { a: { hits: 5, error: false, items: [], message: undefined } })
      );
      expect(customerServiceMock.CustomerListCustomers).toHaveBeenCalledWith({
        input: { qs: 'test' },
        skip: 10,
        take: 25,
      });
    });

    it('should catch an Error and show UiErrorModalComponent', () => {
      customerServiceMock.CustomerListCustomers.and.returnValue(cold('-#', undefined, { message: 'error' }));

      const filter = new UiFilter();
      spyOn(filter, 'getQueryToken').and.returnValue({ input: { qs: 'test' } });
      expect(spectator.service.search(filter, { skip: 10 })).toBeObservable(hot('-(a|)', { a: {} }));
      expect(modalServiceMock.open).toHaveBeenCalledWith({
        content: UiErrorModalComponent,
        title: 'Fehler beim Laden der Kunden Suchergebnisse',
        data: { message: 'error' },
      });
    });
  });

  describe('mapResponseToSearchStateSearchResult()', () => {
    it('should return SearchStateSearchResult object with the params from ListResponseArgsOfCustomerInfoDTO', () => {
      const response: ListResponseArgsOfCustomerInfoDTO = {
        result: [],
        message: 'Test',
        hits: 30,
        error: true,
      };

      expect(spectator.service.mapResponseToSearchStateSearchResult(response)).toEqual({
        items: response.result,
        message: response.message,
        hits: response.hits,
        error: response.error,
      });
    });

    it('should return SearchStateSearchResult object with default values when the params from ListResponseArgsOfCustomerInfoDTO are not set', () => {
      const response: ListResponseArgsOfCustomerInfoDTO = { error: false };

      expect(spectator.service.mapResponseToSearchStateSearchResult(response)).toEqual({
        items: [],
        message: undefined,
        hits: 0,
        error: false,
      });
    });
  });
});
