import { ForbiddenException, Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
import { InjectDataSource } from '@nestjs/typeorm';
import { getAction } from 'src/core/helpers/path/get-action-from-path.helper';
import { UserProvider } from 'src/core/sessions';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model';
import { DataSource, IsNull } from 'typeorm';
import { UserRole } from 'src/modules/user-related/user/constants';
import { UserPrivilegeConfigurationEntity } from 'src/modules/user-related/user-privilege/domain/entities/user-privilege-configuration.entity';

@Injectable({ scope: Scope.REQUEST })
export class PrivilegeService {
  constructor(
    @InjectDataSource(CONNECTION_NAME.DEFAULT)
    protected readonly dataSource: DataSource,

    @Inject(REQUEST) private readonly request: Request,
    protected readonly session: UserProvider,
  ) {}

  get repository() {
    return this.dataSource.getRepository(UserPrivilegeConfigurationModel);
  }

  get user() {
    return this.session.user;
  }

  get action() {
    const headerAction = this.request.headers['ex-model-action'] as string;
    return headerAction ?? getAction(this.request.method, this.request.path);
  }

  async isAllowed() {
    // jika rolenya adalah superadmin, abaikan dan return true
    if (this.user.role == UserRole.SUPERADMIN) return true;

    // check privilege dan sesuaikan dengan akse
    const configurations = await this.privilegeConfiguration();
    return configurations[this.action];
  }

  async isNotAllowed() {
    return !(await this.isAllowed());
  }

  private moduleKey() {
    const headerKey = 'ex-model-key';
    const moduleKey = this.request.headers[headerKey] as string;
    if (!moduleKey) {
      throw new ForbiddenException({
        statusCode: 10005,
        message: `Akses Terlarang, anda tidak punya akses ke module ini!`,
        error: 'MODULE_KEY_NOT_FOUND',
      });
    }
    const [module, menu, sub_menu, section] = moduleKey.split('.');
    return { module, menu, sub_menu, section };
  }

  async privilegeConfiguration(): Promise<UserPrivilegeConfigurationEntity> {
    const { module, menu } = this.moduleKey();
    return await this.repository.findOne({
      select: ['id', 'view', 'create', 'edit', 'delete', 'cancel', 'confirm'],
      where: {
        user_privilege_id: this.user.user_privilege_id,
        module: module,
        menu: menu ?? IsNull(),
      },
    });
  }
}
