import { Injectable, UnauthorizedException } from '@nestjs/common';
import { TicketDataService } from '../data/services/ticket.service';
import { QueueOrder } from './entities/order.entity';
import { Queue } from './entities/queue.entity';
import {
  QueueOrderService,
  QueueService,
} from '../data/services/queue.service';
import { RegisterQueueManager } from './usecases/register-queue.manager';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { RegisterQueueDto } from '../infrastructure/controllers/dto/register-queue.dto';
import { CustomerQueueSummaryManager } from './usecases/queue/customer-queue-summary.manager';
import { CustomerQueueDetailManager } from './usecases/queue/customer-queue-detail.manager';
import { CustomerQueueItemManager } from './usecases/queue/customer-queue-item.manager';
import { CustomerQueueItemListManager } from './usecases/queue/customer-queue-item-list.manager';
import { CustomerQueueListManager } from './usecases/queue/customer-queue-list.manager';
import { SplitQueueDto } from '../infrastructure/controllers/dto/split-queue.dto';
import { SplitQueueManager } from './usecases/split-queue.manager';

@Injectable()
export class QueueOrchestrator {
  constructor(
    private readonly dataService: TicketDataService,
    private readonly queueService: QueueService,
    private readonly queueOrderService: QueueOrderService,
    private readonly registerQueueManager: RegisterQueueManager,
    private readonly splitQueueManager: SplitQueueManager,
  ) {}

  async loginCustomer(id: string): Promise<QueueOrder> {
    try {
      return await this.dataService.loginQueue(id);
    } catch (error) {
      throw new UnauthorizedException({
        message: 'Invoice tidak ditemukan',
        error: 'INVOICE_NOT_FOUND',
      });
    }
  }

  async create(data: RegisterQueueDto): Promise<Queue> {
    const queue = await this.queueService.getTicketItems(
      data.ticket_id,
      data.item_id,
    );
    const queueRequest: any = {
      qty: data.qty,
      item_id: queue.id,
    };
    this.registerQueueManager.setData(queueRequest);
    this.registerQueueManager.setService(this.queueService, TABLE_NAME.QUEUE);
    await this.registerQueueManager.execute();
    return this.registerQueueManager.getResult();
  }

  async split(data: SplitQueueDto): Promise<QueueOrder> {
    const queueIds = data.items.map((i) => i.queue_item_id);
    const queue = await this.dataService.orderItems(data.order_id, queueIds);
    // queue.tickets = queue.tickets.map((ticket) => {
    //   ticket.items = ticket.items.map((item) => {
    //     const itemQty = data.items.find((i) => i.queue_item_id === item.id);
    //     return {
    //       ...item,
    //       qty: itemQty.qty,
    //     };
    //   });
    //   return ticket;
    // });

    this.splitQueueManager.setRequestData(data);
    this.splitQueueManager.setData(queue);
    this.splitQueueManager.setService(
      this.queueOrderService,
      TABLE_NAME.QUEUE_ORDER,
    );
    await this.splitQueueManager.execute();
    return this.splitQueueManager.getResult();
  }

  async queueTickets(order_id: string): Promise<any> {
    const tickets = await this.dataService.queueTickets(order_id);
    const manager = new CustomerQueueSummaryManager(tickets);
    return manager.data;
  }

  async queueTicketDetail(order_id: string, ticket_id: string): Promise<any> {
    const tickets = await this.dataService.queueTicketItems(
      order_id,
      ticket_id,
    );
    const manager = new CustomerQueueDetailManager(tickets);
    return manager.data;
  }

  async queueItemDetail(order_id: string, item_id: string): Promise<any> {
    const tickets = await this.dataService.queueItemTickets(order_id, item_id);
    const manager = new CustomerQueueItemManager(tickets);
    return manager.data;
  }

  async queueItems(order_id: string): Promise<any> {
    const tickets = await this.dataService.queueTickets(order_id);
    const manager = new CustomerQueueItemListManager(tickets);
    return manager.data;
  }

  async queueOrderItems(order_id: string): Promise<any> {
    const tickets = await this.dataService.queueTickets(order_id);
    const manager = new CustomerQueueListManager(tickets);
    return manager.data;
  }
}
