import { Availability, AvailabilityType } from '../models';
import { StockInfo } from '@isa/remission/data-access';
import { Supplier } from '@isa/checkout/data-access';
import { ensureCurrencyDefaults } from '@isa/common/data-access';
import { selectPreferredAvailability, isDownloadAvailable } from './availability.helpers';
import { logger } from '@isa/core/logging';

// Lazy logger initialization to avoid injection context issues at module load time
const getTransformerLogger = () => logger(() => ({ module: 'AvailabilityTransformers' }));

/**
 * Transforms API response array into dictionary grouped by itemId.
 *
 * This is the standard transformation used by most order types (Pickup, DIG-Versand, B2B-Versand).
 * It filters availabilities by itemId, selects the preferred one, and builds a result dictionary.
 *
 * @param availabilities - Raw availabilities from API
 * @param requestedItems - Items that were requested (must have itemId)
 * @returns Dictionary of availabilities by itemId
 *
 * @example
 * ```typescript
 * const result = transformAvailabilitiesToDictionary(
 *   apiResponse,
 *   [{ itemId: 123 }, { itemId: 456 }]
 * );
 * // Returns: { '123': Availability, '456': Availability }
 * ```
 */
export function transformAvailabilitiesToDictionary(
  availabilities: Availability[],
  requestedItems: Array<{ itemId?: number }>,
): { [itemId: string]: Availability } {
  const result: { [itemId: string]: Availability } = {};

  for (const item of requestedItems) {
    if (!item.itemId) continue;

    const itemAvailabilities = availabilities.filter(
      (av) => String(av.itemId) === String(item.itemId),
    );

    const preferred = selectPreferredAvailability(itemAvailabilities);

    if (preferred) {
      result[String(item.itemId)] = preferred;
    }
  }

  return result;
}

/**
 * Transforms API response for standard delivery (Versand) - excludes supplier/logistician.
 *
 * This transformation differs from other order types by EXCLUDING supplier and logistician fields
 * to match the old service behavior. Including these fields causes the backend to
 * automatically change the orderType from "Versand" to "DIG-Versand".
 *
 * Excluded fields:
 * - supplierId, supplier
 * - logisticianId, logistician
 *
 * @param availabilities - Raw availabilities from API
 * @param requestedItems - Items that were requested
 * @returns Dictionary of availabilities by itemId (without supplier/logistician)
 *
 * @example
 * ```typescript
 * const result = transformAvailabilitiesToDictionaryWithFieldFilter(
 *   apiResponse,
 *   [{ itemId: 123 }]
 * );
 * // Returns: { '123': Availability } (without supplierId/logisticianId)
 * ```
 */
export function transformAvailabilitiesToDictionaryWithFieldFilter(
  availabilities: Availability[],
  requestedItems: Array<{ itemId?: number }>,
): { [itemId: string]: Availability } {
  const result: { [itemId: string]: Availability } = {};

  for (const item of requestedItems) {
    if (!item.itemId) continue;

    const itemAvailabilities = availabilities.filter(
      (av) => String(av.itemId) === String(item.itemId),
    );

    const preferred = selectPreferredAvailability(itemAvailabilities);

    if (preferred) {
      // Create a copy without supplier/logistician fields
      const {
        supplierId,
        supplier,
        logisticianId,
        logistician,
        ...deliveryAvailability
      } = preferred;

      result[String(item.itemId)] = deliveryAvailability as Availability;
    }
  }

  return result;
}

/**
 * Transforms download availabilities with validation.
 *
 * Download items require special validation:
 * - Supplier ID 16 with 0 stock = unavailable
 * - Must have valid availability type code
 *
 * Items that fail validation are excluded from the result (not marked as unavailable).
 *
 * @param availabilities - Raw availabilities from API
 * @param requestedItems - Items that were requested
 * @returns Dictionary of validated availabilities by itemId
 *
 * @example
 * ```typescript
 * const result = transformDownloadAvailabilitiesToDictionary(
 *   apiResponse,
 *   [{ itemId: 123 }, { itemId: 456 }]
 * );
 * // Returns: { '123': Availability } (only valid downloads)
 * ```
 */
export function transformDownloadAvailabilitiesToDictionary(
  availabilities: Availability[],
  requestedItems: Array<{ itemId?: number }>,
): { [itemId: string]: Availability } {
  const result: { [itemId: string]: Availability } = {};

  for (const item of requestedItems) {
    if (!item.itemId) continue;

    const itemAvailabilities = availabilities.filter(
      (av) => String(av.itemId) === String(item.itemId),
    );

    const preferred = selectPreferredAvailability(itemAvailabilities);

    // Validate download availability
    if (preferred && isDownloadAvailable(preferred)) {
      result[String(item.itemId)] = preferred;
    }
    // Logging disabled in helper functions due to injection context limitations in tests
    // TODO: Pass logger instance from service if logging is required
    // else {
    //   getTransformerLogger().warn('Download unavailable for item', () => ({
    //     itemId: item.itemId,
    //     supplierId: preferred?.supplierId,
    //     status: preferred?.status,
    //   }));
    // }
  }

  return result;
}

/**
 * Transforms stock information to availability format (InStore/Rücklage).
 *
 * This transformation is specific to in-store (Rücklage) availability:
 * - Maps stock quantities to availability status
 * - Includes supplier information
 * - Uses fixed SSC values for in-store items
 *
 * @param stocks - Stock information from remission service
 * @param requestedItemIds - Item IDs that were requested
 * @param supplier - Supplier to include in availability (typically supplier 'F')
 * @returns Dictionary of availabilities by itemId
 *
 * @example
 * ```typescript
 * const result = transformStockToAvailability(
 *   stockInfos,
 *   [123, 456],
 *   takeAwaySupplier
 * );
 * // Returns: { '123': Availability, '456': Availability }
 * ```
 */
export function transformStockToAvailability(
  stocks: StockInfo[],
  requestedItemIds: Array<number>,
  supplier: Supplier,
): { [itemId: string]: Availability } {
  const result: { [itemId: string]: Availability } = {};

  for (const itemId of requestedItemIds) {
    const stockInfo = stocks.find((s) => s.itemId === itemId);

    if (!stockInfo) {
      continue;
    }

    const inStock = stockInfo.inStock ?? 0;
    const isAvailable = inStock > 0;

    result[String(itemId)] = {
      status: isAvailable
        ? AvailabilityType.Available
        : AvailabilityType.NotAvailable,
      itemId: stockInfo.itemId,
      qty: inStock,
      ssc: isAvailable ? '999' : '',
      sscText: isAvailable ? 'Filialentnahme' : '',
      supplierId: supplier?.id,
      price: ensureCurrencyDefaults(stockInfo.retailPrice),
    } satisfies Availability;
  }

  return result;
}
