import {
  EventBus,
  // EventsHandler,
  IEventHandler,
} from '@nestjs/cqrs';
import { UserPrivilegeConfigUpdatedEvent } from '../../../entities/event/user-privilege-configuration-updated.event';
import { UserPrivilegeConfigurationHelper } from '../helpers/generate-user-privilege-configuration.helper';
import { UserPrivilegeDataService } from 'src/modules/user-related/user-privilege/data/service/user-privilege-data.service';
import { PrivilegeAction } from 'src/core/strings/constants/privilege.constants';
import { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model';
import { UserPrivilegeUpdatedEvent } from '../../../entities/event/user-privilege-updated.event';
import { OPERATION } from 'src/core/strings/constants/base.constants';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';

// FIXME => FIX HANDLER FOR ADD NEW MODULE PRIVILEGE CONFIGURATIONS

// @EventsHandler(UserPrivilegeConfigUpdatedEvent)
export class UserPrivilegeConfigUpdateHandler
  implements IEventHandler<UserPrivilegeConfigUpdatedEvent>
{
  constructor(
    private dataService: UserPrivilegeDataService,
    private eventBus: EventBus,
  ) {}

  async handle(event: UserPrivilegeConfigUpdatedEvent) {
    const data = event.data.data;
    const configuration = await this.dataService.getOneByOptions({
      where: {
        id: data.user_privilege_id,
      },
      relations: ['user_privilege_configurations'],
    });
    let configurationData = configuration?.[
      'user_privilege_configurations'
    ]?.sort((a, b) => a.index - b.index);
    const configs = UserPrivilegeConfigurationHelper.createConfigurations();

    configs
      .filter(
        (base) =>
          !configurationData.some((data) => {
            return base.menu_label == data.menu_label;
          }),
      )
      .map((item) => {
        Object.assign(item, {
          user_privilege_id: data.user_privilege_id,
        });

        configurationData.push(item);
      });

    configurationData = configurationData
      ?.filter((item) =>
        configs.some((data) => {
          return item.menu_label == data.menu_label;
        }),
      )
      ?.map((item) => {
        const exist = configs.find(
          (config) => config.menu_label == item.menu_label,
        );
        return {
          ...item,
          view: exist.actions.includes(PrivilegeAction.VIEW)
            ? item.view ?? false
            : null,
          cancel: exist.actions.includes(PrivilegeAction.CANCEL)
            ? item.cancel ?? false
            : null,
          confirm: exist.actions.includes(PrivilegeAction.CONFIRM)
            ? item.confirm ?? false
            : null,
          create: exist.actions.includes(PrivilegeAction.CREATE)
            ? item.create ?? false
            : null,
          delete: exist.actions.includes(PrivilegeAction.DELETE)
            ? item.delete ?? false
            : null,
          edit: exist.actions.includes(PrivilegeAction.EDIT)
            ? item.edit ?? false
            : null,
        };
      });

    Object.assign(configuration, {
      user_privilege_configurations: configurationData,
    });

    const queryRunner = this.dataService
      .getRepository()
      .manager.connection.createQueryRunner();

    await this.dataService.update(
      queryRunner,
      UserPrivilegeConfigurationModel,
      { id: data.user_privilege_id },
      configuration,
    );

    this.eventBus.publishAll([
      new UserPrivilegeUpdatedEvent({
        id: configuration.id,
        old: null,
        data: configuration,
        user: event.data.user,
        description: '',
        module: TABLE_NAME.USER_PRIVILEGE_CONFIGURATION,
        op: OPERATION.UPDATE,
      }),
    ]);
  }
}
