import { computed } from '@angular/core';
import { signalStore, withState, withComputed, withMethods } from '@ngrx/signals';
import { patchState } from '@ngrx/signals';

/**
 * Validated Bon data structure
 *
 * Maps to LoyaltyBonResponse from @generated/swagger/crm-api
 */
export interface ValidatedBon {
  bonNumber: string;
  date: string;
  total: number;
}

/**
 * State for Bon redemption feature
 */
interface BonRedemptionState {
  /**
   * Current Bon number input by user
   */
  bonNumber: string;

  /**
   * Whether Bon validation is in progress
   */
  isValidating: boolean;

  /**
   * Whether Bon redemption is in progress
   */
  isRedeeming: boolean;

  /**
   * Tracks if validation was attempted (button clicked)
   */
  validationAttempted: boolean;

  /**
   * Validated Bon data after successful validation
   */
  validatedBon: ValidatedBon | undefined;

  /**
   * Error message from validation or redemption
   */
  errorMessage: string | undefined;
}

const initialState: BonRedemptionState = {
  bonNumber: '',
  isValidating: false,
  isRedeeming: false,
  validationAttempted: false,
  validatedBon: undefined,
  errorMessage: undefined,
};

/**
 * SignalStore for managing Bon redemption state.
 *
 * Component-scoped store (provided in component providers).
 *
 * @example
 * ```typescript
 * @Component({
 *   providers: [BonRedemptionStore]
 * })
 * export class CrmFeatureCustomerBonRedemptionComponent {
 *   store = inject(BonRedemptionStore);
 * }
 * ```
 */
export const BonRedemptionStore = signalStore(
  withState(initialState),

  withComputed((store) => ({
    /**
     * Whether the search button should be disabled
     */
    disableSearch: computed(
      () =>
        store.isValidating() ||
        store.isRedeeming() ||
        !store.bonNumber().trim(),
    ),

    /**
     * Whether the redemption button should be disabled
     */
    disableRedemption: computed(() => {
      const bon = store.validatedBon();
      return store.isRedeeming() || store.isValidating() || !bon;
    }),

    /**
     * Whether a valid Bon is currently loaded
     */
    hasValidBon: computed(() => {
      const bon = store.validatedBon();
      return !!bon;
    }),

    /**
     * Whether there is an error message
     */
    hasError: computed(() => {
      const error = store.errorMessage();
      return !!error;
    }),
  })),

  withMethods((store) => ({
    /**
     * Update the Bon number input
     */
    setBonNumber(bonNumber: string): void {
      patchState(store, {
        bonNumber,
        errorMessage: undefined,
        validatedBon: undefined,
        validationAttempted: false,
      });
    },

    /**
     * Set validation loading state
     */
    setValidating(isValidating: boolean): void {
      patchState(store, { isValidating });
    },

    /**
     * Set redemption loading state
     */
    setRedeeming(isRedeeming: boolean): void {
      patchState(store, { isRedeeming });
    },

    /**
     * Mark that validation was attempted
     */
    setValidationAttempted(validationAttempted: boolean): void {
      patchState(store, { validationAttempted });
    },

    /**
     * Set validated Bon data
     */
    setValidatedBon(validatedBon: ValidatedBon | undefined): void {
      patchState(store, { validatedBon, errorMessage: undefined });
    },

    /**
     * Set error message
     */
    setError(errorMessage: string | undefined): void {
      patchState(store, { errorMessage, validatedBon: undefined });
    },

    /**
     * Reset store to initial state
     */
    reset(): void {
      patchState(store, initialState);
    },
  })),
);
