import {
  ReqType as DbRequestType,
  UserRequest as DbUserRequest,
} from '@prisma/client';
import { mockDeep, mockReset } from 'jest-mock-extended';
import {
  JSON_INVALID,
  USER_REQUEST_NOT_FOUND,
  USER_REQUEST_REORDERING_FAILED,
} from 'src/errors';
import { PrismaService } from 'src/prisma/prisma.service';
import { PubSubService } from 'src/pubsub/pubsub.service';
import * as E from 'fp-ts/Either';
import { GetUserRequestArgs } from './input-type.args';
import { MoveUserRequestArgs } from './input-type.args';
import {
  CreateUserRequestArgs,
  UpdateUserRequestArgs,
} from './input-type.args';
import { UserRequest } from './user-request.model';
import { UserRequestService } from './user-request.service';
import { AuthUser } from 'src/types/AuthUser';
import { ReqType } from 'src/types/RequestTypes';
import { UserCollectionService } from 'src/user-collection/user-collection.service';

const mockPrisma = mockDeep<PrismaService>();
const mockPubSub = mockDeep<PubSubService>();
const mockUserCollectionService = mockDeep<UserCollectionService>();

// @ts-ignore
const userRequestService = new UserRequestService(
  mockPrisma,
  mockPubSub as any,
  mockUserCollectionService,
);

const user: AuthUser = {
  uid: 'user-uid',
  email: 'test@gmail.com',
  displayName: 'Test User',
  photoURL: 'https://example.com/photo.png',
  isAdmin: false,
  refreshToken: null,
  lastLoggedOn: new Date(),
  lastActiveOn: new Date(),
  createdOn: new Date(),
  currentGQLSession: null,
  currentRESTSession: null,
};
const dbUserRequests: DbUserRequest[] = [
  {
    id: 'user-request-id-11',
    collectionID: 'collection-id-1',
    orderIndex: 1,
    userUid: user.uid,
    title: 'Request 1',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-12',
    collectionID: 'collection-id-1',
    orderIndex: 2,
    userUid: user.uid,
    title: 'Request 2',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-13',
    collectionID: 'collection-id-1',
    orderIndex: 3,
    userUid: user.uid,
    title: 'Request 3',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-14',
    collectionID: 'collection-id-1',
    orderIndex: 4,
    userUid: user.uid,
    title: 'Request 4',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-21',
    collectionID: 'collection-id-2',
    orderIndex: 1,
    userUid: user.uid,
    title: 'Request 1',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-22',
    collectionID: 'collection-id-2',
    orderIndex: 2,
    userUid: user.uid,
    title: 'Request 2',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-23',
    collectionID: 'collection-id-2',
    orderIndex: 3,
    userUid: user.uid,
    title: 'Request 3',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
  {
    id: 'user-request-id-24',
    collectionID: 'collection-id-2',
    orderIndex: 4,
    userUid: user.uid,
    title: 'Request 4',
    request: {},
    type: DbRequestType.REST,
    createdOn: new Date(),
    updatedOn: new Date(),
  },
];
const userRequests: UserRequest[] = dbUserRequests.map((r) => {
  return {
    ...r,
    request: JSON.stringify(r.request),
    type: ReqType[r.type],
  };
});

beforeEach(() => {
  mockReset(mockPrisma);
  mockPubSub.publish.mockClear();
  mockUserCollectionService.getUserCollection.mockClear();
});

describe('UserRequestService', () => {
  describe('fetchUserRequests', () => {
    test('Should resolve right and fetch user requests (with collection ID)', () => {
      const args: GetUserRequestArgs = {
        collectionID: 'collection-id-1',
        cursor: undefined,
        take: undefined,
      };
      const expectedDbUserRequests = dbUserRequests.filter(
        (r) => r.collectionID === args.collectionID,
      );
      const expectedUserRequests = userRequests.filter(
        (r) => r.collectionID === args.collectionID,
      );

      mockPrisma.userRequest.findMany.mockResolvedValue(expectedDbUserRequests);
      const result = userRequestService.fetchUserRequests(
        args.collectionID,
        ReqType.REST,
        args.cursor,
        args.take,
        user,
      );

      expect(result).resolves.toEqualRight(expectedUserRequests);
    });

    test('Should resolve right and fetch user requests (with collection ID and take)', () => {
      const args: GetUserRequestArgs = {
        collectionID: 'collection-id-1',
        cursor: undefined,
        take: 2,
      };
      const expectedDbUserRequests = dbUserRequests.filter(
        (r) => r.collectionID === args.collectionID,
      );
      const expectedUserRequests = userRequests.filter(
        (r) => r.collectionID === args.collectionID,
      );

      mockPrisma.userRequest.findMany.mockResolvedValue(expectedDbUserRequests);
      const result = userRequestService.fetchUserRequests(
        args.collectionID,
        ReqType.REST,
        args.cursor,
        args.take,
        user,
      );

      expect(result).resolves.toEqualRight(expectedUserRequests);
    });
    test('Should resolve right and fetch user requests (with all params)', () => {
      const args: GetUserRequestArgs = {
        collectionID: 'collection-id-1',
        cursor: 'user-request-id-12',
        take: 2,
      };
      const expectedDbUserRequests = dbUserRequests.filter(
        (r) => r.collectionID === args.collectionID,
      );
      const expectedUserRequests = userRequests.filter(
        (r) => r.collectionID === args.collectionID,
      );

      mockPrisma.userRequest.findMany.mockResolvedValue(expectedDbUserRequests);
      const result = userRequestService.fetchUserRequests(
        args.collectionID,
        ReqType.REST,
        args.cursor,
        args.take,
        user,
      );

      expect(result).resolves.toEqualRight(expectedUserRequests);
    });
  });

  describe('fetchUserRequest', () => {
    test('Should resolve right and fetch user request', () => {
      const expectedDbUserRequest = dbUserRequests[0];
      const expectedUserRequest = userRequests[0];

      mockPrisma.userRequest.findUnique.mockResolvedValue(
        expectedDbUserRequest,
      );
      const result = userRequestService.fetchUserRequest(
        expectedUserRequest.id,
        user,
      );

      expect(result).resolves.toEqualRight(expectedUserRequest);
    });

    test('Should resolve left if user request not exist', () => {
      mockPrisma.userRequest.findUnique.mockResolvedValue(null);
      const result = userRequestService.fetchUserRequest(
        userRequests[0].id,
        user,
      );

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
    });

    test('Should resolve left if another users user-request asked', () => {
      mockPrisma.userRequest.findUnique.mockResolvedValue({
        ...dbUserRequests[0],
        userUid: 'another-user',
      });
      const result = userRequestService.fetchUserRequest(
        userRequests[0].id,
        user,
      );

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
    });
  });

  describe('createRequest', () => {
    test('Should resolve right and create user request', () => {
      const args: CreateUserRequestArgs = {
        collectionID: userRequests[0].collectionID,
        title: userRequests[0].title,
        request: userRequests[0].request,
        type: userRequests[0].type,
      };

      mockPrisma.userRequest.count.mockResolvedValue(
        dbUserRequests[0].orderIndex - 1,
      );
      mockUserCollectionService.getUserCollection.mockResolvedValue(
        E.right({ type: userRequests[0].type, userUid: user.uid } as any),
      );
      mockPrisma.userRequest.create.mockResolvedValue(dbUserRequests[0]);

      const result = userRequestService.createRequest(
        args.collectionID,
        args.title,
        args.request,
        args.type,
        user,
      );

      expect(result).resolves.toEqualRight(userRequests[0]);
    });
    test('Should execute prisma.create() with correct params', async () => {
      const args: CreateUserRequestArgs = {
        collectionID: userRequests[0].collectionID,
        title: userRequests[0].title,
        request: userRequests[0].request,
        type: userRequests[0].type,
      };

      mockPrisma.userRequest.count.mockResolvedValue(
        dbUserRequests[0].orderIndex - 1,
      );
      mockPrisma.userRequest.create.mockResolvedValue(dbUserRequests[0]);

      await userRequestService.createRequest(
        args.collectionID,
        args.title,
        args.request,
        args.type,
        user,
      );

      expect(mockPrisma.userRequest.create).toHaveBeenCalledWith({
        data: {
          ...args,
          request: JSON.parse(args.request),
          type: DbRequestType[args.type],
          orderIndex: dbUserRequests[0].orderIndex,
          userUid: user.uid,
        },
      });
    });
    test('Should publish user request created message in pubnub', async () => {
      const args: CreateUserRequestArgs = {
        collectionID: userRequests[0].collectionID,
        title: userRequests[0].title,
        request: userRequests[0].request,
        type: userRequests[0].type,
      };

      mockPrisma.userRequest.count.mockResolvedValue(
        dbUserRequests[0].orderIndex - 1,
      );
      mockPrisma.userRequest.create.mockResolvedValue(dbUserRequests[0]);

      await userRequestService.createRequest(
        args.collectionID,
        args.title,
        args.request,
        args.type,
        user,
      );

      expect(mockPubSub.publish).toHaveBeenCalledWith(
        `user_request/${dbUserRequests[0].userUid}/created`,
        userRequests[0],
      );
    });
    test('Should resolve left for json-invalid request', () => {
      const args: CreateUserRequestArgs = {
        collectionID: userRequests[0].collectionID,
        title: userRequests[0].title,
        request: 'invalid json',
        type: userRequests[0].type,
      };

      mockPrisma.userRequest.count.mockResolvedValue(
        dbUserRequests[0].orderIndex - 1,
      );
      mockPrisma.userRequest.create.mockResolvedValue(dbUserRequests[0]);

      const result = userRequestService.createRequest(
        args.collectionID,
        args.title,
        args.request,
        args.type,
        user,
      );

      expect(result).resolves.toEqualLeft(JSON_INVALID);
    });
  });

  describe('updateRequest', () => {
    test('Should resolve right and update user request', () => {
      const id = userRequests[0].id;
      const type = userRequests[0].type;
      const args: UpdateUserRequestArgs = {
        title: userRequests[0].title,
        request: userRequests[0].request,
      };

      mockPrisma.userRequest.findFirst.mockResolvedValueOnce(dbUserRequests[0]);
      mockPrisma.userCollection.findFirst.mockResolvedValueOnce({} as any);
      mockPrisma.userRequest.update.mockResolvedValue(dbUserRequests[0]);

      const result = userRequestService.updateRequest(
        id,
        args.title,
        type,
        args.request,
        user,
      );

      expect(result).resolves.toEqualRight(userRequests[0]);
    });
    test('Should resolve right and perform prisma.update with correct param', async () => {
      const id = userRequests[0].id;
      const type = userRequests[0].type;
      const args: UpdateUserRequestArgs = {
        title: userRequests[0].title,
        request: userRequests[0].request,
      };

      mockPrisma.userRequest.findFirst.mockResolvedValueOnce(dbUserRequests[0]);
      mockPrisma.userCollection.findFirst.mockResolvedValueOnce({} as any);
      mockPrisma.userRequest.update.mockResolvedValue(dbUserRequests[0]);

      await userRequestService.updateRequest(
        id,
        args.title,
        type,
        args.request,
        user,
      );

      expect(mockPrisma.userRequest.update).toHaveBeenCalledWith({
        where: { id },
        data: {
          ...args,
          request: JSON.parse(args.request),
        },
      });
    });
    test('Should resolve right and publish to pubnub with correct param', async () => {
      const id = userRequests[0].id;
      const type = userRequests[0].type;
      const args: UpdateUserRequestArgs = {
        title: userRequests[0].title,
        request: userRequests[0].request,
      };

      mockPrisma.userRequest.findFirst.mockResolvedValueOnce(dbUserRequests[0]);
      mockPrisma.userCollection.findFirst.mockResolvedValueOnce({} as any);
      mockPrisma.userRequest.update.mockResolvedValue(dbUserRequests[0]);

      await userRequestService.updateRequest(
        id,
        args.title,
        type,
        args.request,
        user,
      );

      expect(mockPubSub.publish).toHaveBeenCalledWith(
        `user_request/${dbUserRequests[0].userUid}/updated`,
        userRequests[0],
      );
    });
    test('Should resolve left if user request not found', () => {
      const id = userRequests[0].id;
      const type = userRequests[0].type;
      const args: UpdateUserRequestArgs = {
        title: userRequests[0].title,
        request: userRequests[0].request,
      };

      mockPrisma.userRequest.findFirst.mockResolvedValue(null);

      const result = userRequestService.updateRequest(
        id,
        args.title,
        type,
        args.request,
        user,
      );

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
    });
    test('Should resolve left if stringToJson returns error', () => {
      const id = userRequests[0].id;
      const type = userRequests[0].type;
      const args: UpdateUserRequestArgs = {
        title: userRequests[0].title,
        request: 'invalid json',
      };

      mockPrisma.userRequest.findFirst.mockResolvedValueOnce(dbUserRequests[0]);
      mockPrisma.userCollection.findFirst.mockResolvedValueOnce({} as any);

      const result = userRequestService.updateRequest(
        id,
        args.title,
        type,
        args.request,
        user,
      );

      expect(result).resolves.toEqualLeft(JSON_INVALID);
    });
  });

  describe('deleteRequest', () => {
    test('Should resolve right and delete user request', () => {
      const id = userRequests[0].id;

      mockPrisma.userRequest.findFirst.mockResolvedValue(dbUserRequests[0]);
      mockPrisma.userRequest.delete.mockResolvedValue(dbUserRequests[0]);

      const result = userRequestService.deleteRequest(id, user);

      expect(result).resolves.toEqualRight(true);
    });
    test('Should resolve right and perform prisma.delete with correct param', async () => {
      const id = userRequests[0].id;

      mockPrisma.userRequest.findFirst.mockResolvedValue(dbUserRequests[0]);
      mockPrisma.userRequest.delete.mockResolvedValue(null);

      await userRequestService.deleteRequest(id, user);

      expect(mockPrisma.userRequest.delete).toHaveBeenCalledWith({
        where: { id },
      });
    });
    test('Should resolve right and perform prisma.updateMany with correct param', async () => {
      const id = userRequests[0].id;

      mockPrisma.userRequest.findFirst.mockResolvedValue(dbUserRequests[0]);
      mockPrisma.userRequest.delete.mockResolvedValue(null);

      await userRequestService.deleteRequest(id, user);

      expect(mockPrisma.userRequest.updateMany).toHaveBeenCalledWith({
        where: {
          collectionID: dbUserRequests[0].collectionID,
          orderIndex: { gt: dbUserRequests[0].orderIndex },
        },
        data: { orderIndex: { decrement: 1 } },
      });
    });
    test('Should resolve and publish message to pubnub', async () => {
      const id = userRequests[0].id;

      mockPrisma.userRequest.findFirst.mockResolvedValue(dbUserRequests[0]);
      mockPrisma.userRequest.delete.mockResolvedValue(null);

      const result = await userRequestService.deleteRequest(id, user);

      expect(mockPubSub.publish).toHaveBeenCalledWith(
        `user_request/${dbUserRequests[0].userUid}/deleted`,
        userRequests[0],
      );
    });
    test('Should resolve error if the user request is not found', () => {
      const id = userRequests[0].id;
      mockPrisma.userRequest.findFirst.mockResolvedValue(null);

      const result = userRequestService.deleteRequest(id, user);

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
      expect(mockPrisma.userRequest.findFirst).toHaveBeenCalledWith({
        where: { id, userUid: dbUserRequests[0].userUid },
      });
      expect(mockPrisma.userRequest.updateMany).not.toHaveBeenCalled();
      expect(mockPrisma.userRequest.delete).not.toHaveBeenCalled();
      expect(mockPubSub.publish).not.toHaveBeenCalled();
    });
  });

  describe('reorderRequests', () => {
    test('Should resolve left if transaction throws an error', async () => {
      const srcCollID = dbUserRequests[0].collectionID;
      const request = dbUserRequests[0];
      const destCollID = dbUserRequests[4].collectionID;
      const nextRequest = dbUserRequests[4];

      mockPrisma.$transaction.mockRejectedValueOnce(new Error());
      const result = await userRequestService.reorderRequests(
        srcCollID,
        request,
        destCollID,
        nextRequest,
      );
      expect(result).toEqual(E.left(USER_REQUEST_REORDERING_FAILED));
    });
    test('Should resolve right and call transaction with the correct data', async () => {
      const srcCollID = dbUserRequests[0].collectionID;
      const request = dbUserRequests[0];
      const destCollID = dbUserRequests[4].collectionID;
      const nextRequest = dbUserRequests[4];

      const updatedReq: DbUserRequest = {
        ...request,
        collectionID: destCollID,
        orderIndex: nextRequest.orderIndex,
      };

      mockPrisma.$transaction.mockResolvedValueOnce(E.right(updatedReq));
      const result = await userRequestService.reorderRequests(
        srcCollID,
        request,
        destCollID,
        nextRequest,
      );
      expect(mockPrisma.$transaction).toHaveBeenCalledWith(
        expect.any(Function),
      );
      expect(result).toEqual(E.right(updatedReq));
    });
  });

  describe('findRequestAndNextRequest', () => {
    test('Should resolve right if the request and the next request are found', async () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[4].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: userRequests[4].id,
      };

      mockPrisma.userRequest.findFirst
        .mockResolvedValueOnce(dbUserRequests[0])
        .mockResolvedValueOnce(dbUserRequests[4]);

      const result = await userRequestService.findRequestAndNextRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).toEqualRight({
        request: dbUserRequests[0],
        nextRequest: dbUserRequests[4],
      });
    });
    test('Should resolve right if the request and next request null', () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[1].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: null,
      };

      mockPrisma.userRequest.findFirst
        .mockResolvedValueOnce(dbUserRequests[0])
        .mockResolvedValueOnce(null);

      const result = userRequestService.findRequestAndNextRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).resolves.toEqualRight({
        request: dbUserRequests[0],
        nextRequest: null,
      });
    });
    test('Should resolve left if the request is not found', () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[1].collectionID,
        requestID: 'invalid',
        nextRequestID: null,
      };

      mockPrisma.userRequest.findFirst.mockResolvedValueOnce(null);

      const result = userRequestService.findRequestAndNextRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
    });
    test('Should resolve left if the nextRequest is not found', () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[1].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: 'invalid',
      };

      mockPrisma.userRequest.findFirst
        .mockResolvedValueOnce(dbUserRequests[0])
        .mockResolvedValueOnce(null);

      const result = userRequestService.findRequestAndNextRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
    });
  });

  describe('moveRequest', () => {
    test('Should resolve right and the request', () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[0].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: null,
      };

      jest
        .spyOn(userRequestService, 'findRequestAndNextRequest')
        .mockResolvedValue(
          E.right({ request: dbUserRequests[0], nextRequest: null }),
        );
      jest
        .spyOn(userRequestService, 'reorderRequests')
        .mockResolvedValue(E.right(dbUserRequests[0]));
      jest
        .spyOn(userRequestService, 'validateTypeEqualityForMoveRequest')
        .mockResolvedValue(E.right(true));

      const result = userRequestService.moveRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).resolves.toEqualRight(userRequests[0]);
    });
    test('Should resolve right and publish message to pubnub', async () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[0].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: null,
      };

      jest
        .spyOn(userRequestService, 'findRequestAndNextRequest')
        .mockResolvedValue(
          E.right({ request: dbUserRequests[0], nextRequest: null }),
        );
      jest
        .spyOn(userRequestService, 'reorderRequests')
        .mockResolvedValue(E.right(dbUserRequests[0]));
      jest
        .spyOn(userRequestService, 'validateTypeEqualityForMoveRequest')
        .mockResolvedValue(E.right(true));

      await userRequestService.moveRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(mockPubSub.publish).toHaveBeenCalledWith(
        `user_request/${dbUserRequests[0].userUid}/moved`,
        { request: userRequests[0], nextRequest: null },
      );
    });
    test('Should resolve left if finding the requests fails', () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[0].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: null,
      };

      jest
        .spyOn(userRequestService, 'findRequestAndNextRequest')
        .mockResolvedValue(E.left(USER_REQUEST_NOT_FOUND));
      jest
        .spyOn(userRequestService, 'validateTypeEqualityForMoveRequest')
        .mockResolvedValue(E.right(true));

      const result = userRequestService.moveRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).resolves.toEqualLeft(USER_REQUEST_NOT_FOUND);
    });
    test('Should resolve left if reordering the request fails', async () => {
      const args: MoveUserRequestArgs = {
        sourceCollectionID: userRequests[0].collectionID,
        destinationCollectionID: userRequests[0].collectionID,
        requestID: userRequests[0].id,
        nextRequestID: null,
      };

      jest
        .spyOn(userRequestService, 'findRequestAndNextRequest')
        .mockResolvedValue(
          E.right({
            request: dbUserRequests[0],
            nextRequest: null,
          }),
        );
      jest
        .spyOn(userRequestService, 'reorderRequests')
        .mockResolvedValue(E.left(USER_REQUEST_REORDERING_FAILED));
      jest
        .spyOn(userRequestService, 'validateTypeEqualityForMoveRequest')
        .mockResolvedValue(E.right(true));

      const result = await userRequestService.moveRequest(
        args.sourceCollectionID,
        args.destinationCollectionID,
        args.requestID,
        args.nextRequestID,
        user,
      );

      expect(result).toEqualLeft(USER_REQUEST_REORDERING_FAILED);
    });
  });

  describe('validateTypeEqualityForMoveRequest', () => {
    test('Should resolve right if the types are equal', () => {
      const srcCollID = 'srcCollID';
      const destCollID = 'destCollID';

      mockUserCollectionService.getUserCollection.mockResolvedValueOnce(
        E.right({ type: userRequests[0].type, userUid: user.uid } as any),
      );
      mockUserCollectionService.getUserCollection.mockResolvedValueOnce(
        E.right({ type: userRequests[1].type, userUid: user.uid } as any),
      );

      const result = userRequestService.validateTypeEqualityForMoveRequest(
        srcCollID,
        destCollID,
        userRequests[0],
        userRequests[1],
      );

      expect(result).resolves.toEqualRight(true);
    });
  });
});
