import {
  computed,
  inject,
  Injectable,
  resource,
  signal,
  Signal,
} from '@angular/core';
import { OrdersService } from '../services/orders.service';
import { DisplayOrderDTO } from '@generated/swagger/oms-api';

/**
 * Resource for fetching display orders by their numeric IDs.
 *
 * Provides reactive access to display order data with loading and error states.
 * Supports both single and multiple display order fetching.
 *
 * @example
 * ```typescript
 * // Fetch single display order
 * readonly displayOrdersResource = inject(DisplayOrdersResource);
 * this.displayOrdersResource.loadOrder(123);
 *
 * // Fetch multiple display orders
 * this.displayOrdersResource.loadOrders([123, 456, 789]);
 *
 * // Access data
 * const orders = this.displayOrdersResource.orders();
 * const isLoading = this.displayOrdersResource.loading();
 * ```
 */
@Injectable()
export class DisplayOrdersResource {
  #ordersService = inject(OrdersService);

  #orderIds = signal<number[] | undefined>(undefined);

  /**
   * Internal resource that manages data fetching and caching
   */
  #resource = resource({
    params: computed(() => ({
      orderIds: this.#orderIds(),
    })),
    loader: async ({ params, abortSignal }): Promise<DisplayOrderDTO[]> => {
      if (!params?.orderIds?.length) {
        return [];
      }

      return await this.#ordersService.getDisplayOrders(
        params.orderIds,
        abortSignal,
      );
    },
    defaultValue: [],
  });

  /**
   * Signal containing the array of fetched display orders.
   * Returns empty array when loading or on error.
   */
  readonly orders: Signal<readonly DisplayOrderDTO[]> =
    this.#resource.value.asReadonly();

  /**
   * Signal indicating whether data is currently being fetched
   */
  readonly loading: Signal<boolean> = this.#resource.isLoading;

  /**
   * Signal containing error message if fetch failed, otherwise null
   */
  readonly error = computed(() => this.#resource.error()?.message ?? null);

  /**
   * Load a single display order by its numeric ID
   */
  loadOrder(orderId: number): void {
    this.#orderIds.set([orderId]);
  }

  /**
   * Load multiple display orders by their numeric IDs
   */
  loadOrders(orderIds: number[] | undefined): void {
    this.#orderIds.set(orderIds);
  }

  /**
   * Manually refresh the current display orders data
   */
  refresh(): void {
    this.#resource.reload();
  }
}
