import { EventBus, EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { RefundChangeStatusEvent } from 'src/modules/transaction/refund/domain/entities/event/refund-change-status.event';
import { TransactionDataService } from '../../../data/services/transaction-data.service';
import {
  BLANK_USER,
  OPERATION,
  STATUS,
} from 'src/core/strings/constants/base.constants';
import { TransactionModel } from '../../../data/models/transaction.model';
import { RefundDeletedEvent } from 'src/modules/transaction/refund/domain/entities/event/refund-deleted.event';
import { RefundCreatedEvent } from 'src/modules/transaction/refund/domain/entities/event/refund-created.event';
import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';

@EventsHandler(RefundChangeStatusEvent, RefundDeletedEvent, RefundCreatedEvent)
export class RefundUpdatedHandler
  implements IEventHandler<RefundChangeStatusEvent>
{
  constructor(
    private dataService: TransactionDataService,
    private eventBus: EventBus,
  ) {}

  async handle(event: RefundChangeStatusEvent) {
    const current_data = event.data.data;
    let status: STATUS;

    //GET TRANSACTION DATA BEFORE UPDATE
    const oldData = current_data?.transaction;

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

    const data = new TransactionModel();
    const if_full_refund =
      Number(current_data.refund_total ?? 0) ==
      Number(current_data.transaction?.payment_total);

    if (
      event.data.op == OPERATION.DELETE ||
      current_data.status == STATUS.CANCEL
    )
      status = STATUS.SETTLED;
    else {
      if (current_data.status == STATUS.REFUNDED && if_full_refund)
        status = STATUS.REFUNDED;
      else if (current_data.status == STATUS.REFUNDED && !if_full_refund)
        status = STATUS.PARTIAL_REFUND;
      else status = STATUS.PROCESS_REFUND;
    }

    await this.dataService.update(
      queryRunner,
      TransactionModel,
      { id: current_data.transaction_id },
      {
        ...data,
        status: status,
      },
    );

    //GET TRANSACTION DATA AFTER UPDATE
    const newData = await this.dataService.getOneByOptions({
      where: {
        id: current_data.transaction_id,
      },
      relations: ['items'],
    });

    this.eventBus.publish(
      new TransactionChangeStatusEvent({
        id: current_data.transaction_id,
        old: oldData,
        data: newData,
        user: BLANK_USER,
        description: 'Refund Callback',
        module: TABLE_NAME.TRANSACTION,
        op: OPERATION.UPDATE,
      }),
    );
  }
}
