import { InjectRepository } from '@nestjs/typeorm';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { ItemQueueModel } from 'src/modules/item-related/item-queue/data/models/item-queue.model';
import { QueueDataService } from 'src/modules/queue/data/services/queue.service';
import { Repository } from 'typeorm';
import * as moment from 'moment';
import * as math from 'mathjs';
import { QueueModel } from 'src/modules/queue/data/models/queue.model';

export class QueueTimeFormula {
  constructor(
    private readonly queueDataService: QueueDataService,
    @InjectRepository(ItemQueueModel, CONNECTION_NAME.DEFAULT)
    private itemQueueRepo: Repository<ItemQueueModel>,
  ) {}

  public average = 0;

  async items(item_queue_id: string) {
    const queues = await this.queueDataService.waitingQueue(item_queue_id);
    if (queues.length == 0) {
      return {};
    }

    const itemQueue = await this.itemQueueRepo.findOne({
      relations: ['items'],
      where: {
        id: item_queue_id,
      },
    });

    const times = itemQueue.items.map((item) => item.play_estimation ?? 0);
    const average = times.length > 0 ? math.mean(times) * 60 * 1000 : 0; // change average minute to milliseconds
    this.average = Math.floor(average);

    const calledQueue = await this.queueDataService.lastQueue(item_queue_id);

    return QueueTimeFormula.queueTime(queues, calledQueue, average);
  }

  static queueTime(
    queues: QueueModel[],
    lastQueue: QueueModel,
    average: number,
  ) {
    const queueTimes = {};
    if (queues.length < 1) return queueTimes;
    const timeNow = moment().valueOf();
    const lastCall = lastQueue?.call_time ?? timeNow - average;

    const callTime = +lastCall + average;
    const currentQueueCallTime = timeNow > callTime ? timeNow : callTime;

    queueTimes[queues[0].id] = currentQueueCallTime;
    let now = currentQueueCallTime;

    for (let i = 1; i < queues.length; i++) {
      const before = queues[i - 1];
      // duration will be total qty multiple by average from last queue
      const duration = before.qty * average;

      const queue = queues[i];
      // time to call will be now + duration
      const time = now + duration;
      queueTimes[queue.id] = time;

      // update now to last call time
      now = time;
    }

    return queueTimes;
  }
}
