import './SntShipping.scss'
import Vue from 'vue'
import { mapActions, mapGetters } from 'vuex'
import {
  GET_SALEPAGE_CALC_PRICE,
  GET_SALEPAGE_SHIPPING,
  GET_SHIPPING_CALCULATORS
} from '../../resources/graphql'

export default Vue.extend({
  name: 'SntShipping',
  apollo: {
    products: () => ({
      fetchPolicy: 'network-only',
      query: GET_SALEPAGE_CALC_PRICE,
      skip () {
        return this.isDemo || !this.isAuth
      },
      debounce: 800,
      variables () {
        return {
          domain: this.subdomain || 'pomelo',
          customerId: this.customerId,
          purchases: this.cart
            .filter(({ __typename }) => __typename === 'Purchase')
            .map(({ id: subproductId, quantity, price }) => ({
              subproductId,
              quantity,
              price
            }))
        }
      },
      update ({ salePage }) {
        return salePage.calculatePrice
          .map(({ subproductId: id, name, price, quantity, discount }) => ({
            id,
            quantity,
            name,
            price,
            discount
          }))
      }
    }),
    shippingList: () => ({
      fetchPolicy: 'network-only',
      query () {
        return this.isDemo ? GET_SHIPPING_CALCULATORS : GET_SALEPAGE_SHIPPING
      },
      skip () {
        return !this.purchases.length && !this.setPurchases.length
      },
      variables () {
        return this.isDemo
          ? {
              page: 1,
              perPage: 100
            }
          : {
              domain: this.subdomain,
              input: {
                purchases: this.purchases,
                setPurchases: this.setPurchases
              }
            }
      },
      update (data) {
        const items = this.isDemo
          ? this.$_.map(data.shippingCalculators.nodes, ({ shippingType: name, cost, type }) => ({ name, cost, type }))
          : this.$_.map(data.salePage.shippingList, ({ name, cost, type }) => ({ name, cost, type }))
        const shippings = []
        const suffixCod = 'COD'
        items.forEach((item) => {
          const words = item.name.split(' ')
          const isCod = this.$_.includes(words, suffixCod)
          const filteredWords = this.$_.filter(words, (str) => str !== suffixCod)
          let name = filteredWords.join(' ')
          if (!name && isCod) {
            name = suffixCod
          }
          const value = {
            name,
            cost: item.cost,
            codCost: item.cost,
            type: item.type,
            isCod
          }
          const shipping = shippings.find((ship) => ship.name === value.name)
          if (!shipping) {
            shippings.push(value)
          } else {
            shipping.codCost = isCod ? item.cost : shipping.codCost
            shipping.isCod = isCod || shipping.isCod
          }
        })
        return shippings
      },
      result ({ data }) {
        if (!this.isDemo) {
          let shipping = null
          if (!this.shipping.name) {
            shipping = this.shippingList.find((ship) => ship.name === data.salePage.stock.shop.defaultShippingType)
          } else {
            shipping = this.shippingList.find((ship) => ship.name === this.shipping.name)
          }
          if (shipping) {
            this.selectShipping(shipping)
          }
        }
      }
    })
  },
  data () {
    return {
      products: [],
      shippingList: []
    }
  },
  computed: {
    ...mapGetters({
      subdomain: 'salePage/subdomain',
      customer: 'salePage/customer',
      checkout: 'salePage/checkout',
      cart: 'cart/cart',
      selected: 'cart/selected'
    }),
    isDemo () {
      return !this.subdomain
    },
    customerId () {
      return this.customer?.id
    },
    isAuth () {
      return !!this.customerId
    },
    loading () {
      return this.$apollo.queries.shippingList.loading
    },
    cartProducts () {
      return this.cart.map((cartItem) => {
        let price = cartItem.price
        let discount = 0
        if (cartItem.__typename === 'Purchase') {
          const product = this.products.find((productItem) => productItem.id === cartItem.id)
          if (product) {
            price = product.price
            discount = product.discount
          }
        }
        return {
          ...cartItem,
          price,
          discount
        }
      })
    },
    selectedPurchase () {
      return this.cartProducts.filter(
        (cartItem) => this.selected.some(
          (selected) => cartItem.id === selected.id
          && cartItem.__type === selected.__type
        )
      ) || []
    },
    shipping () {
      return this.checkout.shipping
    },
    paymentMethod () {
      return this.checkout.paymentMethod
    },
    shippingFee () {
      return this.paymentMethod === 1 ? this.shipping?.codCost : this.shipping?.cost
    },
    purchases () {
      return this.selectedPurchase
        .filter(({ __typename }) => __typename === 'Purchase')
        .map(({ id: subproductId, quantity, price, discount }) => ({
          subproductId,
          quantity,
          price,
          discount
        }))
    },
    setPurchases () {
      return this.selectedPurchase
        .filter(({ __typename }) => __typename === 'SetPurchase')
        .map(({ id: subproductId, quantity, price }) => ({
          subproductId,
          quantity,
          price
        }))
    },
    slotProps () {
      return {
        items: this.shippingList,
        value: this.shipping,
        loading: this.loading,
        selectShipping: this.selectShipping,
        isShippingSelected: this.isShippingSelected
      }
    }
  },
  methods: {
    ...mapActions({
      setCheckout: 'salePage/setCheckout'
    }),
    isShippingSelected (shipping) {
      return this.shipping.name === shipping.name
    },
    selectShipping (shipping) {
      this.setCheckout({
        shipping,
        paymentMethod: this.$_.isEqual(this.shipping, shipping) ? this.paymentMethod : null
      })
      this.$emit('input', shipping)
    }
  },
  template: `
    <div class="snt-shipping">
      <slot v-bind="slotProps">
        <snt-container class="snt-shipping__container">
          <div class="snt-shipping__title">
            <span>
              วิธีการจัดส่ง
            </span>
          </div>
          <div class="snt-shipping__text">
            <div class="snt-shipping-text">
              <snt-select
                :value="shipping"
                :items="shippingList"
                :loading="loading"
                class="snt-shipping__input"
                item-text="name"
                placeholder="เลือกวิธีจัดส่ง"
                return-object
                outlined
                dense
                hide-details
                @change="selectShipping($event)" />
              <span class="snt-shipping__price">
                {{ shippingFee | toLocaleString }} บาท
              </span>
            </div>
          </div>
        </snt-container>
      </slot>
    </div>
  `
})
