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

/**
 * Resource for fetching orders by their numeric IDs.
 *
 * Provides reactive access to order data with loading and error states.
 * Supports both single and multiple order fetching.
 *
 * @example
 * ```typescript
 * // Fetch single order
 * readonly ordersResource = inject(OrdersResource);
 * this.ordersResource.loadOrder(123);
 *
 * // Fetch multiple orders
 * this.ordersResource.loadOrders([123, 456, 789]);
 *
 * // Access data
 * const orders = this.ordersResource.orders();
 * const isLoading = this.ordersResource.loading();
 * ```
 */
@Injectable()
export class OrdersResource {
  #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<OrderDTO[]> => {
      if (!params?.orderIds?.length) {
        return [];
      }

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

  /**
   * Signal containing the array of fetched orders.
   * Returns empty array when loading or on error.
   */
  readonly orders: Signal<readonly OrderDTO[]> =
    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 order by its numeric ID
   */
  loadOrder(orderId: number): void {
    this.#orderIds.set([orderId]);
  }

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

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