import { createComponentFactory, mockProvider, Spectator, SpyObject } from '@ngneat/spectator';
import { ModalNotificationsComponent } from './notifications.component';
import { CommonModule } from '@angular/common';
import { UiModalRef, UiModalService } from '@ui/modal';
import { of } from 'rxjs';

describe('ModalNotificationsComponent', () => {
  let spectator: Spectator<ModalNotificationsComponent>;
  let modalRefMock: SpyObject<UiModalRef>;

  const createComponent = createComponentFactory({
    component: ModalNotificationsComponent,
    imports: [CommonModule],
    providers: [mockProvider(UiModalRef, { data: { product: {} } })],
    mocks: [UiModalService],
  });

  beforeEach(() => {
    spectator = createComponent();
    modalRefMock = spectator.inject(UiModalRef);
  });

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

  describe('close()', () => {
    it('should call _modalRef.close()', () => {
      spectator.component.close();
      expect(modalRefMock.close).toHaveBeenCalled();
    });
  });

  describe('get activeCard', () => {
    it('should return the activeCard', () => {
      spectator.component.activeCard = 'testCard';
      expect(spectator.component.activeCard).toBe('testCard');
    });
  });

  describe('get activeCard$', () => {
    it('should return activeCard$', () => {
      spectator.component.activeCard = 'testCard';

      spectator.component.activeCard$
        .subscribe((c) => {
          expect(c).toBe('testCard');
        })
        .unsubscribe();
    });
  });

  describe('get groupedNotifications', () => {
    it('should return the groupedNotifications', () => {
      spectator.component.groupedNotifications = [{ group: 'test', items: [] }];
      expect(spectator.component.groupedNotifications).toEqual([{ group: 'test', items: [] }]);
    });
  });

  describe('get groupedNotifications$', () => {
    it('should return the groupedNotifications$', () => {
      spectator.component.groupedNotifications = [{ group: 'test', items: [] }];

      spectator.component.groupedNotifications$
        .subscribe((gn) => {
          expect(gn).toEqual([{ group: 'test', items: [] }]);
        })
        .unsubscribe();
    });
  });

  describe('activeNotifications$', () => {
    it('should return the item with the activeCard within the group', () => {
      spectator.component.groupedNotifications = [{ group: 'testCard', items: [{ text: 'testmessage' }] }];
      spectator.component.activeCard = 'testCard';
      spectator.component.activeNotifications$
        .subscribe((an) => {
          expect(an).toEqual([{ text: 'testmessage' }]);
        })
        .unsubscribe();
    });

    it('should not return anything if the item with the activeCard is not within the group', () => {
      spectator.component.groupedNotifications = [{ group: 'testCard', items: [{ text: 'testmessage' }] }];
      spectator.component.activeCard = 'testCardtest';
      spectator.component.activeNotifications$
        .subscribe((an) => {
          expect(an).toBeUndefined();
        })
        .unsubscribe();
    });
  });

  describe('ngOnInit()', () => {
    it('should call patchState with activeCard', () => {
      const activeCard = 'test';
      spectator = createComponent({ props: { activeCard, groupedNotifications: [{ group: activeCard, items: [] }] } });
      spyOn(spectator.component, 'patchState');
      spectator.component.ngOnInit();
      expect(spectator.component.patchState).toHaveBeenCalledWith({
        activeCard: [{ group: activeCard, items: [] }].find((_) => true)?.group,
      });
    });
  });
});
