import { Test, TestingModule } from '@nestjs/testing';
import { LicensesService } from '../licenses.service';
import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service';
import { User } from '../../../repositories/users/entity/user.entity';
import { Account } from '../../../repositories/accounts/entity/account.entity';
import { UsersRepositoryService } from '../../../repositories/users/users.repository.service';
import { AccountsRepositoryService } from '../../../repositories/accounts/accounts.repository.service';

export type LicensesRepositoryMockValue = {
  order: undefined | Error;
  createCardLicenses: string[] | Error;
  activateCardLicense: undefined | Error;
};

export type AccountsRepositoryMockValue = {
  findAccountById: Account | Error;
};

export type UsersRepositoryMockValue = {
  findUserByExternalId: User | Error;
};

export const makeLicensesServiceMock = async (
  licensesRepositoryMockValue: LicensesRepositoryMockValue,
  usersRepositoryMockValue: UsersRepositoryMockValue,
  accountsRepositoryMockValue: AccountsRepositoryMockValue,
): Promise<LicensesService> => {
  const module: TestingModule = await Test.createTestingModule({
    providers: [LicensesService],
  })
    .useMocker((token) => {
      switch (token) {
        case LicensesRepositoryService:
          return makeLicensesRepositoryMock(licensesRepositoryMockValue);
        case UsersRepositoryService:
          return makeUsersRepositoryMock(usersRepositoryMockValue);
        case AccountsRepositoryService:
          return makeAccountsRepositoryMock(accountsRepositoryMockValue);
      }
    })
    .compile();

  return module.get<LicensesService>(LicensesService);
};

export const makeLicensesRepositoryMock = (
  value: LicensesRepositoryMockValue,
) => {
  const { order, createCardLicenses, activateCardLicense } = value;
  return {
    order:
      order instanceof Error
        ? jest.fn<Promise<void>, []>().mockRejectedValue(order)
        : jest.fn<Promise<void>, []>().mockResolvedValue(order),
    createCardLicenses:
      createCardLicenses instanceof Error
        ? jest.fn<Promise<void>, []>().mockRejectedValue(createCardLicenses)
        : jest
            .fn<Promise<string[]>, []>()
            .mockResolvedValue(createCardLicenses),
    activateCardLicense:
      activateCardLicense instanceof Error
        ? jest.fn<Promise<void>, []>().mockRejectedValue(activateCardLicense)
        : jest.fn<Promise<void>, []>().mockResolvedValue(activateCardLicense),
  };
};

export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => {
  const { findUserByExternalId } = value;

  return {
    findUserByExternalId:
      findUserByExternalId instanceof Error
        ? jest.fn<Promise<void>, []>().mockRejectedValue(findUserByExternalId)
        : jest.fn<Promise<User>, []>().mockResolvedValue(findUserByExternalId),
  };
};

export const makeAccountsRepositoryMock = (
  value: AccountsRepositoryMockValue,
) => {
  const { findAccountById } = value;

  return {
    findAccountById:
      findAccountById instanceof Error
        ? jest.fn<Promise<void>, []>().mockRejectedValue(findAccountById)
        : jest.fn<Promise<Account>, []>().mockResolvedValue(findAccountById),
  };
};

export const makeDefaultLicensesRepositoryMockValue =
  (): LicensesRepositoryMockValue => {
    return {
      order: undefined,
      createCardLicenses: [
        'WZCETXC0Z9PQZ9GKRGGY',
        'F0JD7EZEDBH4PQRQ83YF',
        'H0HXBP5K9RW7T7JSVDJV',
        'HKIWX54EESYL4X132223',
        '363E81JR460UBHXGFXFI',
        '70IKAPV9K6YMEVLTOXBY',
        '1RJY1TRRYYTGF1LL9WLU',
        'BXM0HKFO7IULTL0A1B36',
        'XYLEWNY2LR6Q657CZE41',
        'AEJWRFFSWRQYQQJ6WVLV',
      ],
      activateCardLicense: undefined,
    };
  };
export const makeDefaultUsersRepositoryMockValue =
  (): UsersRepositoryMockValue => {
    const user1 = new User();
    user1.id = 2;
    user1.external_id = 'ede66c43-9b9d-4222-93ed-5f11c96e08e2';
    user1.account_id = 1234567890123456;
    user1.role = 'none';
    user1.author_id = '6cce347f-0cf1-a15e-19ab-d00988b643f9';
    user1.accepted_terms_version = '1.0';
    user1.email_verified = true;
    user1.auto_renew = false;
    user1.license_alert = false;
    user1.notification = false;
    user1.encryption = false;
    user1.prompt = false;
    user1.deleted_at = undefined;
    user1.created_by = 'test';
    user1.created_at = new Date();
    user1.updated_by = undefined;
    user1.updated_at = undefined;

    return {
      findUserByExternalId: user1,
    };
  };

export const makeDefaultAccountsRepositoryMockValue =
  (): AccountsRepositoryMockValue => {
    const account1 = new Account();
    account1.id = 2;
    account1.parent_account_id = 987654321098765;

    return {
      findAccountById: account1,
    };
  };
