import { DataSource } from 'typeorm';
import {
  License,
  LicenseOrder,
} from '../../../repositories/licenses/entity/license.entity';
import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity';
import { UserGroup } from '../../../repositories/user_groups/entity/user_group.entity';
import { UserGroupMember } from '../../../repositories/user_groups/entity/user_group_member.entity';
import { Worktype } from '../../../repositories/worktypes/entity/worktype.entity';
import { OptionItem } from '../../../repositories/worktypes/entity/option_item.entity';
import { OPTION_ITEM_VALUE_TYPE } from '../../../constants';
import { Account } from '../../../repositories/accounts/entity/account.entity';

/**
 * テスト ユーティリティ: すべてのソート条件を取得する
 * @param dataSource データソース
 * @returns 該当ソート条件一覧
 */
export const getSortCriteria = async (dataSource: DataSource) => {
  return await dataSource.getRepository(SortCriteria).find();
};

export const createLicense = async (
  datasource: DataSource,
  licenseId: number,
  expiry_date: Date | null,
  accountId: number,
  type: string,
  status: string,
  allocated_user_id: number | null,
  order_id: number | null,
  deleted_at: Date | null,
  delete_order_id: number | null,
): Promise<void> => {
  const { identifiers } = await datasource.getRepository(License).insert({
    id: licenseId,
    expiry_date: expiry_date,
    account_id: accountId,
    type: type,
    status: status,
    allocated_user_id: allocated_user_id,
    order_id: order_id,
    deleted_at: deleted_at,
    delete_order_id: delete_order_id,
    created_by: 'test_runner',
    created_at: new Date(),
    updated_by: 'updater',
    updated_at: new Date(),
  });
  identifiers.pop() as License;
};

// 有効期限・ステータス付きのライセンスを作成
export const createLicenseSetExpiryDateAndStatus = async (
  datasource: DataSource,
  accountId: number,
  expiryDate: Date | null,
  status: string,
  allocated_user_id?: number | null,
): Promise<void> => {
  const { identifiers } = await datasource.getRepository(License).insert({
    expiry_date: expiryDate,
    account_id: accountId,
    type: 'NORMAL',
    status: status,
    allocated_user_id: allocated_user_id,
    order_id: null,
    deleted_at: null,
    delete_order_id: null,
    created_by: 'test_runner',
    created_at: new Date(),
    updated_by: 'updater',
    updated_at: new Date(),
  });
  identifiers.pop() as License;
};

export const createLicenseOrder = async (
  datasource: DataSource,
  fromAccountId: number,
  toAccountId: number,
  quantity: number,
  po_number = 'TEST123',
  ordered_at = new Date(),
): Promise<void> => {
  const { identifiers } = await datasource.getRepository(LicenseOrder).insert({
    po_number: po_number,
    from_account_id: fromAccountId,
    to_account_id: toAccountId,
    ordered_at: ordered_at,
    issued_at: null,
    quantity: quantity,
    status: 'Issue Requesting',
    canceled_at: null,
    created_by: 'test_runner',
    created_at: new Date(),
    updated_by: 'updater',
    updated_at: new Date(),
  });
  identifiers.pop() as License;
};

// タイピストグループを取得する
export const getTypistGroup = async (
  datasource: DataSource,
  accountId: number,
): Promise<UserGroup[]> => {
  return await datasource.getRepository(UserGroup).find({
    where: {
      account_id: accountId,
    },
  });
};
// タイピストグループメンバーを取得する
export const getTypistGroupMember = async (
  datasource: DataSource,
  userGroupId: number,
): Promise<UserGroupMember[]> => {
  return await datasource.getRepository(UserGroupMember).find({
    where: {
      user_group_id: userGroupId,
    },
  });
};

// Worktypeを作成する
export const createWorktype = async (
  datasource: DataSource,
  accountId: number,
  worktypeId: string,
  description?: string,
  isActive?: boolean,
): Promise<Worktype> => {
  const { identifiers } = await datasource.getRepository(Worktype).insert({
    account_id: accountId,
    custom_worktype_id: worktypeId,
    description: description ?? null,
    deleted_at: null,
    created_by: 'test_runner',
    created_at: new Date(),
    updated_by: 'updater',
    updated_at: new Date(),
  });
  const worktype = identifiers.pop() as Worktype;

  if (isActive) {
    await datasource.getRepository(Account).update(
      { id: accountId },
      {
        active_worktype_id: worktype.id,
      },
    );
  }
  return (await datasource
    .getRepository(Worktype)
    .findOne({ where: { id: worktype.id } })) as Worktype;
};

// Worktypeを取得する
export const getWorktypes = async (
  datasource: DataSource,
  accountId: number,
): Promise<Worktype[]> => {
  return await datasource.getRepository(Worktype).find({
    where: {
      account_id: accountId,
    },
  });
};

// オプションアイテムを作成する
export const createOptionItems = async (
  datasource: DataSource,
  worktypeId: number,
): Promise<OptionItem[]> => {
  const optionItems: OptionItem[] = [];

  for (let i = 0; i < 10; i++) {
    const optionItem = new OptionItem();
    {
      optionItem.worktype_id = worktypeId;
      optionItem.item_label = '';
      optionItem.default_value_type = OPTION_ITEM_VALUE_TYPE.DEFAULT;
      optionItem.initial_value = '';
      optionItem.created_by = 'test_runner';
      optionItem.created_at = new Date();
      optionItem.updated_by = 'updater';
      optionItem.updated_at = new Date();
    }
    optionItems.push(optionItem);
  }

  await datasource.getRepository(OptionItem).insert(optionItems);

  const items = datasource
    .getRepository(OptionItem)
    .find({ where: { worktype_id: worktypeId } });

  return items;
};

// オプションアイテムを取得する
export const getOptionItems = async (
  datasource: DataSource,
  worktypeId?: number,
): Promise<OptionItem[]> => {
  return worktypeId
    ? await datasource.getRepository(OptionItem).find({
        where: {
          worktype_id: worktypeId,
        },
      })
    : await datasource.getRepository(OptionItem).find();
};
