import {
  getOrderTypeFeature,
  OrderTypeFeature,
  ShoppingCartItem,
} from '@isa/checkout/data-access';
import {
  GetAvailabilityInputParams,
  GetSingleItemAvailabilityInputParams,
} from '../schemas';

// TODO: [Adapter Refactoring - Medium Priority] Replace switch with builder pattern
// Current: 67-line switch statement, 90% duplication (Complexity: 6/10)
// Target: Fluent builder API with type safety
//
// Proposed approach:
//   1. Create AvailabilityParamsBuilder class:
//      - withItem(catalogProductNumber, ean, quantity, price)  // Fix: type-safe price (not any)
//      - withOrderType(orderType)
//      - withShopId(shopId)
//      - build(): GetAvailabilityInputParams | undefined
//
//   2. Encapsulate business rules in builder:
//      - requiresShopId check (InStore, Pickup)
//      - Download special case (no quantity)
//      - Validation logic
//
//   3. Simplify adapter to:
//      return new AvailabilityParamsBuilder()
//        .withItem(catalogProductNumber, ean, quantity, price)
//        .withOrderType(orderType)
//        .withShopId(targetBranch)
//        .build();
//
// Benefits:
//   - Eliminates switch statement duplication
//   - Fixes 'any' type on line 158 (type-safe price parameter)
//   - Fluent API makes intent clear
//   - Easy to add new order types
//   - Encapsulates validation rules
//
// Effort: ~3 hours | Impact: Medium | Risk: Low
// See: complexity-analysis.md (Code Review Section 3, Option 1)
export class GetAvailabilityParamsAdapter {
  static fromShoppingCartItem(
    item: ShoppingCartItem,
    orderType = getOrderTypeFeature(item.features),
  ): GetAvailabilityInputParams | undefined {
    const itemData = this.extractItemData(item);
    if (!itemData) {
      return undefined;
    }

    const { catalogProductNumber, quantity, targetBranch, ean } = itemData;
    const price = this.preparePriceData(item);
    const baseItems = [
      this.createBaseItem(catalogProductNumber, ean, quantity, price),
    ];

    switch (orderType) {
      case OrderTypeFeature.InStore:
        if (!targetBranch) {
          return undefined;
        }
        return {
          orderType: OrderTypeFeature.InStore,
          branchId: targetBranch,
          itemsIds: baseItems.map((item) => item.itemId), // Note: itemsIds is array of numbers
        };

      case OrderTypeFeature.Pickup:
        if (!targetBranch) {
          return undefined;
        }
        return {
          orderType: OrderTypeFeature.Pickup,
          branchId: targetBranch,
          items: baseItems,
        };

      case OrderTypeFeature.Delivery:
        return {
          orderType: OrderTypeFeature.Delivery,
          items: baseItems,
        };

      case OrderTypeFeature.DigitalShipping:
        return {
          orderType: OrderTypeFeature.DigitalShipping,
          items: baseItems,
        };

      case OrderTypeFeature.B2BShipping:
        return {
          orderType: OrderTypeFeature.B2BShipping,
          items: baseItems,
        };

      case OrderTypeFeature.Download:
        return {
          orderType: OrderTypeFeature.Download,
          items: baseItems.map((item) => ({
            itemId: item.itemId,
            ean: item.ean,
            price: item.price,
            // Download doesn't need quantity
          })),
        };

      default:
        return undefined;
    }
  }

  /**
   * Converts a ShoppingCartItem to single-item availability parameters.
   * Returns params for the convenience method that checks only one item.
   *
   * @param item Shopping cart item to convert
   * @returns Single-item availability params or undefined if data is invalid
   */
  static fromShoppingCartItemToSingle(
    item: ShoppingCartItem,
    orderType = getOrderTypeFeature(item.features),
  ): GetSingleItemAvailabilityInputParams | undefined {
    // Extract common data
    const itemData = this.extractItemData(item);
    if (!itemData) {
      return undefined;
    }

    const { catalogProductNumber, quantity, targetBranch, ean } = itemData;
    const price = this.preparePriceData(item);

    // Create the item object
    const itemObj = this.createBaseItem(
      catalogProductNumber,
      ean,
      quantity,
      price,
    );

    // Build single-item params based on order type
    switch (orderType) {
      case OrderTypeFeature.InStore:
        if (!targetBranch) {
          return undefined;
        }
        return {
          orderType,
          branchId: targetBranch,
          itemId: itemObj.itemId,
        };
      case OrderTypeFeature.Pickup:
        if (!targetBranch) {
          return undefined;
        }
        return {
          orderType,
          branchId: targetBranch,
          item: itemObj,
        };

      case OrderTypeFeature.Delivery:
      case OrderTypeFeature.DigitalShipping:
      case OrderTypeFeature.B2BShipping:
      case OrderTypeFeature.Download:
        return {
          orderType,
          item: itemObj,
        };

      default:
        return undefined;
    }
  }

  /**
   * Extracts and validates required data from a ShoppingCartItem.
   * @returns Extracted data or undefined if validation fails
   */
  private static extractItemData(item: ShoppingCartItem) {
    const catalogProductNumber = item.product.catalogProductNumber;
    const quantity = item.quantity;
    const targetBranch = item.destination?.data?.targetBranch?.id;
    const ean = item.product.ean;

    if (!catalogProductNumber || !ean || !quantity) {
      return undefined;
    }

    return { catalogProductNumber, quantity, targetBranch, ean };
  }

  /**
   * Prepares price data from a ShoppingCartItem to match PriceSchema structure.
   * @returns Formatted price object or undefined
   */
  private static preparePriceData(item: ShoppingCartItem) {
    return item.availability?.price
      ? {
          value: item.availability.price.value ?? {
            value: undefined,
            currency: 'EUR',
            currencySymbol: '€',
          },
          vat: item.availability.price.vat ?? {
            value: undefined,
            label: undefined,
            inPercent: undefined,
            vatType: undefined,
          },
        }
      : undefined;
  }

  /**
   * Creates a base item object for availability requests.
   *
   * TODO: [Next Sprint] Replace `any` type with proper typing
   * - Change parameter type from `price: any` to `price: Price | undefined`
   * - Import: import { Price } from '@isa/common/data-access';
   * - Ensures compile-time type safety for price transformations
   * - Prevents potential runtime errors from invalid price structures
   */
  private static createBaseItem(
    catalogProductNumber: string | number,
    ean: string,
    quantity: number,
    price: any, // TODO: Replace with `Price | undefined`
  ) {
    return {
      itemId: Number(catalogProductNumber),
      ean,
      quantity,
      price,
    };
  }
}
