import { Product } from '@commerce/types'

import {
  Product as SaleorProduct,
  Checkout,
  CheckoutLine,
  Money,
  ProductVariant,
} from '../schema'

import type { Cart, LineItem } from '../types'

// TODO: Check nextjs-commerce bug if no images are added for a product
const placeholderImg = '/product-img-placeholder.svg'

const money = ({ amount, currency }: Money) => {
  return {
    value: +amount,
    currencyCode: currency || 'USD',
  }
}

const normalizeProductOptions = (options: ProductVariant[]) => {
  const optionNames = options
    .map((option) => {
      // can a variant have multiple attributes?
      return option.attributes[0].attribute.name
    })
    .filter((x, i, a) => a.indexOf(x) == i)

  return optionNames.map((displayName) => {
    const matchedOptions = options.filter(
      ({ attributes }) => attributes[0].attribute.name === displayName // can a variant have multiple attributes?
    )

    return {
      __typename: 'MultipleChoiceOption',
      // next-commerce can only display labels for options with displayName 'size', or colors
      displayName: displayName?.toLowerCase().includes('size')
        ? 'size'
        : displayName,
      values: matchedOptions.map(({ name }) => ({
        label: name,
      })),
    }
  })
}

const normalizeProductVariants = (variants: ProductVariant[]) =>
  variants?.map((variant) => {
    const { id, sku, name, pricing } = variant
    const price = pricing?.price?.net && money(pricing.price.net)?.value

    return {
      id,
      name,
      sku: sku ?? id,
      price,
      listPrice: price,
      requiresShipping: true,
      options: normalizeProductOptions([variant]),
    }
  })

export function normalizeProduct(productNode: SaleorProduct): Product {
  const {
    id,
    name,
    media,
    variants,
    description,
    slug,
    pricing,
    ...rest
  } = productNode

  const product = {
    id,
    name,
    vendor: '',
    description: description
      ? JSON.parse(description)?.blocks[0]?.data.text
      : '',
    path: `/${slug}`,
    slug: slug?.replace(/^\/+|\/+$/g, ''),
    price:
      (pricing?.priceRange?.start?.net &&
        money(pricing.priceRange.start.net)) ||
      0,
    // TODO: Check nextjs-commerce bug if no images are added for a product
    images: media?.length ? media : [{ url: placeholderImg }],
    variants:
      variants && variants.length > 0 ? normalizeProductVariants(variants) : [],
    options:
      variants && variants.length > 0 ? normalizeProductOptions(variants) : [],
    ...rest,
  }

  return product
}

export function normalizeCart(checkout: Checkout): Cart {
  const lines = checkout.lines as CheckoutLine[]; 
  const lineItems: LineItem[] = lines.length > 0 ? lines?.map<LineItem>(normalizeLineItem) : [];

  return {
    id: checkout.id,
    customerId: '',
    email: '',
    createdAt: checkout.created,
    currency: {
      code: checkout.totalPrice?.currency!
    },
    taxesIncluded: false,
    lineItems, 
    lineItemsSubtotalPrice: checkout.subtotalPrice?.gross?.amount!, 
    subtotalPrice: checkout.subtotalPrice?.gross?.amount!, 
    totalPrice: checkout.totalPrice?.gross.amount!,
    discounts: [],
  }
}

function normalizeLineItem({ id, variant, quantity }: CheckoutLine): LineItem {
  return {
    id,
    variantId: String(variant?.id),
    productId: String(variant?.id),
    name: `${variant.name}`,
    quantity,
    variant: {
      id: String(variant?.id),
      sku: variant?.sku ?? '',
      name: variant?.name!,
      image: {
        url: variant?.media![0].url ?? '/product-img-placeholder.svg',
      },
      requiresShipping: false,
      price: variant?.pricing?.price?.gross.amount!,
      listPrice: 0 
    },
    path: String(variant?.product?.slug),
    discounts: [],
    options: [ ],
  }
}