import { Injectable } from '@nestjs/common';
import {
  EventTopics,
  columnUniques,
  validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager';
import { STATUS } from 'src/core/strings/constants/base.constants';
import { QueueItemModel, QueueModel } from '../../data/models/queue.model';
import { padCode } from 'src/modules/transaction/vip-code/domain/usecases/managers/helpers/generate-random.helper';
import { QueueBucketReadService } from '../../data/services/queue-bucket';
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
import { QueueTimeFormula } from './formula/queue-time.formula';
import { WhatsappService } from 'src/services/whatsapp/whatsapp.service';
import { WhatsappQueue } from 'src/services/whatsapp/entity/whatsapp-queue.entity';
import * as moment from 'moment';

@Injectable()
export class RegisterQueueManager extends BaseCreateManager<QueueModel> {
  constructor(
    private readonly bucketService: QueueBucketReadService,
    private readonly queueTimeFormula: QueueTimeFormula,
  ) {
    super();
  }

  private currentItemMaster: ItemModel;

  async averageTime(): Promise<number> {
    const item = await this.getItemMaster();
    return item.play_estimation;
  }

  async queueTime(queue_id: string): Promise<number[]> {
    const queueTimes = await this.queueTimeFormula.items(queue_id);
    const queues = Object.values<number>(queueTimes);

    const first = queues[0];
    const last = queues[queues.length - 1] ?? moment().valueOf();
    const average = this.queueTimeFormula.average;
    return [Math.floor(first), Math.floor(last + average)];
  }

  async beforeProcess(): Promise<void> {
    const vip = this.data.vip ?? false;
    const item = await this.getItemMaster();
    this.currentItemMaster = item;
    const [, end] = await this.queueTime(item.item_queue_id);

    const queueNumber = await this.bucketService.getQueue(
      item.item_queue_id,
      vip,
    );
    const prefix = vip ? 'B' : 'A';
    const code = `${prefix}${padCode(queueNumber)}`;

    Object.assign(this.data, {
      status: STATUS.WAITING,
      time: end,
      item_queue_id: item.item_queue_id,
      vip,
      code,
    });
    return;
  }

  async getItemMaster(): Promise<ItemModel> {
    const queueItem: QueueItemModel = await this.dataService.item.findOne({
      relations: ['item', 'item.item_queue'],
      where: {
        id: this.data.item_id,
      },
    });

    return queueItem.item;
  }

  async afterProcess(): Promise<void> {
    const notificationService = new WhatsappService();
    const item = this.currentItemMaster ?? (await this.getItemMaster());

    if (!item.item_queue.use_notification) return;

    const queueTicket = await this.dataService.queueTicket(this.result.id);

    const payload: WhatsappQueue = {
      id: this.result.id,
      phone: queueTicket.item.ticket.phone,
      code: this.result.code,
      name: queueTicket.item.ticket.customer,
      item_name: item.name,
      time: this.result.time,
    };

    if (payload.phone) {
      notificationService.queueRegister(payload);
      const currentTime = moment().valueOf();
      this.dataService.updateLastNotification(this.result.id, currentTime);
    }
    return;
  }

  get validateRelations(): validateRelations[] {
    return [];
  }

  get uniqueColumns(): columnUniques[] {
    return [];
  }

  get eventTopics(): EventTopics[] {
    return [];
  }

  get entityTarget(): any {
    return QueueModel;
  }
}
