import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { TemplateFile } from './entity/template_file.entity';
import { insertEntity, updateEntity } from '../../common/repository';
import { Context } from '../../common/log';

@Injectable()
export class TemplateFilesRepositoryService {
  //クエリログにコメントを出力するかどうか
  private readonly isCommentOut = process.env.STAGE !== 'local';

  constructor(private dataSource: DataSource) {}

  /**
   * アカウント内のテンプレートファイルの一覧を取得する
   * @param accountId
   * @returns template files
   */
  async getTemplateFiles(
    context: Context,
    accountId: number,
  ): Promise<TemplateFile[]> {
    return await this.dataSource.transaction(async (entityManager) => {
      const templateFilesRepo = entityManager.getRepository(TemplateFile);

      const templates = await templateFilesRepo.find({
        where: { account_id: accountId },
        comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
      });

      return templates;
    });
  }

  /**
   * アカウント内にテンプレートファイルを追加（すでに同名ファイルがあれば更新）する
   * @param accountId
   * @param fileName
   * @param url
   * @returns template file
   */
  async upsertTemplateFile(
    context: Context,
    accountId: number,
    fileName: string,
    url: string,
  ): Promise<void> {
    await this.dataSource.transaction(async (entityManager) => {
      const templateFilesRepo = entityManager.getRepository(TemplateFile);

      // アカウント内に同名ファイルがあるか確認
      const template = await templateFilesRepo.findOne({
        where: { account_id: accountId, file_name: fileName },
        comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
        lock: { mode: 'pessimistic_write' },
      });

      // 同名ファイルは同じものとして扱うため、すでにファイルがあれば更新（更新日時の履歴を残しておきたい）
      if (template) {
        await updateEntity(
          templateFilesRepo,
          { id: template.id },
          { file_name: fileName, url: url },
          this.isCommentOut,
          context,
        );
      } else {
        const newTemplate = new TemplateFile();
        newTemplate.account_id = accountId;
        newTemplate.file_name = fileName;
        newTemplate.url = url;
        await insertEntity(
          TemplateFile,
          templateFilesRepo,
          newTemplate,
          this.isCommentOut,
          context,
        );
      }
    });
  }
}
