import {
  HttpStatus,
  Inject,
  Injectable,
  Logger,
  UnauthorizedException,
} from '@nestjs/common';
import { validatePassword } from 'src/core/helpers/password/bcrypt.helpers';
import { BaseCustomManager } from 'src/core/modules/domain/usecase/managers/base-custom.manager';
import { SessionService } from 'src/core/sessions';
import { STATUS } from 'src/core/strings/constants/base.constants';
import { EventTopics } from 'src/core/strings/constants/interface.constants';
import { UserModel } from 'src/modules/user-related/user/data/models/user.model';
import { UserEntity } from 'src/modules/user-related/user/domain/entities/user.entity';
import { In } from 'typeorm';
import { UserRole } from 'src/modules/user-related/user/constants';
import { AppSource, LogUserType } from 'src/core/helpers/constant';
import { LogUserLoginEvent } from 'src/modules/configuration/log/domain/entities/log-user-login.event';
import { UserLoginEntity } from 'src/modules/user-related/user/domain/entities/user-login.entity';

@Injectable()
export class LoginAdminQueueManager extends BaseCustomManager<UserEntity> {
  @Inject()
  protected session: SessionService;
  protected token;
  protected userLogin;

  async validateProcess(): Promise<void> {
    return;
  }

  async beforeProcess(): Promise<void> {
    return;
  }

  async process(): Promise<void> {
    const itemLogin = await this.dataService.getLoginUserByItem(
      this.data.item_id,
    );

    // get user active by username
    this.userLogin = await this.dataService.getOneByOptions({
      where: {
        username: this.data.username,
        status: STATUS.ACTIVE,
        role: In([UserRole.QUEUE_ADMIN, UserRole.SUPERADMIN]),
      },
      relations: ['user_login'],
    });

    if (!this.userLogin) this.throwError();

    // validasi password
    const valid = await validatePassword(
      this.data.password,
      this.userLogin?.password,
    );
    if (!valid) this.throwError();

    const userLoginItem = await this.dataService.getOneByOptions({
      where: {
        id: itemLogin?.user_id,
      },
    });

    const hasLoginAsQueue = this.userLogin?.user_login?.find(
      (item) => item.source === AppSource.QUEUE_ADMIN,
    );

    if (hasLoginAsQueue && hasLoginAsQueue?.item_id !== this.data.item_id) {
      throw new UnauthorizedException({
        statusCode: HttpStatus.UNAUTHORIZED,
        message: `Akun anda sudah login di item "${hasLoginAsQueue?.item_name}"`,
        error: 'Unauthorized',
      });
    }
    // else if (itemLogin && itemLogin.user_id !== this.userLogin.id) {
    //   throw new UnauthorizedException({
    //     statusCode: HttpStatus.UNAUTHORIZED,
    //     message: `"${userLoginItem.name}" masih login sebagai admin antrian `,
    //     error: 'Unauthorized',
    //   });
    // }

    // * Disini untuk isi token
    const tokenData = {
      id: this.userLogin.id,
      name: this.userLogin.name,
      username: this.userLogin.username,
      role: this.userLogin.role,
      user_privilege_id: this.userLogin.user_privilege_id,
      item_id: this.data.item_id,
      item_name: this.data.item_name,
      source: AppSource.QUEUE_ADMIN,
    };

    Logger.debug('Sign Token Admin Queue', 'LoginAdminQueueManager');
    this.token = this.session.createAccessToken(tokenData);

    Logger.debug('Save Login Token', 'LoginManager');
    const userLoginData: UserLoginEntity = {
      user_id: this.userLogin.id,
      login_token: this.token,
      login_date: new Date().getTime(),
      source: AppSource.QUEUE_ADMIN,
      role: this.userLogin.role,
      item_id: this.data.item_id,
      item_name: this.data.item_name,
    };
    if (hasLoginAsQueue?.item_id === this.data.item_id) {
      Object.assign(userLoginData, { id: hasLoginAsQueue.id });
    }
    // Update refresh token
    await this.dataService.saveUserLogin(userLoginData);

    await this.publishEvents();

    Logger.debug('Process Login Admin Queue Done', 'LoginAdminQueueManager');
    return;
  }

  async afterProcess(): Promise<void> {
    return;
  }

  getResult() {
    return {
      id: this.userLogin.id,
      name: this.userLogin.name,
      username: this.userLogin.username,
      role: this.userLogin.role,
      token: this.token,
      item_id: this.data.item_id,
      item_name: this.data.item_name,
    };
  }

  get entityTarget(): any {
    return UserModel;
  }

  get eventTopics(): EventTopics[] {
    return [
      {
        topic: LogUserLoginEvent,
        data: {
          type: LogUserType.login,
          role: this.userLogin.role,
          user_id: this.userLogin.id,
          username: this.userLogin.username,
          created_at: new Date().getTime(),
          item_id: this.data.item_id,
          item_name: this.data.item_name,
          source: AppSource.QUEUE_ADMIN,
        },
      },
    ];
  }

  // !throw errornya akan sama, untuk security
  throwError() {
    throw new UnauthorizedException({
      statusCode: HttpStatus.UNAUTHORIZED,
      message: `Gagal! username atau password tidak sesuai`,
      error: 'Unauthorized',
    });
  }
}
