import {
  BranchDTO,
  DisplayAddresseeDTO,
  DisplayOrderDTO,
  DisplayOrderItemDTO,
} from '@generated/swagger/oms-api';
import { getOrderTypeFeature } from './get-order-type-feature.helper';
import { getOrderTypeIcon } from './get-order-type-icon.helper';
import { OrderTypeFeature } from '@isa/common/data-access';

/**
 * Order types that are associated with shipping addresses
 */
export const SHIPPING_ORDER_TYPE_FEATURES: readonly OrderTypeFeature[] = [
  OrderTypeFeature.Delivery,
  OrderTypeFeature.B2BShipping,
  OrderTypeFeature.DigitalShipping,
];

/**
 * Order types that are associated with physical branch locations
 */
export const BRANCH_ORDER_TYPE_FEATURES: readonly OrderTypeFeature[] = [
  OrderTypeFeature.Pickup,
  OrderTypeFeature.InStore,
];

/**
 * Represents a group of order items with the same delivery type and destination
 */
export type OrderItemGroup = {
  /** The order type feature (e.g., 'Versand', 'Abholung') */
  orderType: OrderTypeFeature;
  /** The icon name for this order type */
  orderTypeIcon: string;
  /** The target branch for pickup/in-store orders */
  targetBranch?: BranchDTO;
  /** The shipping address for delivery orders */
  shippingAddress?: DisplayAddresseeDTO;
  /** Order features from the DisplayOrderDTO */
  features: Record<string, string>;
  /** Array of items in this group */
  items: DisplayOrderItemDTO[];
};

/**
 * Groups display order items by their delivery type and destination.
 *
 * Items are grouped by:
 * - Order type (Versand, Abholung, Rücklage, etc.)
 * - Destination (shipping address for delivery orders, branch for pickup/in-store orders)
 *
 * Uses Map-based lookups for O(1) performance instead of array.find().
 *
 * @param orders - Array of DisplayOrderDTO objects to process
 * @returns Array of OrderItemGroup objects, each containing items with the same delivery type and destination
 *
 * @example
 * ```typescript
 * const orders = [
 *   { id: '1', items: [item1, item2], features: { orderType: 'Versand' }, shippingAddress: addr1 },
 *   { id: '2', items: [item3], features: { orderType: 'Abholung' }, targetBranch: branch1 }
 * ];
 *
 * const grouped = groupItemsByDeliveryDestination(orders);
 * // Returns: [
 * //   { orderType: 'Versand', items: [item1, item2], shippingAddress: addr1, ... },
 * //   { orderType: 'Abholung', items: [item3], targetBranch: branch1, ... }
 * // ]
 * ```
 */
export function groupItemsByDeliveryDestination(
  orders: readonly DisplayOrderDTO[] | undefined | null,
): OrderItemGroup[] {
  const groupMap = new Map<string, OrderItemGroup>();

  if (!orders?.length) {
    return [];
  }

  for (const order of orders) {
    const targetBranch = order.targetBranch;
    const shippingAddress = order.shippingAddress;
    const features = order.features ?? {};

    if (!order.items?.length) {
      continue;
    }

    for (const item of order.items) {
      const orderType = getOrderTypeFeature(item.features);

      if (!orderType) {
        continue;
      }

      // Generate unique key for this group
      let groupKey = orderType;

      if (
        SHIPPING_ORDER_TYPE_FEATURES.includes(orderType) &&
        shippingAddress
      ) {
        groupKey += `-shippingAddress-${JSON.stringify(shippingAddress)}`;
      }

      if (BRANCH_ORDER_TYPE_FEATURES.includes(orderType) && targetBranch) {
        groupKey += `-targetBranch-${targetBranch.id}`;
      }

      // Get or create group
      let group = groupMap.get(groupKey);

      if (!group) {
        group = {
          orderType: orderType,
          orderTypeIcon: getOrderTypeIcon(orderType),
          targetBranch: targetBranch,
          shippingAddress: shippingAddress,
          features: features,
          items: [],
        };

        groupMap.set(groupKey, group);
      }

      group.items.push(item);
    }
  }

  return Array.from(groupMap.values());
}
