import { inject, Injectable } from '@angular/core';
import { ShoppingCartService, CheckoutService } from '../services';
import {
  CompleteOrderParams,
  RemoveShoppingCartItemParams,
  UpdateShoppingCartItemParams,
  CompleteCrmOrderParamsSchema,
  CompleteCrmOrderParams,
} from '../schemas';
import {
  CustomerAdapter,
  ShippingAddressAdapter,
  PayerAdapter,
} from '../adapters';

@Injectable({ providedIn: 'root' })
export class ShoppingCartFacade {
  #shoppingCartService = inject(ShoppingCartService);
  #checkoutService = inject(CheckoutService);

  createShoppingCart() {
    return this.#shoppingCartService.createShoppingCart();
  }

  async getShoppingCart(shoppingCartId: number, abortSignal?: AbortSignal) {
    const sc = await this.#shoppingCartService.getShoppingCart(
      shoppingCartId,
      abortSignal,
    );
    return sc;
  }

  async removeItem(params: RemoveShoppingCartItemParams) {
    const sc = await this.#shoppingCartService.removeItem(params);
    return sc;
  }

  async updateItem(params: UpdateShoppingCartItemParams) {
    const sc = await this.#shoppingCartService.updateItem(params);
    return sc;
  }

  /**
   * Complete checkout and create orders.
   *
   * @param params - Complete checkout parameters
   * @param abortSignal - Optional AbortSignal for cancellation
   * @returns Promise<number> - Checkout Id
   * @throws CheckoutCompletionError - If validation or order creation fails
   */
  async complete(
    params: CompleteOrderParams,
    abortSignal?: AbortSignal,
  ): Promise<number> {
    // Complete checkout preparation
    return await this.#checkoutService.complete(params, abortSignal);
  }

  /**
   * Complete order with CRM data.
   *
   * @remarks
   * Accepts raw CRM data (customer, shipping address, payer) and transforms it
   * to checkout format before completing the order. This method encapsulates
   * the business logic of converting CRM entities to checkout entities.
   *
   * **Transformation Steps:**
   * 1. Validates input parameters with Zod schema
   * 2. Transforms customer to buyer using CustomerAdapter.toBuyer()
   * 3. Transforms CRM shipping address (if provided) using ShippingAddressAdapter
   * 4. Transforms CRM payer (if provided) using PayerAdapter
   * 5. Extracts customer features using CustomerAdapter.extractCustomerFeatures()
   * 6. Delegates to complete() with transformed data
   *
   * @param params - CRM order completion parameters
   * @param abortSignal - Optional AbortSignal for cancellation
   * @returns Promise<number> - Checkout Id
   * @throws CheckoutCompletionError - If validation or order creation fails
   *
   * @example
   * ```typescript
   * const customer = await customerResource.value();
   * const orders = await facade.completeWithCrmData({
   *   shoppingCartId: 123,
   *   customer,
   *   crmShippingAddress: customer.shippingAddresses[0].data,
   *   crmPayer: customer.payers[0].payer.data,
   *   notificationChannels: customer.notificationChannels ?? 1,
   * });
   * ```
   */
  completeWithCrmData(
    params: CompleteCrmOrderParams,
    abortSignal?: AbortSignal,
  ): Promise<number> {
    // Validate input parameters
    const validatedParams = CompleteCrmOrderParamsSchema.parse(params);

    const {
      shoppingCartId,
      crmCustomer,
      crmShippingAddress,
      crmPayer,
      notificationChannels,
      specialComment,
    } = validatedParams;

    // Build checkout parameters
    const checkoutParams: CompleteOrderParams = {
      shoppingCartId,
      buyer: CustomerAdapter.toBuyer(crmCustomer),
      shippingAddress: ShippingAddressAdapter.fromCrmShippingAddress(
        crmShippingAddress as any,
      ),
      customerFeatures: CustomerAdapter.extractCustomerFeatures(
        crmCustomer as any,
      ),
      payer: PayerAdapter.toCheckoutFormat(crmPayer as any),
      notificationChannels:
        notificationChannels ?? crmCustomer.notificationChannels ?? 1,
      specialComment,
    };

    // Delegate to existing complete method
    return this.complete(checkoutParams, abortSignal);
  }
}
