import { inject, Injectable } from '@angular/core';
import { LogisticianService as GeneratedLogisticianService } from '@generated/swagger/oms-api';
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
import { logger } from '@isa/core/logging';
import { firstValueFrom } from 'rxjs';
import { Cache, CacheTimeToLive, InFlight } from '@isa/common/decorators';
import { Logistician } from '../models';

/**
 * Service for fetching logistician information from the OMS API.
 *
 * Provides cached access to logisticians with automatic request deduplication.
 */
@Injectable({ providedIn: 'root' })
export class LogisticianService {
  #logger = logger(() => ({ service: 'LogisticianService' }));
  #logisticianService = inject(GeneratedLogisticianService);

  /**
   * Fetches logistician '2470' for B2B delivery.
   *
   * This logistician is used for B2B shipping availability overrides.
   * Results are cached for 1 hour with automatic request deduplication.
   *
   * @param abortSignal Optional abort signal for request cancellation
   * @returns Promise resolving to logistician 2470
   * @throws ResponseArgsError if the API call fails
   * @throws Error if logistician 2470 is not found
   */
  @Cache({ ttl: CacheTimeToLive.oneHour })
  @InFlight()
  async getLogistician2470(abortSignal?: AbortSignal): Promise<Logistician> {
    this.#logger.debug('Fetching logistician 2470');

    let req$ = this.#logisticianService.LogisticianGetLogisticians({});

    if (abortSignal) {
      req$ = req$.pipe(takeUntilAborted(abortSignal));
    }

    const res = await firstValueFrom(req$);

    if (res.error || !res.result) {
      const error = new ResponseArgsError(res);
      this.#logger.error('Failed to fetch logisticians', error);
      throw error;
    }

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

    if (!logistician) {
      const notFoundError = new Error('Logistician 2470 not found');
      this.#logger.error('Logistician 2470 not found', notFoundError, () => ({
        availableLogisticians: res.result?.map((l) => l.logisticianNumber),
      }));
      throw notFoundError;
    }

    this.#logger.debug('Logistician 2470 fetched', () => ({
      logisticianId: logistician.id,
      logisticianNumber: logistician.logisticianNumber,
    }));

    return logistician;
  }
}
