import { DataSource } from 'typeorm';
import {
  License,
  CardLicense,
  CardLicenseIssue,
  LicenseAllocationHistory,
  LicenseOrder,
  LicenseArchive,
  LicenseAllocationHistoryArchive,
} from '../../../repositories/licenses/entity/license.entity';

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 createCardLicense = async (
  datasource: DataSource,
  licenseId: number,
  issueId: number,
  cardLicenseKey: string,
): Promise<void> => {
  const { identifiers } = await datasource.getRepository(CardLicense).insert({
    license_id: licenseId,
    issue_id: issueId,
    card_license_key: cardLicenseKey,
    activated_at: null,
    created_by: 'test_runner',
    created_at: new Date(),
    updated_by: 'updater',
    updated_at: new Date(),
  });
  identifiers.pop() as CardLicense;
};

export const createCardLicenseIssue = async (
  datasource: DataSource,
  issueId: number,
): Promise<void> => {
  const { identifiers } = await datasource
    .getRepository(CardLicenseIssue)
    .insert({
      id: issueId,
      issued_at: new Date(),
      created_by: 'test_runner',
      created_at: new Date(),
      updated_by: 'updater',
      updated_at: new Date(),
    });
  identifiers.pop() as CardLicenseIssue;
};

export const createLicenseAllocationHistory = async (
  datasource: DataSource,
  historyId: number,
  userId: number,
  licenseId: number,
  accountId: number,
  type: string,
): Promise<void> => {
  const { identifiers } = await datasource
    .getRepository(LicenseAllocationHistory)
    .insert({
      id: historyId,
      user_id: userId,
      license_id: licenseId,
      is_allocated: true,
      account_id: accountId,
      executed_at: new Date(),
      switch_from_type: type,
      deleted_at: null,
      created_by: null,
      created_at: new Date(),
      updated_by: null,
      updated_at: new Date(),
    });
  identifiers.pop() as LicenseAllocationHistory;
};

export const createOrder = async (
  datasource: DataSource,
  poNumber: string,
  fromId: number,
  toId: number,
  issuedAt: Date | null,
  quantity: number,
  status: string,
): Promise<void> => {
  const { identifiers } = await datasource.getRepository(LicenseOrder).insert({
    po_number: poNumber,
    from_account_id: fromId,
    to_account_id: toId,
    ordered_at: new Date(),
    issued_at: issuedAt,
    quantity: quantity,
    status: status,
    canceled_at: null,
    created_by: null,
    created_at: new Date(),
    updated_by: null,
    updated_at: new Date(),
  });
  identifiers.pop() as LicenseOrder;
};

export const selectCardLicensesCount = async (
  datasource: DataSource,
): Promise<{ count: number }> => {
  const count = await datasource.getRepository(CardLicense).count();
  return { count: count };
};

export const selectCardLicense = async (
  datasource: DataSource,
  cardLicenseKey: string,
): Promise<{ cardLicense: CardLicense | null }> => {
  const cardLicense = await datasource.getRepository(CardLicense).findOne({
    where: {
      card_license_key: cardLicenseKey,
    },
  });
  return { cardLicense };
};

export const selectLicense = async (
  datasource: DataSource,
  id: number,
): Promise<{ license: License | null }> => {
  const license = await datasource.getRepository(License).findOne({
    where: {
      id: id,
    },
  });
  return { license };
};

export const selectLicenseAllocationHistory = async (
  datasource: DataSource,
  userId: number,
  licence_id: number,
): Promise<{ licenseAllocationHistory: LicenseAllocationHistory | null }> => {
  const licenseAllocationHistory = await datasource
    .getRepository(LicenseAllocationHistory)
    .findOne({
      where: {
        user_id: userId,
        license_id: licence_id,
      },
      order: {
        executed_at: 'DESC',
      },
    });
  return { licenseAllocationHistory };
};

export const selectOrderLicense = async (
  datasource: DataSource,
  accountId: number,
  poNumber: string,
): Promise<{ orderLicense: LicenseOrder | null }> => {
  const orderLicense = await datasource.getRepository(LicenseOrder).findOne({
    where: {
      from_account_id: accountId,
      po_number: poNumber,
    },
  });
  return { orderLicense };
};

/**
 * テスト ユーティリティ: ライセンス退避テーブルの内容を取得する
 * @param dataSource データソース
 * @returns ライセンス退避テーブルの内容
 */
export const getLicenseArchive = async (
  dataSource: DataSource,
): Promise<LicenseArchive[]> => {
  return await dataSource.getRepository(LicenseArchive).find();
};

/**
 * テスト ユーティリティ: ライセンス割り当て履歴退避テーブルの内容を取得する
 * @param dataSource データソース
 * @returns ライセンス割り当て履歴退避テーブルの内容
 */
export const getLicenseAllocationHistoryArchive = async (
  dataSource: DataSource,
): Promise<LicenseAllocationHistoryArchive[]> => {
  return await dataSource.getRepository(LicenseAllocationHistoryArchive).find();
};
