import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { CouchService } from '../../data/services/couch.service';
import { STATUS } from 'src/core/strings/constants/base.constants';
import { ItemDeletedEvent } from 'src/modules/item-related/item/domain/entities/event/item-deleted.event';
import { ItemUpdatedEvent } from 'src/modules/item-related/item/domain/entities/event/item-updated.event';
import { ItemChangeStatusEvent } from 'src/modules/item-related/item/domain/entities/event/item-change-status.event';
import { ItemDataService } from 'src/modules/item-related/item/data/services/item-data.service';
import { SeasonPeriodUpdatedEvent } from 'src/modules/season-related/season-period/domain/entities/event/season-period-updated.event';
import { SeasonPeriodChangeStatusEvent } from 'src/modules/season-related/season-period/domain/entities/event/season-period-change-status.event';
import { ItemRateUpdatedEvent } from 'src/modules/item-related/item-rate/domain/entities/event/item-rate-updated.event';

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

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

@EventsHandler(ItemChangeStatusEvent, ItemUpdatedEvent)
export class ItemUpdatedHandler
  implements IEventHandler<ItemChangeStatusEvent>
{
  constructor(
    private couchService: CouchService,
    private itemService: ItemDataService,
  ) {}

  async handle(event: ItemChangeStatusEvent) {
    const dataOld = event.data.old;
    const data = event.data.data;
    const dataItem = await this.itemService.getOneByOptions({
      where: {
        id: data.id,
      },
      relations: [
        'item_category',
        'bundling_items',
        'bundling_items.item_category',
        'bundling_items.time_group',
        'item_rates',
        'item_rates.item',
        'item_rates.season_period',
        'item_rates.season_period.season_type',
        'time_group',
      ],
    });

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

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

@EventsHandler(SeasonPeriodChangeStatusEvent, SeasonPeriodUpdatedEvent)
export class ItemPriceUpdatedHandler
  implements IEventHandler<SeasonPeriodChangeStatusEvent>
{
  constructor(
    private couchService: CouchService,
    private itemService: ItemDataService,
  ) {}

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

    // change status to active
    if (data.status == STATUS.ACTIVE) {
      const dataItems = await this.itemService.getManyByOptions({
        where: {
          status: STATUS.ACTIVE,
        },
        relations: [
          'item_category',
          'bundling_items',
          'bundling_items.item_category',
          'bundling_items.time_group',
          'item_rates',
          'item_rates.item',
          'item_rates.season_period',
          'item_rates.season_period.season_type',
          'time_group',
        ],
      });

      for (const dataItem of dataItems) {
        await this.couchService.updateDoc(
          {
            _id: dataItem.id,
            ...dataItem,
          },
          'item',
        );
      }
    }
  }
}

@EventsHandler(ItemRateUpdatedEvent)
export class ItemRateUpdatedHandler
  implements IEventHandler<ItemRateUpdatedEvent>
{
  constructor(
    private couchService: CouchService,
    private itemService: ItemDataService,
  ) {}

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

    const dataItems = await this.itemService.getManyByOptions({
      where: {
        status: STATUS.ACTIVE,
        id: data.item?.id,
      },
      relations: [
        'item_category',
        'bundling_items',
        'bundling_items.item_category',
        'bundling_items.time_group',
        'item_rates',
        'item_rates.item',
        'item_rates.season_period',
        'item_rates.season_period.season_type',
        'time_group',
      ],
    });

    for (const dataItem of dataItems) {
      await this.couchService.updateDoc(
        {
          _id: dataItem.id,
          ...dataItem,
        },
        'item',
      );
    }
  }
}
