import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { sign } from '../../common/jwt';
import sendgrid from '@sendgrid/mail';
import { getPrivateKey } from '../../common/jwt/jwt';

@Injectable()
export class SendGridService {
  private readonly logger = new Logger(SendGridService.name);
  constructor(private readonly configService: ConfigService) {
    const key = this.configService.get<string>('SENDGRID_API_KEY');
    sendgrid.setApiKey(key);
  }

  /**
   * Email認証用のメールコンテンツを作成する
   * @param accountId 認証対象のユーザーが所属するアカウントのID
   * @param userId 認証対象のユーザーのID
   * @param email  認証対象のユーザーのメールアドレス
   * @returns メールのサブジェクトとコンテンツ
   */
  async createMailContentFromEmailConfirm(
    accountId: number,
    userId: number,
    email: string,
  ): Promise<{ subject: string; text: string; html: string }> {
    const lifetime =
      this.configService.get<number>('EMAIL_CONFIRM_LIFETIME') ?? 0;
    const privateKey = getPrivateKey(this.configService);
    const token = sign<{ accountId: number; userId: number; email: string }>(
      {
        accountId,
        userId,
        email,
      },
      lifetime,
      privateKey,
    );
    const domains = this.configService.get<string>('APP_DOMAIN');
    const path = 'mail-confirm/';

    return {
      subject: 'Verify your new account',
      text: `The verification URL. ${domains}${path}?verify=${token}`,
      html: `<p>The verification URL.<p><a href="${domains}${path}?verify=${token}">${domains}${path}?verify=${token}"</a>`,
    };
  }

  /**
   * Email認証用のメールコンテンツを作成する(一般ユーザ向け)
   * @param accountId 認証対象のユーザーが所属するアカウントのID
   * @param userId 認証対象のユーザーのID
   * @param email  認証対象のユーザーのメールアドレス
   * @returns メールのサブジェクトとコンテンツ
   */
  //TODO [Task2163] 中身が管理ユーザ向けのままなので、修正の必要あり
  async createMailContentFromEmailConfirmForNormalUser(
    accountId: number,
    userId: number,
    email: string,
  ): Promise<{ subject: string; text: string; html: string }> {
    const lifetime =
      this.configService.get<number>('EMAIL_CONFIRM_LIFETIME') ?? 0;

    const privateKey = getPrivateKey(this.configService);

    const token = sign<{ accountId: number; userId: number; email: string }>(
      {
        accountId,
        userId,
        email,
      },
      lifetime,
      privateKey,
    );
    const domains = this.configService.get<string>('APP_DOMAIN');
    const path = 'mail-confirm/user/';

    return {
      subject: 'Verify your new account',
      text: `The verification URL. ${domains}${path}?verify=${token}`,
      html: `<p>The verification URL.<p><a href="${domains}${path}?verify=${token}">${domains}${path}?verify=${token}"</a>`,
    };
  }

  /**
   * メールを送信する
   * @param accountId アカウントID
   * @param userId ユーザーID
   * @returns user confirm token
   */
  async sendMail(
    to: string,
    from: string,
    subject: string,
    text: string,
    html: string,
  ): Promise<void> {
    try {
      const res = await sendgrid
        .send({
          from: {
            email: from,
          },
          to: {
            email: to,
          },
          subject: subject,
          text: text,
          html: html,
        })
        .then((v) => v[0]);
      this.logger.log(
        `status code: ${res.statusCode} body: ${JSON.stringify(res.body)}`,
      );
    } catch (e) {
      console.log(JSON.stringify(e));
      throw e;
    }
  }
}
