import { Customer } from '../types/customer'
import { Product, ProductOption } from '../types/product'
import { MoneyV2 } from '../schema'

import type {
  Cart,
  CartLineItem,
  SwellCustomer,
  SwellProduct,
  SwellImage,
  SwellVariant,
  ProductOptionValue,
  SwellProductOptionValue,
  SwellCart,
  LineItem,
} from '../types'

const money = ({ amount, currencyCode }: MoneyV2) => {
  return {
    value: +amount,
    currencyCode,
  }
}

type swellProductOption = {
  id: string
  name: string
  values: any[]
}

type normalizedProductOption = {
  id: string
  displayName: string
  values: ProductOptionValue[]
}

const normalizeProductOption = ({
  id,
  name: displayName = '',
  values = [],
}: swellProductOption): ProductOption => {
  let returnValues = values.map((value) => {
    let output: any = {
      label: value.name,
      // id: value?.id || id,
    }
    if (displayName.match(/colou?r/gi)) {
      output = {
        ...output,
        hexColors: [value.name],
      }
    }
    return output
  })
  return {
    __typename: 'MultipleChoiceOption',
    id,
    displayName,
    values: returnValues,
  }
}

const normalizeProductImages = (images: SwellImage[]) => {
  if (!images || images.length < 1) {
    return [{ url: '/' }]
  }
  return images?.map(({ file, ...rest }: SwellImage) => ({
    url: file?.url + '',
    height: Number(file?.height),
    width: Number(file?.width),
    ...rest,
  }))
}

const normalizeProductVariants = (
  variants: SwellVariant[],
  productOptions: swellProductOption[]
) => {
  return variants?.map(
    ({ id, name, price, option_value_ids: optionValueIds = [] }) => {
      const values = name
        .split(',')
        .map((i) => ({ name: i.trim(), label: i.trim() }))

      const options = optionValueIds.map((id) => {
        const matchingOption = productOptions.find((option) => {
          return option.values.find(
            (value: SwellProductOptionValue) => value.id == id
          )
        })
        return normalizeProductOption({
          id,
          name: matchingOption?.name ?? '',
          values,
        })
      })

      return {
        id,
        // name,
        // sku: sku ?? id,
        // price: price ?? null,
        // listPrice: price ?? null,
        // requiresShipping: true,
        options,
      }
    }
  )
}

export function normalizeProduct(swellProduct: SwellProduct): Product {
  const {
    id,
    name,
    description,
    images,
    options,
    slug,
    variants,
    price: value,
    currency: currencyCode,
  } = swellProduct
  // ProductView accesses variants for each product
  const emptyVariants = [{ options: [], id, name }]

  const productOptions = options
    ? options.map((o) => normalizeProductOption(o))
    : []
  const productVariants = variants
    ? normalizeProductVariants(variants, options)
    : []

  const productImages = normalizeProductImages(images)
  const product = {
    ...swellProduct,
    description,
    id,
    vendor: '',
    path: `/${slug}`,
    images: productImages,
    variants:
      productVariants && productVariants.length
        ? productVariants
        : emptyVariants,
    options: productOptions,
    price: {
      value,
      currencyCode,
    },
  }
  return product
}

export function normalizeCart({
  id,
  account_id,
  date_created,
  currency,
  tax_included_total,
  items,
  sub_total,
  grand_total,
  discounts,
}: SwellCart) {
  const cart: Cart = {
    id: id,
    customerId: account_id + '',
    email: '',
    createdAt: date_created,
    currency: { code: currency },
    taxesIncluded: tax_included_total > 0,
    lineItems: items?.map(normalizeLineItem) ?? [],
    lineItemsSubtotalPrice: +sub_total,
    subtotalPrice: +sub_total,
    totalPrice: grand_total,
    discounts: discounts?.map((discount) => ({ value: discount.amount })),
  }
  return cart
}

export function normalizeCustomer(customer: SwellCustomer): Customer {
  const { first_name: firstName, last_name: lastName } = customer
  return {
    ...customer,
    firstName,
    lastName,
  }
}

function normalizeLineItem({
  id,
  product,
  price,
  variant,
  quantity,
}: CartLineItem): LineItem {
  const item = {
    id,
    variantId: variant?.id,
    productId: product.id ?? '',
    name: product?.name ?? '',
    quantity,
    variant: {
      id: variant?.id ?? '',
      sku: variant?.sku ?? '',
      name: variant?.name!,
      image: {
        url:
          product?.images && product.images.length > 0
            ? product?.images[0].file.url
            : '/',
      },
      requiresShipping: false,
      price: price,
      listPrice: price,
    },
    path: '',
    discounts: [],
    options: [
      {
        value: variant?.name,
      },
    ],
  }
  return item
}