import { inject, Injectable } from '@angular/core';
import { ReturnService } from '@generated/swagger/inventory-api';
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
import { firstValueFrom } from 'rxjs';
import { KeyValueStringAndString } from '../models';
import { logger } from '@isa/core/logging';
import { InFlight, Cache, CacheTimeToLive } from '@isa/common/decorators';
import { RemissionStockService } from './remission-stock.service';

/**
 * Service responsible for managing remission return reasons.
 * Handles fetching return reason data from the inventory API.
 *
 * @class RemissionReasonService
 * @injectable
 *
 * @example
 * // Inject the service
 * constructor(private reasonService: RemissionReasonService) {}
 *
 * // Fetch return reasons for a stock
 * const reasons = await this.reasonService.fetchReturnReasons({
 *   stockId: 'stock123'
 * });
 */
@Injectable({ providedIn: 'root' })
export class RemissionReasonService {
  #stockService = inject(RemissionStockService);
  #returnService = inject(ReturnService);
  #logger = logger(() => ({ service: 'RemissionReasonService' }));

  /**
   * Fetches all available return reasons for the specified stock.
   * Validates input parameters using FetchReturnReasonSchema.
   *
   * @async
   * @param {FetchReturnReasonParams} params - Parameters for the return reasons query
   * @param {string} params.stockId - ID of the stock to fetch reasons for
   * @param {AbortSignal} [abortSignal] - Optional signal to abort the request
   * @returns {Promise<KeyValueStringAndString[]>} Array of key-value pairs representing return reasons
   * @throws {ResponseArgsError} When the API request fails
   * @throws {z.ZodError} When parameter validation fails
   *
   * @example
   * const controller = new AbortController();
   * try {
   *   const reasons = await service.fetchReturnReasons(
   *     { stockId: 'stock123' },
   *     controller.signal
   *   );
   *   reasons.forEach(reason => {
   *     console.log(`${reason.key}: ${reason.value}`);
   *   });
   * } catch (error) {
   *   console.error('Failed to fetch return reasons:', error);
   * }
   */
  @Cache({ ttl: CacheTimeToLive.fiveMinutes })
  @InFlight()
  async fetchReturnReasons(
    abortSignal?: AbortSignal,
  ): Promise<KeyValueStringAndString[]> {
    this.#logger.debug('Fetching return reasons');

    const assignedStock =
      await this.#stockService.fetchAssignedStock(abortSignal);

    if (!assignedStock) {
      this.#logger.warn('No assigned stock found, returning empty reasons');
      return [];
    }

    this.#logger.info('Fetching return reasons from API', () => ({
      stockId: assignedStock?.id,
    }));

    let req$ = this.#returnService.ReturnGetReturnReasons({
      stockId: assignedStock?.id,
    });

    if (abortSignal) {
      this.#logger.debug('Request configured with abort signal');
      req$ = req$.pipe(takeUntilAborted(abortSignal));
    }

    const res = await firstValueFrom(req$);

    if (res.error) {
      this.#logger.error(
        'Failed to fetch return reasons',
        new Error(res.message || 'Unknown error'),
      );
      throw new ResponseArgsError(res);
    }

    this.#logger.debug('Successfully fetched return reasons', () => ({
      reasonCount: res.result?.length || 0,
    }));

    return res.result as KeyValueStringAndString[];
  }
}
