import Vue from 'vue'
import './SntCheckout.scss'
import { mapActions, mapGetters } from 'vuex'
import { CREATE_ORDER, GET_SALEPAGE_CALC_PRICE, GET_SALEPAGE_ORDER_CREDITCARD } from '../../resources/graphql'
import CreditCardForm from '../common/CreditCardForm.vue'

export default Vue.extend({
  name: 'SntCheckout',
  components: { CreditCardForm },
  apollo: {
    products: () => ({
      fetchPolicy: 'network-only',
      query: GET_SALEPAGE_CALC_PRICE,
      skip () {
        return this.isDemo || !this.isAuth
      },
      debounce: 800,
      variables () {
        return {
          domain: this.subdomain,
          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
          }))
      }
    })
  },
  data () {
    return {
      creditCard: undefined,
      products: [],
      submitting: false
    }
  },
  computed: {
    ...mapGetters({
      subdomain: 'salePage/subdomain',
      customer: 'salePage/customer',
      checkout: 'salePage/checkout',
      cart: 'cart/cart',
      purchases: 'cart/purchases',
      setPurchases: 'cart/setPurchases',
      selected: 'cart/selected'
    }),
    isDemo () {
      return !this.subdomain
    },
    customerId () {
      return this.customer?.id
    },
    isAuth () {
      return !!this.customerId
    },
    loading () {
      return this.$apollo.queries.products.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
        )
      ) || []
    },
    totalQuantity () {
      return this.selectedPurchase.reduce((total, purchase) => total + purchase.quantity, 0)
    },
    totalPrice () {
      return this.selectedPurchase.reduce((total, purchase) => total + ((purchase.price - purchase.discount) * purchase.quantity), 0)
    },
    purchasesItems () {
      const purchases = []
      this.selectedPurchase.forEach((item) => {
        if (item.__typename === 'Purchase') {
          purchases.push({
            subproductId: item.id,
            quantity: item.quantity,
            price: item.price
          })
        }
      })
      return purchases
    },
    setPurchasesItems () {
      const setPurchases = []
      this.selectedPurchase.forEach((item) => {
        if (item.__typename === 'SetPurchase') {
          setPurchases.push({
            productSetId: item.id,
            quantity: item.quantity,
            price: item.price
          })
        }
      })
      return setPurchases
    },
    shipping () {
      return this.checkout.shipping
    },
    shippingFee () {
      return this.paymentMethod === 1 ? this.checkout?.shipping?.codCost : this.checkout?.shipping?.cost
    },
    promoCodeDiscount () {
      if (this.checkout.promocode.discountType === 'percent') {
        return (this.totalPrice * this.checkout.promocode.discountValue) / 100
      }
      return this.checkout.promocode.discountValue || 0
    },
    shippingName () {
      return this.checkout?.shipping?.name
    },
    paymentMethod () {
      return this.checkout.paymentMethod
    },
    address () {
      return `${this.customer.address}`
    },
    netPrice () {
      const net = this.totalPrice + this.shippingFee - this.promoCodeDiscount
      return net > 0 ? net : 0
    },
    errors () {
      const errors = []
      if (!this.$_.isNumber(this.paymentMethod)) {
        errors.push('payment-method')
      }
      if (!this.shippingName) {
        errors.push('shipping')
      }
      if (!this.address.trim()) {
        errors.push('address')
      }
      return errors
    },
    valid () {
      return this.$_.isNumber(this.paymentMethod) && this.shippingName && this.address.trim() && this.totalPrice
    },
    slotProps () {
      return {
        selectedPurchase: this.selectedPurchase,
        totalQuantity: this.totalQuantity,
        totalPrice: this.totalPrice,
        shippingFee: this.shippingFee,
        promoCodeDiscount: this.promoCodeDiscount,
        netPrice: this.netPrice,
        errors: this.errors,
        valid: this.valid,
        submitting: this.submitting,
        submit: this.submit
      }
    }
  },
  methods: {
    ...mapActions({
      deletePurchases: 'cart/deletePurchases',
      deleteSetPurchases: 'cart/deleteSetPurchases',
      setOrder: 'salePage/setOrder',
      clearOrder: 'salePage/clearOrder',
      clearCheckout: 'salePage/clearCheckout',
      setCustomer: 'salePage/setCustomer'
    }),
    async createOrder (order) {
      const { data: { createOrder } } = await this.$apollo.mutate({
        mutation: CREATE_ORDER,
        variables: {
          input: order
        }
      })
      if (createOrder) {
        const customer = createOrder.order.customer
        // clear specific items used
        this.selectedPurchase.forEach((item) => {
          if (item.__typename === 'Purchase') {
            this.deletePurchases(item)
          } else {
            this.deleteSetPurchases(item)
          }
        })
        if (!this.$shipnity.isAuth) {
          await this.$shipnity.login(customer.tel, this.customer.postcode)
        }
        this.clearOrder()
        this.clearCheckout()
      }
      return createOrder
    },
    async submitCreditCardForm (payload) {
      if (this.isDemo) {
        return
      }
      const { id } = payload
      const url = window.location.origin
      const orderId = Number(id)
      const resultUrl = `${url}/orders/${orderId}`
      const { data: { salePage } } = await this.$apollo.query({
        fetchPolicy: 'network-only',
        query: GET_SALEPAGE_ORDER_CREDITCARD,
        variables: {
          domain: this.subdomain,
          customerId: this.$shipnity.customerId,
          orderId,
          resultUrl
        }
      })
      const order = this.$_.head(salePage.findCustomer?.orderList.nodes || [])
      if (order) {
        if (order.creditCardFormData) {
          this.creditCard = order.creditCardFormData
          setTimeout(() => {
            this.$refs.creditCardForm.$el.submit()
          }, 1000)
        }
      }
    },
    async submit () {
      if (this.isDemo) {
        return
      }
      this.submitting = true
      let shippingType = this.checkout.shipping.name
      const paymentMethod = this.paymentMethod
      const purchasesItems = this.purchasesItems
      const setPurchasesItems = this.setPurchasesItems
      const isCod = this.checkout.shipping.isCod
      if (shippingType !== 'COD' && isCod && paymentMethod === 1) {
        shippingType += ' COD'
      }
      const order = {
        shippingType,
        address: this.customer.address,
        customerId: this.customer.id,
        email: this.customer.email,
        name: this.customer.name,
        promotionCode: this.checkout?.promocode?.code,
        salePageDomain: this.subdomain,
        shippop: false,
        taxable: false,
        taxId: this.customer.taxId,
        tel: this.customer.tel,
        purchases: purchasesItems,
        setPurchases: setPurchasesItems
      }
      if (paymentMethod === 0) {
        this.setOrder({
          ...order,
          price: this.netPrice
        })
        this.$router.push({ name: 'SalePagePayment' })
      } else {
        const createOrder = await this.createOrder(order)
        if (createOrder) {
          if (paymentMethod === 1) {
            this.$router.push({
              name: 'SalePageThankYou',
              params: {
                orderId: createOrder.order.id
              }
            })
          } else if (paymentMethod === 2) {
            this.$router.push({
              name: 'SalePageOrderPayment',
              params: {
                orderId: createOrder.order.id
              },
              query: {
                method: 'qr'
              }
            })
          } else if (paymentMethod === 3) {
            await this.submitCreditCardForm(createOrder.order)
          }
        }
      }
      this.submitting = false
    }
  },
  template: `
    <div class="snt-checkout">
      <slot v-bind="slotProps">
        <snt-container class="snt-checkout__container">
          <div class="snt-checkout__items">
            <slot
              name="items"
              :items="cartProducts"
              :totalPrice="totalPrice">
              <snt-cart class="snt-checkout-items">
                <template #header>
                  <div class="snt-checkout-title">
                    สั่งซื้อสินค้า
                  </div>
                </template>
                <template #action>
                  <div class="snt-checkout-total">
                    <div class="snt-checkout-total__title">
                      ราคารวมสินค้าทั้งหมด
                    </div>
                    <snt-spacer />
                    <div class="snt-checkout-total__price">
                      {{ totalPrice | toLocaleString }} บาท
                    </div>
                  </div>
                </template>
              </snt-cart>
            </slot>
          </div>
          <div class="snt-checkout__promocode">
            <slot name="promoCodes">
              <snt-promo-codes />
            </slot>
          </div>
          <div class="snt-checkout__shipping">
            <slot name="shipping">
              <snt-shipping auto-select-first />
            </slot>
          </div>
          <div class="snt-checkout__address">
            <slot name="address">
              <snt-address />
            </slot>
          </div>
          <div class="snt-checkout__payment-methods">
            <slot name="paymentMethods">
              <snt-payment-methods />
            </slot>
          </div>
          <div class="snt-checkout__action">
            <slot
              name="action"
              :selectedPurchase="selectedPurchase"
              :netPrice="netPrice"
              :valid="valid"
              :submitting="submitting"
              :on="{
                submit
              }">
              <div class="snt-checkout-action">
                <div class="snt-checkout-action__net-price">
                  <div class="snt-checkout-action__net-price-title">
                    ราคาสุทธิ
                  </div>
                  <div class="snt-checkout-action__net-price-text">
                    {{ netPrice | toLocaleString }} บาท
                  </div>
                </div>
                <snt-button
                  :loading="submitting"
                  :disabled="!valid"
                  class="snt-checkout-action__submit"
                  color="primary"
                  depressed
                  large
                  @click="submit()">
                  ชำระเงิน
                </snt-button>
              </div>
            </slot>
          </div>
        </snt-container>
      </slot>
      <credit-card-form
        ref="creditCardForm"
        :credit-card="creditCard" />
    </div>
  `
})
