import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { ObjectID } from 'mongodb';
import { BehaviorSubject } from 'rxjs';
import { DatabaseService } from '../shared/database/database.service';
import { UsersService } from '../users/users.service';
import { WhiskyService } from './whisky.service';

jest.mock('../shared/database/database.service.ts');
jest.mock('../users/users.service.ts');

describe('WhiskyService', () => {
  let service: WhiskyService;
  let databaseService: DatabaseService;
  let usersService: UsersService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        WhiskyService,
        {
          provide: DatabaseService,
          useValue: {
            isLoaded: new BehaviorSubject(true),
            collection: {
              find: jest.fn(),
              findOne: jest.fn(),
              insertOne: jest.fn()
            }
          }
        },
        ConfigService,
        UsersService
      ]
    }).compile();

    service = module.get<WhiskyService>(WhiskyService);
    databaseService = module.get<DatabaseService>(DatabaseService);
    usersService = module.get<UsersService>(UsersService);
    usersService.findOne = jest.fn().mockResolvedValue({});
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  describe('[METHOD]: getUsersFavouriteWhiskies', () => {
    let findSpy: jest.SpyInstance;

    beforeEach(() => {
      findSpy = jest.spyOn(usersService, 'findOne');
      findSpy.mockResolvedValue({});
    });
    it('should be defined', () => {
      expect(service.getUsersFavouriteWhiskies).toBeDefined();
    });

    it('should call userService->findOne', () => {
      service.getUsersFavouriteWhiskies(new ObjectID());

      expect(findSpy).toHaveBeenCalled();
    });

    it('should call userService->findOne with an _id search', () => {
      const objectID = new ObjectID();
      service.getUsersFavouriteWhiskies(objectID);

      expect(findSpy).toHaveBeenCalledWith({ _id: objectID });
    });
  });

  describe('[METHOD]: getUsersCurrentWhiskies', () => {
    let findSpy: jest.SpyInstance;

    beforeEach(() => {
      findSpy = jest.spyOn(usersService, 'findOne');
      findSpy.mockResolvedValue({});
    });
    it('should be defined', () => {
      expect(service.getUsersCurrentWhiskies).toBeDefined();
    });

    it('should call userService->findOne', () => {
      service.getUsersCurrentWhiskies(new ObjectID());

      expect(findSpy).toHaveBeenCalled();
    });

    it('should call userService->findOne with an _id search', () => {
      const objectID = new ObjectID();
      service.getUsersCurrentWhiskies(objectID);

      expect(findSpy).toHaveBeenCalledWith({ _id: objectID });
    });
  });

  describe('[METHOD]: getUsersWishlist', () => {
    let findSpy: jest.SpyInstance;

    beforeEach(() => {
      findSpy = jest.spyOn(usersService, 'findOne');
      findSpy.mockResolvedValue({});
    });
    it('should be defined', () => {
      expect(service.getUsersWishlist).toBeDefined();
    });

    it('should call userService->findOne', () => {
      service.getUsersWishlist(new ObjectID());

      expect(findSpy).toHaveBeenCalled();
    });

    it('should call userService->findOne with an _id search', () => {
      const objectID = new ObjectID();
      service.getUsersWishlist(objectID);

      expect(findSpy).toHaveBeenCalledWith({ _id: objectID });
    });
  });
});
