import {
  HttpStatus,
  Injectable,
  UnprocessableEntityException,
} 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 { QueueOrderModel } from '../../data/models/queue.model';
import { SplitQueueDto } from '../../infrastructure/controllers/dto/split-queue.dto';
import { QueueService } from '../../data/services/queue.service';
import { TicketDataService } from '../../data/services/ticket.service';

@Injectable()
export class SplitQueueManager extends BaseCreateManager<QueueOrderModel> {
  private dto: SplitQueueDto;
  constructor(
    private readonly queueService: QueueService,
    private readonly ticketService: TicketDataService,
  ) {
    super();
  }

  setRequestData(dto: SplitQueueDto): void {
    this.dto = dto;
  }

  async validateProcess(): Promise<void> {
    await super.validateProcess();
    const existTickets = await this.ticketService.ticketByUser(
      this.dto.name,
      this.dto.phone,
    );
    if (existTickets) {
      throw new UnprocessableEntityException({
        statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
        code: 20002,
        message:
          'Antrian dengan nama dan nomor telepon sudah terdaftar, silahkan gunakan nomor telepon atau nama lain',
        error: 'QUEUE_ALREADY_EXIST',
      });
    }
  }

  async prepareData(): Promise<void> {
    const existTickets = await this.ticketService.ticketByCode(this.data.code);
    const { tickets, ...order } = this.data;
    const ticket = tickets[0];
    const items = tickets
      .map((ticket) => {
        return ticket.items;
      })
      .flat();
    const postfix = existTickets.length;
    this.data = {
      code: order.code,
      customer: this.dto.name,
      phone: this.dto.phone,
      date: order.date,
      updated_at: new Date().getTime(),
      tickets: [
        {
          code: `${order.code}-${postfix}`,
          customer: this.dto.name,
          phone: this.dto.phone,
          date: ticket.date,
          order_id: order.id,
          items: items.map((item) => {
            const itemQty = this.dto.items.find(
              (i) => i.queue_item_id === item.id,
            );
            return {
              item_id: item.item_id,
              qty: itemQty.qty,
            };
          }),
        },
      ],
    };
    super.prepareData();
    return;
  }

  async beforeProcess(): Promise<void> {
    return;
  }

  async afterProcess(): Promise<void> {
    this.dto.items.forEach((item) => {
      this.queueService.updateItemQty(item.queue_item_id, item.qty);
    });
    return;
  }

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

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

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

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