import {
  computed,
  effect,
  inject,
  Injectable,
  resource,
  signal,
  untracked,
} from '@angular/core';
import { CrmSearchService, CrmTabMetadataService } from '../services';
import { injectTabId } from '@isa/core/tabs';
import { BonusCardInfo } from '../models';
import { getPrimaryBonusCard } from '../helpers';

/**
 * Resource for the primary customer card of a customer.
 *
 * This resource automatically loads the primary bonus card of a customer
 * as soon as a `customerId` is set in the tab metadata. An internal effect
 * monitors changes to the `selectedCustomerId` in the active tab and
 * triggers loading of the customer card automatically.
 *
 * @example
 * ```typescript
 * const resource = inject(PrimaryCustomerCardResource);
 *
 * // Primary customer card (automatically loaded via effect)
 * const card = resource.primaryCustomerCard();
 *
 * // Loading status
 * const isLoading = resource.loading();
 * ```
 */
@Injectable({ providedIn: 'root' })
export class PrimaryCustomerCardResource {
  #customerMetadata = inject(CrmTabMetadataService);
  #customerService = inject(CrmSearchService);
  #tabId = injectTabId();

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

  #primaryCustomerCardResource = resource({
    params: computed(() => ({ customerId: this.#customerId() })),
    loader: async ({
      params,
      abortSignal,
    }): Promise<BonusCardInfo | undefined> => {
      const tabId = this.#tabId();
      if (!tabId || !params.customerId) {
        return undefined;
      }

      const res = await this.#customerService.fetchCustomerCards(
        { customerId: params.customerId },
        abortSignal,
      );

      if (res?.result?.length > 0) {
        return getPrimaryBonusCard(res.result);
      }

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

  /**
   * Signal containing the primary customer card of the selected customer.
   * Automatically updated when the `selectedCustomerId` changes in the tab metadata.
   */
  readonly primaryCustomerCard =
    this.#primaryCustomerCardResource.value.asReadonly();

  /**
   * Signal indicating whether the customer card is currently being loaded.
   */
  readonly loading = this.#primaryCustomerCardResource.isLoading;

  /**
   * Signal containing an error message if an error occurred during loading.
   * Returns `null` if no error is present.
   */
  readonly error = computed(
    () => this.#primaryCustomerCardResource.error()?.message ?? null,
  );

  /**
   * Loads the primary customer card for the specified customer ID.
   *
   * @param customerId - The ID of the customer whose primary card should be loaded
   */
  loadPrimaryCustomerCard(customerId: number | undefined) {
    this.#customerId.set(customerId);
  }

  constructor() {
    /**
     * Effect: Monitors changes to the `selectedCustomerId` in the tab metadata
     * and automatically loads the primary customer card whenever a new customer ID
     * is set. This ensures that the customer card is always in sync with the
     * customer selection in the active tab.
     *
     * Uses `untracked` to prevent creating additional signal dependencies when
     * checking if the customer ID has actually changed, avoiding unnecessary reloads.
     */
    effect(() => {
      const tabId = this.#tabId();
      let customerId = undefined;

      if (tabId) {
        customerId = this.#customerMetadata.selectedCustomerId(tabId);
      }

      untracked(() => {
        if (this.#customerId() !== customerId) {
          this.loadPrimaryCustomerCard(customerId);
        }
      });
    });
  }
}
