import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { CouchService } from '../../data/services/couch.service';
import { STATUS } from 'src/core/strings/constants/base.constants';
import { UserDeletedEvent } from 'src/modules/user-related/user/domain/entities/event/user-deleted.event';
import { UserChangeStatusEvent } from 'src/modules/user-related/user/domain/entities/event/user-change-status.event';
import { UserUpdatedEvent } from 'src/modules/user-related/user/domain/entities/event/user-updated.event';
import { UserDataService } from 'src/modules/user-related/user/data/services/user-data.service';
import { UserPrivilegeConfigUpdatedEvent } from 'src/modules/user-related/user-privilege/domain/entities/event/user-privilege-configuration-updated.event';

@EventsHandler(UserDeletedEvent)
export class UserDeletedHandler implements IEventHandler<UserDeletedEvent> {
  constructor(private couchService: CouchService) {}

  async handle(event: UserDeletedEvent) {
    const data = await this.couchService.deleteDoc(
      {
        _id: event.data.id,
        ...event.data.data,
      },
      'user',
    );
  }
}

@EventsHandler(UserChangeStatusEvent, UserUpdatedEvent)
export class UserUpdatedHandler
  implements IEventHandler<UserChangeStatusEvent>
{
  constructor(
    private couchService: CouchService,
    private userService: UserDataService,
  ) {}

  async handle(event: UserChangeStatusEvent) {
    const dataOld = event.data.old;
    const data = event.data.data;
    const user = await this.userService
      .getOneByOptions({
        where: {
          id: data.id,
        },
        relations: [
          'user_privilege',
          'user_privilege.user_privilege_configurations',
        ],
      })
      .then((item) => {
        if (item.role != 'superadmin') {
          const user_privilege_configurations = item[
            'user_privilege'
          ]?.user_privilege_configurations?.filter(
            (config) => config.module == 'POS',
          );
          Object.assign(item['user_privilege'], {
            user_privilege_configurations: user_privilege_configurations,
          });
        }
        return item;
      });

    // change status to active
    if (dataOld?.status != data.status && data.status == STATUS.ACTIVE) {
      await this.couchService.createDoc(
        {
          _id: data.id,
          ...user,
        },
        'user',
      );
    } else if (dataOld?.status != data.status) {
      await this.couchService.deleteDoc(
        {
          _id: data.id,
          ...user,
        },
        'user',
      );
    }

    // update
    else {
      await this.couchService.updateDoc(
        {
          _id: data.id,
          ...user,
        },
        'user',
      );
    }
  }
}

@EventsHandler(UserPrivilegeConfigUpdatedEvent)
export class UserPrivilegeUpdateHandler
  implements IEventHandler<UserPrivilegeConfigUpdatedEvent>
{
  constructor(
    private couchService: CouchService,
    private userService: UserDataService,
  ) {}

  async handle(event: UserPrivilegeConfigUpdatedEvent) {
    const data = event.data.data;

    const users = await this.userService
      .getManyByOptions({
        where: {
          user_privilege_id: data.user_privilege_id ?? data.id,
          status: STATUS.ACTIVE,
        },
        relations: [
          'user_privilege',
          'user_privilege.user_privilege_configurations',
        ],
      })
      .then((items) => {
        return items?.map((item) => {
          const user_privilege_configurations = item[
            'user_privilege'
          ]?.user_privilege_configurations?.filter(
            (config) => config.module == 'POS',
          );
          Object.assign(item['user_privilege'], {
            user_privilege_configurations: user_privilege_configurations,
          });
          return item;
        });
      });

    for (const user of users) {
      await this.couchService.updateDoc(
        {
          _id: user.id,
          ...user,
        },
        'user',
      );
    }
  }
}
