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

/**
 * Service responsible for managing remission product groups.
 * Handles fetching product group data from the remission API.
 *
 * @class RemissionProductGroupService
 * @injectable
 *
 * @example
 * // Inject the service
 * constructor(private productGroupService: RemissionProductGroupService) {}
 *
 * // Fetch product groups for a stock
 * const groups = await this.productGroupService.fetchProductGroups({
 *   assignedStockId: 'stock123'
 * });
 */
@Injectable({ providedIn: 'root' })
export class RemissionProductGroupService {
  #remiService = inject(RemiService);
  #stockService = inject(RemissionStockService);
  #logger = logger(() => ({ service: 'RemissionProductGroupService' }));

  /**
   * Fetches all available product groups for the specified stock.
   * Validates input parameters using FetchProductGroupsSchema.
   *
   * @async
   * @param {FetchProductGroups} params - Parameters for the product groups query
   * @param {string} params.assignedStockId - ID of the assigned stock
   * @returns {Promise<KeyValueStringAndString[]>} Array of key-value pairs representing product groups
   * @throws {Error} When the API request fails or returns an error
   * @throws {z.ZodError} When parameter validation fails
   *
   * @example
   * try {
   *   const productGroups = await service.fetchProductGroups({
   *     assignedStockId: 'stock123'
   *   });
   *   productGroups.forEach(group => {
   *     console.log(`${group.key}: ${group.value}`);
   *   });
   * } catch (error) {
   *   console.error('Failed to fetch product groups:', error);
   * }
   */
  @Cache({ ttl: CacheTimeToLive.fiveMinutes })
  @InFlight()
  async fetchProductGroups(
    abortSignal?: AbortSignal,
  ): Promise<KeyValueStringAndString[]> {
    this.#logger.debug('Fetching product groups');

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

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

    let req$ = this.#remiService.RemiProductgroups({
      stockId: assignedStock.id,
    });

    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 product groups', error);
      throw error;
    }

    this.#logger.debug('Successfully fetched product groups', () => ({
      groupCount: res.result?.length || 0,
    }));

    return res.result as KeyValueStringAndString[];
  }
}
