import * as T from '@/store/utils/types'
import * as U from '@/store/utils/apiUrls'
import { get, post } from '@/store/utils/api'
import helpers from '@/helpers'
import moment from 'moment'
import store from '@/store'
import { IS_LOGGED_IN_GUEST_GETTER_NAME } from '@/config/defaults'
import Vue from 'vue'
import _ from 'lodash'
import { RouteHasPath } from '@/helpers/routing'
import { ESHOP_I_TOKEN_REDEEM } from '@/config/url-prefix'

/**
 * addProductToCart
 *
 * @param commit
 * @param dispatch
 * @param getters
 * @param rootGetters
 * @param {
 *  int? countryId Current user selected country is used if country id is not provided
 *  int? locationId Current user selected location is used if the location is not provided
 *  int? salesTypeId Current carts sales type id is used if available then it uses products default eligible sales type id if not provided
 *  int? quantity Quantity is 1 if not provided
 *  } payload
 * @returns {Promise<void>}
 */
export const addProductToCart = async ({ commit, dispatch, getters, rootGetters }, payload = {}) => {
  commit(T.PROCESSING_STARTED, 'productsAddingToCart', { root: true })
  let isValid = true
  let isSalesTypeMixed = false
  let qty = Number(payload.quantity)
  let salesTypeId = payload.salesTypeId
  let salesTypes = []
  let query = { country_id: payload.countryId, keys: ['sale_types'] }

  await post(U.MASTER_KEY_URL, query).then(response => {
    salesTypes = response.data.sale_types
  })
  let salesTypeTitle = getters.getProductSaleType(salesTypeId, salesTypes)
  let isRentalProduct = salesTypeTitle.toLowerCase() === 'rental'

  if (qty === 0) {
    /* This block for item remove scenario */
    isValid = true
  } else if (getters.getCartHasRental) {
    /* This block runs when cart has rental product */
    // If current item not rental product `isSalesTypeMixed` flag will be TRUE
    isSalesTypeMixed = !isRentalProduct
    isValid = false
  } else {
    /* This block runs when no rental product detected in the cart */
    let cartItems = getters.getCartDisplayItems
    let cartItemQuantity = cartItems.length

    if (helpers.getValue(cartItems, '[0].is_enrolment_item')) {
      cartItemQuantity--
    }

    if (cartItemQuantity === 0 || !isRentalProduct) {
      isValid = true
    } else {
      // Adding rental and non-rental product to cart actions detected
      isSalesTypeMixed = true
      isValid = false
    }
  }

  if (isValid) {
    commit(T.PROCESSING_STARTED, 'productsAddingToCart-' + payload.product_id + '-' + payload.kitting_id, {
      root: true,
    })
    let country =
      (!helpers.isEmpty(payload.countryId) && payload.countryId) ||
      helpers.getValue(rootGetters.getAppLocationCountry, 'countryId', '')
    let location = payload.locationId || helpers.getValue(rootGetters.getAppLocationCountry, 'locationId', '')
    let inCartProductSalesType = payload.isUpdateSaleType
      ? false
      : getters.getCartProductEligibleSalesType(payload.product_id, payload.kitting_id)
    let orderForUserId = null
    if (rootGetters.getAppStatus('eshop') === true && rootGetters['eshop/getIsOrderingForDownLine'] === true) {
      orderForUserId = rootGetters['eshop/getOrderingFor'].details.user_id
    }
    if (!helpers.isEmpty(country)) {
      let product = {
        country_id: country,
        location_id: location,
        sales_type_id:
          inCartProductSalesType !== false
            ? inCartProductSalesType.id
            : payload.salesTypeId || getters.getProductUserEligibleSalesTypeId(payload.product_id, payload.kitting_id),
        quantity: typeof payload.quantity !== 'undefined' ? payload.quantity : 1,
        order_for_user_id: orderForUserId,
        is_rp: rootGetters['eshop/isShowRetailPrice'],
      }
      if (payload.product_id && payload.product_id.length !== 0) {
        product['product_id'] = payload.product_id
      }
      if (payload.kitting_id && payload.kitting_id.length !== 0) {
        product['kitting_id'] = payload.kitting_id
      }
      let cancelToken = await dispatch(
        'generateCancelToken',
        'products-' + payload.product_id + '-' + payload.kitting_id,
        { root: true }
      )
      post(U.ESHOP_CART_ADD_PRODUCT, product, cancelToken.token)
        .then(response => {
          commit(T.PROCESSING_FINISHED, 'productsAddingToCart', { root: true })
          commit(T.ESHOP_CART_SET_ADD_PRODUCT, response)
          commit(T.PROCESSING_FINISHED, 'productsAddingToCart-' + payload.product_id + '-' + payload.kitting_id, {
            root: true,
          })
          commit(T.ESHOP_CART_SET_PRODUCT_DUMMY, { sizes: [], evoucher: [], name: getters.getCartName }) // clear selected dummies on add product to cart
          commit(T.ESHOP_CART_SET_INST_ADDRESS_PRODUCT_DUMMY, { inst_details: [], name: getters.getCartName }) // clear selected inst product address dummies on add product to cart
          dispatch('loadCart', { countryId: country, locationId: location, ekSmart: isRentalProduct })
        })
        .catch(e => {
          dispatch('logError', { category_loading: e }, { root: true })
          commit(T.PROCESSING_FINISHED, 'productsAddingToCart', { root: true })
          commit(T.PROCESSING_FINISHED, 'productsAddingToCart-' + payload.product_id + '-' + payload.kitting_id, {
            root: true,
          })
        })
    }
  } else {
    commit(T.PROCESSING_FINISHED, 'productsAddingToCart', { root: true })
    let errorText = Vue.prototype.$t('Eshop.EkSmartCartItem.UpperLimit.Error', { qty: 1 })
    if (isSalesTypeMixed) {
      errorText = Vue.prototype.$t('Eshop.Cart.InvalidProductCombination.Error')
    }

    Vue.prototype.$swal({
      title: Vue.prototype.$t('Eshop.AddCart.Error.Title'),
      text: errorText,
      type: 'warning',
      timer: '5000',
    })
  }
  return isValid
}

export const addToCartByProductFilters = ({ dispatch, getters }, payload) => {
  return dispatch('loadProducts', {
    countryId: payload.countryId,
    locationId: payload.locationId,
    salesTypesIds: [payload.salesTypeId],
    filters: [payload.filter],
    readOnly: payload.readOnly || false,
    commit:
      (payload.free && payload.free === true && T.ESHOP_PRODUCT_FREE_SET) ||
      (payload.memberKit && payload.memberKit === true && T.ESHOP_PRODUCT_MEMBER_KIT) ||
      null,
  })
    .then(products => {
      if (products.length && products.length > 0) {
        let productPromisses = []
        products.forEach(product => {
          if (typeof getters.getCartProductOrKitting(product.product_id, product.kitting_id) === 'undefined') {
            productPromisses.push(
              dispatch('addProductToCart', {
                countryId: payload.countryId,
                locationId: payload.locationId,
                product_id: typeof product.product_id !== 'undefined' ? product.product_id : null,
                kitting_id: typeof product.kitting_id !== 'undefined' ? product.kitting_id : null,
                salesTypeId: payload.salesTypeId,
                quantity: 1,
              })
            )
          }
          return Promise.all(productPromisses)
            .then(() => true)
            .catch(() => false)
        })
      } else {
        return false
      }
    })
    .catch(e => {
      return false
    })
}

/**
 * Load Cart
 *
 * @param commit
 * @param dispatch
 * @param rootGetters
 * @param getters
 * @param {
 *  int? countryId current user selected country is used if not provided
 *  int? locationId current location selected location id is used if not provided
 * } payload
 * @returns {Promise<T>}
 */
export const loadCart = async ({ commit, dispatch, rootGetters, getters }, payload = {}) => {
  commit(T.PROCESSING_STARTED, 'loadingCart', { root: true })
  let country = payload.countryId || rootGetters.getAppLocationCountry.countryId
  let location = payload.locationId || rootGetters.getAppLocationCountry.locationId
  let functionType = payload.functionType
  let cancelToken = await dispatch('generateCancelToken', 'loadingCart', { root: true })
  let address = null
  let promotions
  let isRetailPriceToggle = rootGetters['eshop/isShowRetailPrice']
  let enrolmentTypeId = null
  let deliveryMethodId = await dispatch(
    'loadFetchMasterDataId',
    {
      master: ['SALE_DELIVERY_METHOD'],
      data: ['DELIVERY'],
    },
    { root: true }
  )
  if (getters.getOrderShipping !== null) {
    if (getters.getOrderShipping.sale_delivery_method === deliveryMethodId) {
      if (
        typeof getters.getOrderShipping.recipient_addresses !== 'undefined' &&
        typeof getters.getOrderShipping.recipient_selected_shipping_index !== 'undefined'
      ) {
        address =
          getters.getOrderShipping.recipient_addresses[
            getters.getOrderShipping.recipient_addresses.length > 1
              ? getters.getOrderShipping.recipient_selected_shipping_index
              : 0
          ]
      }
    }
  }
  if (rootGetters.getAppStatus('autoship') && _.isEmpty(rootGetters.getAutoshipShippingInfo) === false) {
    address = helpers.getValue(rootGetters.getAutoshipShippingInfo, 'recipient_addresses[0]', null)
  }
  let orderForUserId = null
  if (rootGetters.getAppStatus('eshop') === true && rootGetters['eshop/getIsOrderingForDownLine'] === true) {
    orderForUserId = rootGetters['eshop/getOrderingFor'].details.user_id
  }
  if (rootGetters.getAppStatus('enrolment') === true) {
    enrolmentTypeId = helpers.getValue(rootGetters['enrolment/getEnrolForm'], 'enrolment_type', null)
  }
  // 3rdParty Apps
  if (
    rootGetters.getAppStatus('thirdPartyAppsCheckout') === true ||
    rootGetters.getAppStatus('thirdPartyAppsProductList') === true
  ) {
    if (
      rootGetters[IS_LOGGED_IN_GUEST_GETTER_NAME] &&
      (rootGetters.getCurrentSaleId === 0 || rootGetters.getCurrentSaleId === '')
    ) {
      enrolmentTypeId = helpers.getValue(
        rootGetters['3rdPartyCheckoutMembership/getMembershipInfo'],
        'enrolment_type_id',
        null
      )
    }
    let shippingInfo = helpers.getValue(
      rootGetters['3rdPartyCheckoutShippingAndPayment/getShippingAndPaymentInfo'],
      'shippingModel'
    )
    if (shippingInfo && helpers.getValue(shippingInfo, 'sale_delivery_method') === deliveryMethodId) {
      address = helpers.getValue(shippingInfo, 'recipient_addresses[0]', null)
    }
  }

  if (rootGetters.getAppStatus('virel') === true) {
    isRetailPriceToggle = true
  }
  promotions = getters.getSelectedFocPwpItems

  payload = {
    country_id: country,
    location_id: location,
    order_for_user_id: orderForUserId,
    ek_smart: Boolean(payload.ekSmart),
    address: address,
    promotions: promotions,
    enrolment_type_id: enrolmentTypeId,
    is_rp: isRetailPriceToggle,
    function_type: functionType,
  }

  if (rootGetters.getAppStatus('eshop') === true && Vue.prototype.$appSettings.evo.enable) {
    payload['cw_id'] = getters.getCartSalesCwId
  }

  if (getters.getCartCampaignDetails && !RouteHasPath(store.state.route.path, ESHOP_I_TOKEN_REDEEM)) {
    payload = {
      ...payload,
      redeem_later: getters.getRedeemLaterStatus,
      campaign_selection: getters.getITokenCartItems.map(item => ({
        id: item.id,
        type: item.type,
        quantity: item.quantity,
      })),
    }
  }

  if (rootGetters.getAppStatus('autoship')) {
    payload.filters = ['auto_ship']
  }

  return post(U.ESHOP_CART_DETAILS, payload, cancelToken.token)
    .then(response => {
      let details = response.data
      commit(T.PROCESSING_FINISHED, 'loadingCart', { root: true })
      commit(T.ESHOP_CART_SET_DETAILS, details)
      commit(T.ESHOP_CART_SET_FOC_PWP, { promotion: helpers.getValue(details, 'eligible.promotion', []) })
    })
    .catch(e => {
      dispatch('logError', { category_loading: e }, { root: true })
      commit(T.PROCESSING_FINISHED, 'loadingCart', { root: true })
    })
}

export const cartNeedSelection = ({ getters }, payload) => {
  let cartDummies = getters.getCartDummies
  let cartInstItems = getters.getCartInstItems

  let needSelection = false
  if (cartDummies.length > 0 || cartInstItems.length > 0) {
    needSelection = true
  }
  return needSelection
}

export const loadCartSizesDetails = async ({ getters, commit, dispatch, rootGetters }) => {
  let cartItems = getters.getCartItems
  commit(T.PROCESSING_STARTED, 'loadingCartSizes', { root: true })
  for (let i in cartItems) {
    if (
      !helpers.isEmpty(cartItems[i].product_id) &&
      cartItems[i].is_dummy_code === 1 &&
      !getters.getProductOrKittingDetails(cartItems[i].product_id)
    ) {
      await dispatch('loadProductOrKittingDetails', {
        product_id: cartItems[i].product_id,
        country_id: rootGetters.getAppLocationCountry.countryId,
      })
    } else if (
      !helpers.isEmpty(cartItems[i].kitting_id) !== null &&
      cartItems[i].products.findIndex(product => product.is_dummy_code === 1) !== -1 &&
      !getters.getProductOrKittingDetails(null, cartItems[i].kitting_id)
    ) {
      await dispatch('loadProductOrKittingDetails', {
        kitting_id: cartItems[i].kitting_id,
        country_id: rootGetters.getAppLocationCountry.countryId,
      })
    }
  }
}

export const clearCart = async ({ commit, dispatch }) => {
  commit(T.PROCESSING_STARTED, 'clearCart', { root: true })
  return await get(U.ESHOP_CART_CLEAR)
    .then(response => {
      commit(T.PROCESSING_FINISHED, 'clearCart', { root: true })
      commit(T.ESHOP_CART_CLEAR_LOCAL)
      commit(T.ESHOP_CART_CLEAR_PRODUCT_DUMMY)
    })
    .catch(e => {
      dispatch('logError', { clearCart: e }, { root: true })
      commit(T.PROCESSING_FINISHED, 'clearCart', { root: true })
    })
}

export const orderForDownLine = ({ commit, dispatch }, payload) => {
  commit(T.ESHOP_CART_ORDER_FOR_DOWNLINE, payload)
}

export const setShowProductDetailModal = ({ commit, dispatch }, payload) => {
  commit(T.ESHOP_SHOW_PRODUCT_DETAIL_MODAL, payload)
}
export const selectCartProductsSizes = ({ commit }, payload) => {
  commit(T.ESHOP_CART_SET_PRODUCT_DUMMY, payload)
}

export const clearCartProductsSizes = ({ commit }) => {
  commit(T.ESHOP_CART_CLEAR_PRODUCT_DUMMY, [])
}
export const selectCartProductsInstDetails = ({ commit }, payload) => {
  commit(T.ESHOP_CART_SET_INST_ADDRESS_PRODUCT_DUMMY, payload)
}

export const isInstallationDetailsValid = ({ getters }, payload) => {
  let installationDetails = getters.getCartInstDetails
  if (
    installationDetails !== undefined &&
    installationDetails.inst_details !== undefined &&
    installationDetails.inst_details.length !== undefined
  ) {
    let details = installationDetails.inst_details[0]
    if (details !== undefined) {
      let date = moment(details.installation_date, 'YYYY-MM-DD')
      if (date.isValid() && date > moment() && !helpers.isEmpty(details.installation_time)) {
        return Promise.resolve(true)
      } else {
        return Promise.resolve(false)
      }
    } else {
      return Promise.resolve(false)
    }
  } else {
    return Promise.resolve(false)
  }
}

export const clearCartProductsInstAddresses = ({ commit }) => {
  commit(T.ESHOP_CART_CLEAR_INST_ADDRESS_PRODUCT_DUMMY, [])
}
export const checkCartDummyAllSizesSelected = ({ getters }, payload = {}) => {
  // get selected dummies
  let allSelectedDummies = payload.selectedDummies || getters.getCartIsAllDummiesSelected
  let allSelectedInstAddress = payload.selectedDummiesInstAddress || getters.getCartSelectedInstDetails
  // Get the items in the cart that are dummies
  let cartDummies = payload.allDummies || getters.getCartDummies
  let cartInstItems = payload.allInstDetails || getters.getCartInstItems
  let allSelected = true

  cartInstItems.forEach(instItem => {
    if (!instItem.installation_date || !instItem.installation_date) {
      allSelected = false
    }
  })
  // TO DO
  /*cartInstItems.forEach((item) => {
    // get the selected dummies that belongs to the current cart item
      let selectedInstItems = allSelectedInstAddress['inst_details'].filter(sItem => {
      return ( // for products the product id should be set but the kitting should be null
        typeof item.product_id !== 'undefined' &&
          typeof sItem.product_id !== 'undefined' &&
          item.product_id !== null &&
          sItem.product_id !== null &&
          item.product_id === sItem.product_id &&
          (typeof item.kitting_id === 'undefined' || item.kitting_id === null) &&
          (typeof sItem.kitting_id === 'undefined' || sItem.kitting_id === null)
      ) ||
        ( // kitting the product id and kitting id should exist
          typeof item.kitting_id !== 'undefined' &&
          typeof sItem.kitting_id !== 'undefined' &&
          item.kitting_id !== null &&
          sItem.kitting_id !== null &&
          item.kitting_id === sItem.kitting_id
        )
    })
  })*/

  // For the carts items that has dummies
  cartDummies.forEach(item => {
    // get the selected dummies that belongs to the current cart item
    let selectedDummies = allSelectedDummies['sizes'].filter(sItem => {
      return (
        // for products the product id should be set but the kitting should be null
        (typeof item.product_id !== 'undefined' &&
          typeof sItem.product_id !== 'undefined' &&
          item.product_id !== null &&
          sItem.product_id !== null &&
          item.product_id === sItem.product_id &&
          (typeof item.kitting_id === 'undefined' || item.kitting_id === null) &&
          (typeof sItem.kitting_id === 'undefined' || sItem.kitting_id === null)) || // kitting the product id and kitting id should exist
        (typeof item.kitting_id !== 'undefined' &&
          typeof sItem.kitting_id !== 'undefined' &&
          item.kitting_id !== null &&
          sItem.kitting_id !== null &&
          item.kitting_id === sItem.kitting_id)
      )
    })
    let evoucherQuantity = allSelectedDummies['evoucher'].reduce((qty, voucherItem) => {
      if (item.product_id === voucherItem.product_id && item.kitting_id === voucherItem.kitting_id) {
        qty = qty + voucherItem.quantity
      }
      return qty
    }, 0)
    // get all the dummies that belongs to the cart item
    let itemDummies = getters.getProductOrKittingDummies(item.product_id, item.kitting_id)
    if (itemDummies.length > 0) {
      // check the dummies totals that belongs to the cart item
      itemDummies.forEach(itemDummy => {
        let selectedQuantity = 0
        if (selectedDummies) {
          // get the relative dummy product
          selectedQuantity = selectedDummies.reduce((qty, item) => {
            if (
              (typeof item.product_id !== 'undefined' &&
                item.product_id === itemDummy.product_id &&
                item.is_foc === itemDummy.is_foc) ||
              (typeof item.product_id !== 'undefined' &&
                typeof item.kitting_id !== 'undefined' &&
                item.product_id === itemDummy.product_id &&
                item.kitting_id === itemDummy.kitting_id &&
                item.is_foc === itemDummy.is_foc)
            ) {
              qty = qty + item.quantity
            }
            return qty
          }, 0)
        }
        if (selectedQuantity + evoucherQuantity * itemDummy.quantity !== itemDummy.quantity * item.quantity) {
          allSelected = false
        }
      })
    } else {
      // Dummies not loaded, this only happens if the dummies is not properly setup in the backend
      allSelected = true
    }
  })
  return allSelected
}

export const checkCartDummyInstAddressSelected = ({ getters }, payload = {}) => {
  // get selected dummies
  let allSelectedDummies = payload.selectedDummies || getters.getCartIsAllDummiesSelected
  // Get the items in the cart that are dummies
  let cartDummies = payload.allDummies || getters.getCartDummies
  let allSelected = true
  // For the carts items that has dummies
  cartDummies.forEach(item => {
    // get the selected dummies that belongs to the current cart item
    let selectedDummies = allSelectedDummies['sizes'].filter(sItem => {
      return (
        // for products the product id should be set but the kitting should be null
        (typeof item.product_id !== 'undefined' &&
          typeof sItem.product_id !== 'undefined' &&
          item.product_id !== null &&
          sItem.product_id !== null &&
          item.product_id === sItem.product_id &&
          (typeof item.kitting_id === 'undefined' || item.kitting_id === null) &&
          (typeof sItem.kitting_id === 'undefined' || sItem.kitting_id === null)) || // kitting the product id and kitting id should exist
        (typeof item.kitting_id !== 'undefined' &&
          typeof sItem.kitting_id !== 'undefined' &&
          item.kitting_id !== null &&
          sItem.kitting_id !== null &&
          item.kitting_id === sItem.kitting_id)
      )
    })
    let evoucherQuantity = allSelectedDummies['evoucher'].reduce((qty, voucherItem) => {
      if (item.product_id === voucherItem.product_id && item.kitting_id === voucherItem.kitting_id) {
        qty = qty + voucherItem.quantity
      }
      return qty
    }, 0)
    // get all the dummies that belongs to the cart item
    let itemDummies = getters.getProductOrKittingDummies(item.product_id, item.kitting_id)
    if (itemDummies.length > 0) {
      // check the dummies totals that belongs to the cart item
      itemDummies.forEach(itemDummy => {
        let selectedQuantity = 0
        if (selectedDummies) {
          // get the relative dummy product
          selectedQuantity = selectedDummies.reduce((qty, item) => {
            if (
              (typeof item.product_id !== 'undefined' &&
                item.product_id === itemDummy.product_id &&
                item.is_foc === itemDummy.is_foc) ||
              (typeof item.product_id !== 'undefined' &&
                typeof item.kitting_id !== 'undefined' &&
                item.product_id === itemDummy.product_id &&
                item.kitting_id === itemDummy.kitting_id &&
                item.is_foc === itemDummy.is_foc)
            ) {
              qty = qty + item.quantity
            }
            return qty
          }, 0)
        }
        if (selectedQuantity + evoucherQuantity * itemDummy.quantity !== itemDummy.quantity * item.quantity) {
          allSelected = false
        }
      })
    } else {
      // Dummies not loaded, this only happens if the dummies is not properly setup in the backend
      allSelected = true
    }
  })
  return allSelected
}
export const setCartName = ({ commit }, payload) => {
  commit(T.ESHOP_SET_CART_NAME, payload)
}

export const setPreserveCartState = ({ commit }, payload) => {
  commit(T.SET_CART_PRESERVE_STATE, payload)
}
