import { TermsService } from './terms.service';
import { DataSource } from 'typeorm';
import { makeTestingModule } from '../../common/test/modules';
import { createTermInfo } from '../auth/test/utility';
import { makeContext } from '../../common/log';
import { v4 as uuidv4 } from 'uuid';
import { HttpException, HttpStatus } from '@nestjs/common';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { truncateAllTable } from '../../common/test/init';

describe('利用規約取得', () => {
  let source: DataSource | null = null;
  beforeAll(async () => {
    if (source == null) {
      source = await (async () => {
        const s = new DataSource({
          type: 'mysql',
          host: 'test_mysql_db',
          port: 3306,
          username: 'user',
          password: 'password',
          database: 'odms',
          entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
          synchronize: false, // trueにすると自動的にmigrationが行われるため注意
        });
        return await s.initialize();
      })();
    }
  });

  beforeEach(async () => {
    if (source) {
      await truncateAllTable(source);
    }
  });

  afterAll(async () => {
    await source?.destroy();
    source = null;
  });

  it('最新の利用規約情報が取得できる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    const service = module.get<TermsService>(TermsService);

    await createTermInfo(source, 'EULA', 'v1.0');
    await createTermInfo(source, 'EULA', 'v1.1');
    await createTermInfo(source, 'PrivacyNotice', 'v1.0');
    await createTermInfo(source, 'PrivacyNotice', 'v1.1');
    await createTermInfo(source, 'DPA', 'v1.0');
    await createTermInfo(source, 'DPA', 'v1.2');

    const context = makeContext(uuidv4(), 'requestId');
    const result = await service.getTermsInfo(context);

    expect(result[0].documentType).toBe('EULA');
    expect(result[0].version).toBe('v1.1');
    expect(result[1].documentType).toBe('PrivacyNotice');
    expect(result[1].version).toBe('v1.1');
    expect(result[2].documentType).toBe('DPA');
    expect(result[2].version).toBe('v1.2');
  });

  it('利用規約情報(EULA、DPA両方)が存在しない場合エラーとなる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    const service = module.get<TermsService>(TermsService);
    const context = makeContext(uuidv4(), 'requestId');
    await expect(service.getTermsInfo(context)).rejects.toEqual(
      new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      ),
    );
  });

  it('利用規約情報(EULAのみ)が存在しない場合エラーとなる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    const service = module.get<TermsService>(TermsService);
    await createTermInfo(source, 'DPA', 'v1.0');
    const context = makeContext(uuidv4(), 'requestId');
    await expect(service.getTermsInfo(context)).rejects.toEqual(
      new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      ),
    );
  });

  it('利用規約情報(PrivacyNoticeのみ)が存在しない場合エラーとなる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    const service = module.get<TermsService>(TermsService);
    await createTermInfo(source, 'PrivacyNotice', 'v1.0');
    const context = makeContext(uuidv4(), 'requestId');
    await expect(service.getTermsInfo(context)).rejects.toEqual(
      new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      ),
    );
  });

  it('利用規約情報(DPAのみ)が存在しない場合エラーとなる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    const service = module.get<TermsService>(TermsService);
    await createTermInfo(source, 'EULA', 'v1.0');
    const context = makeContext(uuidv4(), 'requestId');
    await expect(service.getTermsInfo(context)).rejects.toEqual(
      new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      ),
    );
  });
});
