import { Injectable, inject, resource, signal, computed } from '@angular/core';
import { logger } from '@isa/core/logging';
import { CrmSearchService } from '@isa/crm/data-access';
import { LoyaltyBookingInfoDTO } from '@generated/swagger/crm-api';

/**
 * Resource for loading customer loyalty card transactions.
 *
 * Provides reactive loading of the last 5 transactions for a given card code.
 * Card code can be changed dynamically via `params()` method.
 *
 * **Note:** This resource should be provided at the component level,
 * not in root. Provide it in the `providers` array of the component
 * that needs scoped access to transactions.
 *
 * @example
 * ```typescript
 * export class MyFeatureComponent {
 *   #transactionsResource = inject(CustomerCardTransactionsResource);
 *
 *   transactions = this.#transactionsResource.resource.value;
 *   isLoading = this.#transactionsResource.resource.isLoading;
 *
 *   loadTransactions(cardCode: string) {
 *     this.#transactionsResource.params({ cardCode });
 *   }
 * }
 * ```
 */
@Injectable()
export class CustomerCardTransactionsResource {
  readonly #crmSearchService = inject(CrmSearchService);
  readonly #logger = logger(() => ({
    context: 'CustomerCardTransactionsResource',
  }));

  readonly #customerId = signal<number | undefined>(undefined);

  /**
   * Resource that loads transactions based on current parameters.
   *
   * Exposes:
   * - `value()` - Array of transactions or undefined
   * - `isLoading()` - Loading state
   * - `error()` - Error state
   * - `status()` - Current status ('idle' | 'loading' | 'resolved' | 'error')
   */
  readonly resource = resource({
    params: computed(() => ({ customerId: this.#customerId() })),
    loader: async ({
      params,
      abortSignal,
    }): Promise<LoyaltyBookingInfoDTO[] | undefined> => {
      const { customerId } = params;

      if (!customerId) {
        this.#logger.debug('No customerId provided, skipping load');
        return undefined;
      }

      this.#logger.debug('Loading loyalty card transactions', () => ({
        customerId,
      }));

      const transactions = await this.#crmSearchService.fetchLoyaltyBookings(
        customerId,
        abortSignal,
      );

      this.#logger.debug('Transactions loaded', () => ({
        customerId,
        count: transactions.length,
      }));

      return transactions;
    },
    defaultValue: undefined,
  });

  /**
   * Update resource parameters to trigger a reload.
   *
   * @param params - Parameters for loading transactions
   * @param params.customerId - Card code to load transactions for (undefined clears data)
   */
  params(params: { customerId?: number }): void {
    this.#logger.debug('Updating params', () => params);
    this.#customerId.set(params.customerId);
  }
}
