import { HttpException, HttpStatus } from '@nestjs/common';
import { AccessToken } from '../../common/token';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { User as EntityUser } from '../../repositories/users/entity/user.entity';
import {
  makeDefaultAdB2cMockValue,
  makeDefaultConfigValue,
  makeDefaultSendGridlValue,
  makeDefaultSortCriteriaRepositoryMockValue,
  makeDefaultUsersRepositoryMockValue,
  makeUsersServiceMock,
} from './test/users.service.mock';
import { User } from './types/types';
import { EmailAlreadyVerifiedError } from '../../repositories/users/errors/types';

describe('UsersService', () => {
  it('ユーザの仮登録時に払い出されるトークンにより、未認証のユーザが認証済みになる', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendGridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendGridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token =
      'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
    expect(await service.confirmUser(token)).toEqual(undefined);
  });

  it('ユーザーが発行されたパスワードでログインできるようにする', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    usersRepositoryMockValue.findUserById = {
      id: 1,
      external_id: 'TEST9999',
      account_id: 1,
      role: 'None',
      accepted_terms_version: 'string',
      email_verified: false,
      created_by: 'string;',
      created_at: new Date(),
      updated_by: 'string;',
      updated_at: new Date(),
      auto_renew: true,
      license_alert: true,
      notification: true,
    };
    const adb2cParam = makeDefaultAdB2cMockValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const sendGridMockValue = makeDefaultSendGridlValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendGridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );

    const token =
      'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
    expect(await service.confirmUserAndInitPassword(token)).toEqual(undefined);
  });

  it('トークンの形式が不正な場合、形式不正エラーとなる。', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendgridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendgridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token = 'invalid.id.token';
    await expect(service.confirmUser(token)).rejects.toEqual(
      new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST),
    );
  });

  it('トークンの形式が不正な場合、形式不正エラーとなる。(メール認証API)', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    usersRepositoryMockValue.findUserById = {
      id: 1,
      external_id: 'TEST9999',
      account_id: 1,
      role: 'None',
      accepted_terms_version: 'string',
      email_verified: false,
      created_by: 'string;',
      created_at: new Date(),
      updated_by: 'string;',
      updated_at: new Date(),
      auto_renew: true,
      license_alert: true,
      notification: true,
    };
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendGridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendGridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token = 'invalid.id.token';
    await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual(
      new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST),
    );
  });
  it('ユーザが既に認証済みだった場合、認証済みユーザエラーとなる。', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendgridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();

    usersRepositoryMockValue.updateUserVerified =
      new EmailAlreadyVerifiedError();

    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendgridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token =
      'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
    await expect(service.confirmUser(token)).rejects.toEqual(
      new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST),
    );
  });
  it('ユーザが既に認証済みだった場合、認証済みユーザエラーとなる。(メール認証API)', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    usersRepositoryMockValue.findUserById = {
      id: 1,
      external_id: 'TEST9999',
      account_id: 1,
      role: 'None',
      accepted_terms_version: 'string',
      email_verified: true,
      created_by: 'string;',
      created_at: new Date(),
      updated_by: 'string;',
      updated_at: new Date(),
      auto_renew: true,
      license_alert: true,
      notification: true,
    };
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendGridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    usersRepositoryMockValue.updateUserVerified =
      new EmailAlreadyVerifiedError();

    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendGridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token =
      'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
    await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual(
      new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST),
    );
  });
  it('DBネットワークエラーとなる場合、エラーとなる。', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendgridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    usersRepositoryMockValue.updateUserVerified = new Error('DB error');

    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendgridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token =
      'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
    await expect(service.confirmUser(token)).rejects.toEqual(
      new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      ),
    );
  });
  it('DBネットワークエラーとなる場合、エラーとなる。(メール認証API)', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    usersRepositoryMockValue.findUserById = {
      id: 1,
      external_id: 'TEST9999',
      account_id: 1,
      role: 'None',
      accepted_terms_version: 'string',
      email_verified: false,
      created_by: 'string;',
      created_at: new Date(),
      updated_by: 'string;',
      updated_at: new Date(),
      auto_renew: true,
      license_alert: true,
      notification: true,
    };
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendGridMockValue = makeDefaultSendGridlValue();
    usersRepositoryMockValue.updateUserVerified = new Error('DB error');
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendGridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const token =
      'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
    await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual(
      new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      ),
    );
  });
  it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:None)', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendgridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendgridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const name = 'test_user1';
    const role = 'None';
    const email = 'test1@example.co.jp';
    const autoRenew = true;
    const licenseAlert = true;
    const notification = true;
    const token: AccessToken = { userId: '0001', role: '', tier: 5 };
    expect(
      await service.createUser(
        token,
        name,
        role,
        email,
        autoRenew,
        licenseAlert,
        notification,
      ),
    ).toEqual(undefined);
  });
});

describe('UsersService', () => {
  it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:Author)', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendgridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendgridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const name = 'test_user2';
    const role = 'Author';
    const email = 'test2@example.co.jp';
    const autoRenew = true;
    const licenseAlert = true;
    const notification = true;
    const authorId = 'testID';
    const token: AccessToken = { userId: '0001', role: '', tier: 5 };
    expect(
      await service.createUser(
        token,
        name,
        role,
        email,
        autoRenew,
        licenseAlert,
        notification,
        authorId,
      ),
    ).toEqual(undefined);
  });
});

describe('UsersService', () => {
  it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:Transcriptioninst)', async () => {
    const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
    const adb2cParam = makeDefaultAdB2cMockValue();
    const sendgridMockValue = makeDefaultSendGridlValue();
    const configMockValue = makeDefaultConfigValue();
    const sortCriteriaRepositoryMockValue =
      makeDefaultSortCriteriaRepositoryMockValue();
    const service = await makeUsersServiceMock(
      usersRepositoryMockValue,
      adb2cParam,
      sendgridMockValue,
      configMockValue,
      sortCriteriaRepositoryMockValue,
    );
    const name = 'test_user3';
    const role = 'Transcriptioninst';
    const email = 'test3@example.co.jp';
    const autoRenew = true;
    const licenseAlert = true;
    const notification = true;
    const typistGroupId = 111;
    const token: AccessToken = { userId: '0001', role: '', tier: 5 };
    expect(
      await service.createUser(
        token,
        name,
        role,
        email,
        autoRenew,
        licenseAlert,
        notification,
        undefined,
        typistGroupId,
      ),
    ).toEqual(undefined);
  });
});

it('DBネットワークエラーとなる場合、エラーとなる。', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  usersRepositoryMockValue.createNormalUser = new Error('DB error');
  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );
  const name = 'test_user5';
  const role = 'Transcriptioninst';
  const email = 'test5@example.co.jp';
  const autoRenew = true;
  const licenseAlert = true;
  const notification = true;
  const token: AccessToken = { userId: '0001', role: '', tier: 5 };
  await expect(
    service.createUser(
      token,
      name,
      role,
      email,
      autoRenew,
      licenseAlert,
      notification,
    ),
  ).rejects.toEqual(
    new HttpException(
      makeErrorResponse('E009999'),
      HttpStatus.INTERNAL_SERVER_ERROR,
    ),
  );
});
it('Azure ADB2Cでネットワークエラーとなる場合、エラーとなる。', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  adb2cParam.createUser = new Error();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );
  const name = 'test_user6';
  const role = 'Transcriptioninst';
  const email = 'test6@example.co.jp';
  const autoRenew = true;
  const licenseAlert = true;
  const notification = true;
  const token: AccessToken = { userId: '0001', role: '', tier: 5 };
  await expect(
    service.createUser(
      token,
      name,
      role,
      email,
      autoRenew,
      licenseAlert,
      notification,
    ),
  ).rejects.toEqual(
    new HttpException(
      makeErrorResponse('E009999'),
      HttpStatus.INTERNAL_SERVER_ERROR,
    ),
  );
});
it('メールアドレスが重複している場合、エラーとなる。', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  adb2cParam.createUser = { reason: 'email', message: 'ObjectConflict' };
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );
  const name = 'test_user7';
  const role = 'Transcriptioninst';
  const email = 'test7@example.co.jp';
  const autoRenew = true;
  const licenseAlert = true;
  const notification = true;
  const token: AccessToken = { userId: '0001', role: '', tier: 5 };
  await expect(
    service.createUser(
      token,
      name,
      role,
      email,
      autoRenew,
      licenseAlert,
      notification,
    ),
  ).rejects.toEqual(
    new HttpException(makeErrorResponse('E010301'), HttpStatus.BAD_REQUEST),
  );
});
it('AuthorIDが重複している場合、エラーとなる。(AuthorID重複チェックでエラー)', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  usersRepositoryMockValue.createNormalUser = new Error();
  usersRepositoryMockValue.existsAuthorId = true;

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );
  const name = 'test_user8';
  const role = 'Author';
  const email = 'test8@example.co.jp';
  const autoRenew = true;
  const licenseAlert = true;
  const notification = true;
  const authorId = 'testID';
  const token: AccessToken = { userId: '0001', role: '', tier: 5 };
  await expect(
    service.createUser(
      token,
      name,
      role,
      email,
      autoRenew,
      licenseAlert,
      notification,
      authorId,
    ),
  ).rejects.toEqual(
    new HttpException(makeErrorResponse('E010302'), HttpStatus.BAD_REQUEST),
  );
});
it('AuthorIDが重複している場合、エラーとなる。(insert失敗)', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  usersRepositoryMockValue.createNormalUser = new Error();
  usersRepositoryMockValue.createNormalUser.name = 'ER_DUP_ENTRY';

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );
  const name = 'test_user9';
  const role = 'Author';
  const email = 'test9@example.co.jp';
  const autoRenew = true;
  const licenseAlert = true;
  const notification = true;
  const authorId = 'testID';
  const token: AccessToken = { userId: '0001', role: '', tier: 5 };
  await expect(
    service.createUser(
      token,
      name,
      role,
      email,
      autoRenew,
      licenseAlert,
      notification,
      authorId,
    ),
  ).rejects.toEqual(
    new HttpException(makeErrorResponse('E010302'), HttpStatus.BAD_REQUEST),
  );
});

it('ユーザの一覧を取得する', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  expect(
    await service.getUsers({ role: 'Admin', userId: 'XXXXXX', tier: 5 }),
  ).toEqual(expectedUsers);
});

const expectedUsers = [
  {
    name: 'Hanako Sato',
    role: 'none',
    authorId: '6cce347f-0cf1-a15e-19ab-d00988b643f9',
    typistGroupName: '',
    email: 'hanako@sample.com',
    emailVerified: true,
    autoRenew: false,
    licenseAlert: false,
    notification: false,
  },
  {
    name: 'Hanako Sato',
    role: 'none',
    authorId: '551c4077-5b55-a38c-2c55-cd1edd537aa8',
    typistGroupName: '',
    email: 'hanako@sample.com',
    emailVerified: true,
    autoRenew: false,
    licenseAlert: false,
    notification: false,
  },
];

it('ユーザの一覧を取得に失敗する', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  usersRepositoryMockValue.findSameAccountUsers = new Error(
    'Failure to acquire',
  );

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  await expect(
    service.getUsers({ role: 'Admin', userId: 'XXXXXX', tier: 5 }),
  ).rejects.toEqual(
    new HttpException(makeErrorResponse('E009999'), HttpStatus.NOT_FOUND),
  );
});

it('ユーザの一覧を0件取得する', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();

  // モックでDBからのユーザ取得を空にする
  const noDbUsers: EntityUser[] = [];
  usersRepositoryMockValue.findSameAccountUsers = noDbUsers;

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  const emptyMergedUsers: User[] = [];
  expect(
    await service.getUsers({ role: 'Admin', userId: 'XXXXXX', tier: 5 }),
  ).toEqual(emptyMergedUsers);
});

it('ソート条件を変更できる', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  expect(
    await service.updateSortCriteria('AUTHOR_ID', 'ASC', {
      role: 'none admin',
      userId: 'xxxxxxxxxxxx',
      tier: 5,
    }),
  ).toEqual(undefined);
});

it('ユーザー情報が存在せず、ソート条件を変更できない', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();

  usersRepositoryMockValue.findUserByExternalId = new Error('user not found');

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  await expect(
    service.updateSortCriteria('AUTHOR_ID', 'ASC', {
      role: 'none admin',
      userId: 'xxxxxxxxxxxx',
      tier: 5,
    }),
  ).rejects.toEqual(
    new HttpException(
      makeErrorResponse('E009999'),
      HttpStatus.INTERNAL_SERVER_ERROR,
    ),
  );
});

it('ソート条件が存在せず、ソート条件を変更できない', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  sortCriteriaRepositoryMockValue.updateSortCriteria = new Error(
    'sort criteria not found',
  );

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  await expect(
    service.updateSortCriteria('AUTHOR_ID', 'ASC', {
      role: 'none admin',
      userId: 'xxxxxxxxxxxx',
      tier: 5,
    }),
  ).rejects.toEqual(
    new HttpException(
      makeErrorResponse('E009999'),
      HttpStatus.INTERNAL_SERVER_ERROR,
    ),
  );
});

it('ソート条件を取得できる', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  expect(
    await service.getSortCriteria({
      role: 'none admin',
      userId: 'xxxxxxxxxxxx',
      tier: 5,
    }),
  ).toEqual({ direction: 'ASC', paramName: 'JOB_NUMBER' });
});

it('ソート条件が存在せず、ソート条件を取得できない', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();

  sortCriteriaRepositoryMockValue.getSortCriteria = new Error(
    'sort criteria not found',
  );

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  await expect(
    service.getSortCriteria({
      role: 'none admin',
      userId: 'xxxxxxxxxxxx',
      tier: 5,
    }),
  ).rejects.toEqual(
    new HttpException(
      makeErrorResponse('E009999'),
      HttpStatus.INTERNAL_SERVER_ERROR,
    ),
  );
});

it('DBから取得した値が不正だった場合、エラーとなる', async () => {
  const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
  const adb2cParam = makeDefaultAdB2cMockValue();
  const sendgridMockValue = makeDefaultSendGridlValue();
  const configMockValue = makeDefaultConfigValue();
  const sortCriteriaRepositoryMockValue =
    makeDefaultSortCriteriaRepositoryMockValue();
  sortCriteriaRepositoryMockValue.getSortCriteria = {
    id: 1,
    direction: 'AAA',
    parameter: 'BBBBB',
    user_id: 1,
  };

  const service = await makeUsersServiceMock(
    usersRepositoryMockValue,
    adb2cParam,
    sendgridMockValue,
    configMockValue,
    sortCriteriaRepositoryMockValue,
  );

  await expect(
    service.getSortCriteria({
      role: 'none admin',
      userId: 'xxxxxxxxxxxx',
      tier: 5,
    }),
  ).rejects.toEqual(
    new HttpException(
      makeErrorResponse('E009999'),
      HttpStatus.INTERNAL_SERVER_ERROR,
    ),
  );
});
