import { inject, Injectable } from '@angular/core';
import {
  OrderCheckoutService,
  LogisticianService,
  LogisticianDTO,
} from '@generated/swagger/oms-api';
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
import { logger } from '@isa/core/logging';
import { firstValueFrom } from 'rxjs';
import { DisplayOrder } from '../models';

/**
 * Service for creating orders from checkout.
 *
 * @remarks
 * This service handles order creation operations that are part of the OMS domain.
 * It provides methods to:
 * - Create orders from a completed checkout
 * - Retrieve logistician information
 */
@Injectable({ providedIn: 'root' })
export class OrderCreationService {
  #logger = logger(() => ({ service: 'OrderCreationService' }));
  readonly #orderCheckoutService = inject(OrderCheckoutService);
  readonly #logisticianService = inject(LogisticianService);

  /**
   * Creates orders from a checkout.
   *
   * @param checkoutId - The ID of the checkout to create orders from
   * @returns Promise resolving to array of created orders
   * @throws {Error} If checkoutId is invalid or order creation fails
   */
  async createOrdersFromCheckout(checkoutId: number): Promise<DisplayOrder[]> {
    if (!checkoutId) {
      throw new Error(`Invalid checkoutId: ${checkoutId}`);
    }

    const req$ = this.#orderCheckoutService.OrderCheckoutCreateOrderPOST({
      checkoutId,
    });

    const res = await firstValueFrom(req$);

    if (res.error) {
      const error = new ResponseArgsError(res);
      this.#logger.error('Failed to create orders', error);
      throw error;
    }

    return res.result as DisplayOrder[];
  }

  /**
   * Retrieves logistician information.
   *
   * @param logisticianNumber - The logistician number to retrieve (defaults to '2470')
   * @param abortSignal - Optional signal to abort the operation
   * @returns Promise resolving to logistician data
   * @throws {Error} If logistician is not found or request fails
   */
  async getLogistician(
    logisticianNumber = '2470',
    abortSignal?: AbortSignal,
  ): Promise<LogisticianDTO> {
    let req$ = this.#logisticianService.LogisticianGetLogisticians({});
    if (abortSignal) req$ = req$.pipe(takeUntilAborted(abortSignal));

    const res = await firstValueFrom(req$);

    if (res.error) {
      const error = new ResponseArgsError(res);
      this.#logger.error('Failed to get logistician', error);
      throw error;
    }

    const logistician = res.result?.find(
      (l) => l.logisticianNumber === logisticianNumber,
    );

    if (!logistician) {
      throw new Error(`Logistician ${logisticianNumber} not found`);
    }

    return logistician;
  }
}
