import { ChangeDetectorRef, Directive, HostBinding, HostListener } from '@angular/core';
import { asapScheduler } from 'rxjs';
import { PurchaseOption, PurchaseOptionsStore } from '../store';

/**
 * Base directive for purchase option tile components.
 *
 * Provides common functionality for all purchase option tiles:
 * - Visual selected state binding
 * - Visual disabled state binding
 * - Click handling with disabled check
 * - Auto-selection of available items
 *
 * @example
 * ```typescript
 * export class DeliveryPurchaseOptionTileComponent extends BasePurchaseOptionDirective {
 *   constructor(
 *     protected store: PurchaseOptionsStore,
 *     protected cdr: ChangeDetectorRef,
 *   ) {
 *     super('delivery');
 *   }
 * }
 * ```
 */
@Directive({
  standalone: false,
})
export abstract class BasePurchaseOptionDirective {
  protected abstract store: PurchaseOptionsStore;
  protected abstract cdr: ChangeDetectorRef;

  /**
   * Binds the 'selected' CSS class to the host element.
   * Applied when this purchase option is the currently selected one.
   */
  @HostBinding('class.selected')
  get selected() {
    return this.store.purchaseOption === this.purchaseOption;
  }

  /**
   * Binds the 'disabled' CSS class to the host element.
   * Applied when this purchase option is in the disabledPurchaseOptions array.
   * Disabled options:
   * - Have no availability API calls made
   * - Are shown with reduced opacity and not-allowed cursor
   * - Prevent click interactions
   */
  @HostBinding('class.disabled')
  get disabled() {
    return this.store.disabledPurchaseOptions.includes(this.purchaseOption);
  }

  constructor(protected purchaseOption: PurchaseOption) {}

  /**
   * Handles click events on the purchase option tile.
   *
   * Behavior:
   * 1. If disabled, prevents any action
   * 2. Sets this option as the selected purchase option
   * 3. Resets selected items
   * 4. Auto-selects all items that have availability and can be added for this option
   *
   * @listens click
   */
  @HostListener('click')
  setPurchaseOptions() {
    if (this.disabled) {
      return;
    }
    this.store.setPurchaseOption(this.purchaseOption);
    this.store.resetSelectedItems();
    asapScheduler.schedule(() => {
      const items = this.store.getItemsThatHaveAnAvailabilityAndCanAddForPurchaseOption(this.purchaseOption);
      items.forEach((item) => this.store.setSelectedItem(item.id, true));
    });
    this.cdr.markForCheck();
  }
}
