import { inject, Injectable } from '@angular/core';
import { StoreCheckoutSupplierService } from '@generated/swagger/checkout-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 { Supplier } from '../schemas';

/**
 * Service for fetching supplier information from the checkout API.
 *
 * Provides cached access to suppliers with automatic request deduplication.
 */
@Injectable({ providedIn: 'root' })
export class SupplierService {
  #logger = logger(() => ({ service: 'SupplierService' }));
  #supplierService = inject(StoreCheckoutSupplierService);

  /**
   * Fetches the take away supplier (supplier number 'F' for "Filiale").
   *
   * This supplier is used for in-store (Rücklage) availability.
   * Results are cached for 1 hour with automatic request deduplication.
   *
   * @param abortSignal Optional abort signal for request cancellation
   * @returns Promise resolving to the take away supplier
   * @throws ResponseArgsError if the API call fails
   * @throws Error if supplier 'F' is not found
   */
  @Cache({ ttl: CacheTimeToLive.oneHour })
  @InFlight()
  async getTakeAwaySupplier(abortSignal?: AbortSignal): Promise<Supplier> {
    this.#logger.debug('Fetching take away supplier');

    let req$ = this.#supplierService.StoreCheckoutSupplierGetSuppliers({});

    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 fetch suppliers', error);
      throw error;
    }

    const takeAwaySupplier = res.result?.find(
      (supplier) => supplier.supplierNumber === 'F',
    );

    if (!takeAwaySupplier) {
      const notFoundError = new Error('Take away supplier (F) not found');
      this.#logger.error('Take away supplier not found', notFoundError, () => ({
        availableSuppliers: res.result?.map((s) => s.supplierNumber),
      }));
      throw notFoundError;
    }

    this.#logger.debug('Take away supplier fetched', () => ({
      supplierId: takeAwaySupplier.id,
      supplierNumber: takeAwaySupplier.supplierNumber,
    }));

    return takeAwaySupplier;
  }
}
