import { Injectable } from '@nestjs/common';
import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
import { UserEntity } from '../../domain/entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { UserModel } from '../models/user.model';
import {
  CONNECTION_NAME,
  OPERATION,
} from 'src/core/strings/constants/base.constants';
import { IsNull, Not, Repository } from 'typeorm';
import { UserLoginModel } from '../models/user-login.model';
import { UserLoginEntity } from '../../domain/entities/user-login.entity';
import { LogUserType } from 'src/core/helpers/constant';
import { EventBus } from '@nestjs/cqrs';
import { LogUserLoginEvent } from 'src/modules/configuration/log/domain/entities/log-user-login.event';

@Injectable()
export class UserDataService extends BaseDataService<UserEntity> {
  constructor(
    @InjectRepository(UserModel, CONNECTION_NAME.DEFAULT)
    private repo: Repository<UserModel>,

    @InjectRepository(UserLoginModel, CONNECTION_NAME.DEFAULT)
    private repoLoginUser: Repository<UserLoginModel>,

    private eventBus: EventBus,
  ) {
    super(repo);
  }

  async getLoginUserByItem(itemId: string) {
    return this.repoLoginUser.findOne({
      where: { item_id: itemId, user_id: Not(IsNull()) },
    });
  }

  async saveUserLogin(userLogin: UserLoginEntity) {
    return this.repoLoginUser.save(userLogin);
  }

  async removeUserLogin(userLogin: Partial<UserLoginEntity>) {
    return this.repoLoginUser.delete(userLogin);
  }

  async forceLogout(token: string) {
    const data = await this.repoLoginUser.findOneBy({ login_token: token });

    if (data) return;
    else {
      await this.repoLoginUser.delete({ login_token: token });

      const [, body] = token.split('.');
      const bodyToken = JSON.parse(atob(body));
      const user = {
        role: bodyToken.role,
        user_id: bodyToken.id,
        username: bodyToken.username,
        user_privilege_id: bodyToken.user_privilege_id,
        item_id: bodyToken.item_id,
        item_name: bodyToken.item_name,
        source: bodyToken.source,
      };

      const userLogout = {
        type: LogUserType.logout,
        created_at: new Date().getTime(),
        name: user.username,
        user_privilege_id: user.user_privilege_id,
        ...user,
      };

      this.eventBus.publish(
        new LogUserLoginEvent({
          id: user.user_id,
          old: null,
          data: userLogout,
          user: userLogout as any,
          description: 'Logout',
          module: UserModel.name,
          op: OPERATION.UPDATE,
        }),
      );

      return;
    }
  }
}
