import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { NotificationhubService } from '../../gateways/notificationhub/notificationhub.service';
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
import { UserNotFoundError } from '../../repositories/users/errors/types';
import { v4 as uuidv4 } from 'uuid';
import { Context } from '../../common/log';

@Injectable()
export class NotificationService {
  private readonly logger = new Logger(NotificationService.name);
  constructor(
    private readonly usersRepository: UsersRepositoryService,
    private readonly notificationhubService: NotificationhubService,
  ) {}
  /**
   * Registers notification service
   * @param pns
   * @param pnsHandler
   * @returns register
   */
  async register(
    context: Context,
    externalId: string,
    pns: string,
    pnsHandler: string,
  ): Promise<void> {
    this.logger.log(
      `[IN] [${context.trackingId}] ${this.register.name} | params: { externalId: ${externalId}, pns: ${pns}, pnsHandler: ${pnsHandler} }`,
    );

    // ユーザIDからアカウントIDを取得する
    let userId: number;
    try {
      userId = (await this.usersRepository.findUserByExternalId(externalId)).id;
    } catch (e) {
      this.logger.error(`error=${e}`);
      switch (e.constructor) {
        case UserNotFoundError:
          throw new HttpException(
            makeErrorResponse('E010204'),
            HttpStatus.BAD_REQUEST,
          );
        default:
          throw new HttpException(
            makeErrorResponse('E009999'),
            HttpStatus.INTERNAL_SERVER_ERROR,
          );
      }
    }

    try {
      // TODO: 登録毎に新規登録する想定でUUIDを付与している
      // もしデバイスごとに登録を上書きするようであればUUID部分にデバイス識別子を設定
      const installationId = `${pns}_${userId}_${uuidv4()}`;
      this.logger.log(installationId);

      await this.notificationhubService.register(
        context,
        userId,
        pns,
        pnsHandler,
        installationId,
      );
    } catch (e) {
      this.logger.error(`error=${e}`);
      throw new HttpException(
        makeErrorResponse('E009999'),
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    } finally {
      this.logger.log(`[OUT] [${context.trackingId}] ${this.register.name}`);
    }
  }
}
