import { Injectable, inject, untracked } from '@angular/core';
import { UiModalRef, UiModalService } from '@ui/modal';
import { PurchaseOptionsModalComponent } from './purchase-options-modal.component';
import {
  PurchaseOptionsModalData,
  PurchaseOptionsModalContext,
} from './purchase-options-modal.data';
import {
  CustomerFacade,
  Customer,
  CrmTabMetadataService,
} from '@isa/crm/data-access';
import { TabService } from '@isa/core/tabs';
import { BranchDTO } from '@generated/swagger/checkout-api';
import { CheckoutMetadataService } from '@isa/checkout/data-access';

/**
 * Service for opening and managing the Purchase Options Modal.
 *
 * The Purchase Options Modal allows users to select how they want to receive items
 * (delivery, pickup, in-store, download) and manages availability checking, pricing,
 * and shopping cart operations.
 *
 * @example
 * ```typescript
 * // Basic usage
 * const modalRef = await this.purchaseOptionsModalService.open({
 *   tabId: 123,
 *   shoppingCartId: 456,
 *   type: 'add',
 *   items: [item1, item2],
 * });
 *
 * // Await modal close
 * const result = await firstValueFrom(modalRef.afterClosed$);
 * ```
 */
@Injectable({ providedIn: 'root' })
export class PurchaseOptionsModalService {
  #uiModal = inject(UiModalService);
  #tabService = inject(TabService);
  #crmTabMetadataService = inject(CrmTabMetadataService);
  #checkoutMetadataService = inject(CheckoutMetadataService);
  #customerFacade = inject(CustomerFacade);

  /**
   * Opens the Purchase Options Modal.
   *
   * @param data - Configuration data for the modal
   * @returns Promise resolving to a modal reference
   *
   * @example
   * ```typescript
   * // Add new items with disabled B2B delivery
   * const modalRef = await this.purchaseOptionsModalService.open({
   *   tabId: processId,
   *   shoppingCartId: cartId,
   *   type: 'add',
   *   items: [item1, item2],
   *   disabledPurchaseOptions: ['b2b-delivery'],
   * });
   *
   * // Wait for modal to close
   * const action = await firstValueFrom(modalRef.afterClosed$);
   * if (action === 'continue') {
   *   // Proceed to next step
   * }
   * ```
   */
  async open(
    data: PurchaseOptionsModalData,
  ): Promise<UiModalRef<string, PurchaseOptionsModalData>> {
    const context: PurchaseOptionsModalContext = {
      useRedemptionPoints: !!data.useRedemptionPoints,
      ...data,
    };

    context.selectedCustomer = await this.#getSelectedCustomer(data);
    context.selectedBranch = this.#getSelectedBranch(
      data.tabId,
      data.useRedemptionPoints,
    );
    return this.#uiModal.open<string, PurchaseOptionsModalContext>({
      content: PurchaseOptionsModalComponent,
      data: context,
    });
  }

  #getSelectedCustomer({
    tabId,
  }: {
    tabId: number;
  }): Promise<Customer | undefined> {
    const customerId = this.#crmTabMetadataService.selectedCustomerId(tabId);

    if (!customerId) {
      return Promise.resolve(undefined);
    }

    return this.#customerFacade.fetchCustomer({ customerId });
  }

  #getSelectedBranch(
    tabId: number,
    useRedemptionPoints: boolean,
  ): BranchDTO | undefined {
    const tab = untracked(() =>
      this.#tabService.entities().find((t) => t.id === tabId),
    );

    if (!tab) {
      return undefined;
    }

    if (useRedemptionPoints) {
      return this.#checkoutMetadataService.getSelectedBranch(tabId);
    }

    const legacyProcessData = tab?.metadata?.process_data;

    if (
      typeof legacyProcessData === 'object' &&
      'selectedBranch' in legacyProcessData
    ) {
      return legacyProcessData.selectedBranch as BranchDTO;
    }

    return undefined;
  }
}
