import { transformMedia } from './transformMedia';
import { transformSourceEntryId } from './transformSourceEntryId';
import type { NacelleProduct, ProductVariant, Media } from '@nacelle/types';
import type { Product } from 'storefrontSdkV1';

export function transformProducts(
  products: Product[],
  locale: string
): NacelleProduct[] {
  return products.map((product: Product) => {
    const formatPrice = (price: number): string => {
      if (Number.isInteger(price)) return price.toFixed(1);
      return price.toString();
    };

    const hasVariant =
      Array.isArray(product.variants) && product.variants.length;

    const variantPrices =
      hasVariant &&
      product.variants
        ?.map((variant) => parseFloat(variant.price))
        // We provide a sort function here because by default,
        // "all non-undefined array elements are sorted by
        // converting them to strings and comparing strings
        // in UTF-16 code units order." For more details, see:
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description
        .sort((a, b) => a - b)
        .map((price) => formatPrice(price));

    const priceCurrency = hasVariant
      ? product.variants[0]?.priceCurrency
      : null;

    return {
      availableForSale: product.availableForSale as boolean,
      createdAt: product.createdAt as number,
      description: product.content?.description || null,
      featuredMedia: transformMedia(product.content?.featuredMedia),
      globalHandle: product.content?.handle
        ? `${product.content?.handle}::${locale}`
        : '',
      handle: product.content?.handle || '',
      id: product.nacelleEntryId,
      indexedAt: product.indexedAt as number,
      locale,
      media:
        product.content?.media?.map(
          (media) => transformMedia(media) as Media
        ) || null,
      metafields: product.metafields,
      pimSyncSource: '',
      pimSyncSourceDomain: '',
      pimSyncSourceProductId: transformSourceEntryId(product.sourceEntryId),
      priceRange: Array.isArray(variantPrices)
        ? {
            min: variantPrices[0],
            max: variantPrices[variantPrices.length - 1],
            currencyCode: priceCurrency
          }
        : null,
      productType: product.productType,
      tags: product.tags,
      title: product.content?.title || null,
      updatedAt: product.updatedAt,
      vendor: product.vendor,
      variants: product.variants?.map((variant): ProductVariant => {
        const transformedVariant: ProductVariant = {
          availableForSale: variant.availableForSale,
          compareAtPrice:
            variant.compareAtPrice &&
            formatPrice(Number(variant.compareAtPrice)),
          compareAtPriceCurrency:
            variant.compareAtPrice &&
            formatPrice(Number(variant.compareAtPrice)),
          featuredMedia: transformMedia(variant.content?.featuredMedia),
          id: transformSourceEntryId(variant.sourceEntryId),
          metafields: variant.metafields,
          price: formatPrice(Number(variant.price)),
          priceCurrency: variant.priceCurrency,
          priceRules:
            Array.isArray(variant.priceRules) && variant.priceRules.length
              ? variant.priceRules?.map((priceRule) => ({
                  ...priceRule,
                  comparedAtPrice: priceRule.comparedAtPrice
                    ? formatPrice(Number(priceRule.comparedAtPrice))
                    : null,
                  price: formatPrice(Number(priceRule.price)),
                  priceBreaks:
                    priceRule.priceBreaks &&
                    priceRule.priceBreaks.map((priceBreak) => ({
                      ...priceBreak,
                      price: formatPrice(Number(priceBreak.price))
                    }))
                }))
              : [],
          quantityAvailable: variant.quantityAvailable,
          selectedOptions:
            variant.content?.selectedOptions?.map(({ name, value }) => ({
              name,
              value
            })) || null,
          sku: variant.sku,
          swatchSrc: variant.content?.swatchSrc || null,
          title: variant.content?.title || null,
          weight: variant.weight,
          weightUnit: variant.weightUnit
        };

        return transformedVariant;
      })
    };
  });
}
