<template>
  <div class="snt-checkout">
    <slot v-bind="slotProps">
      <v-container class="snt-checkout__container">
        <div class="snt-checkout__items">
          <slot
            name="items"
            :items="items"
            :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>
                  <v-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>
              <v-btn
                :loading="submitting"
                :disabled="!valid"
                class="snt-checkout-action__submit"
                depressed
                large
                @click="submit()">
                ชำระเงิน
              </v-btn>
            </div>
          </slot>
        </div>
      </v-container>
    </slot>
    <credit-card-form
      ref="creditCardForm"
      :credit-card="creditCard" />
  </div>
</template>

<script>
import { mapActions, mapGetters } from 'vuex'
import { CREATE_ORDER, GET_SALEPAGE_ORDER_CREDITCARD } from '@/resources/graphql'
import SntPromoCodes from './PromoCodes.vue'
import SntAddress from './Address.vue'
import SntShipping from './Shipping.vue'
import SntCart from './Cart.vue'
import SntPaymentMethods from './PaymentMethods.vue'
import CreditCardForm from './CreditCardForm.vue'

export default {
  name: 'SntCheckout',
  components: {
    SntCart,
    SntPromoCodes,
    SntShipping,
    SntAddress,
    SntPaymentMethods,
    CreditCardForm
  },
  data () {
    return {
      creditCard: undefined,
      submitting: false
    }
  },
  computed: {
    ...mapGetters({
      subdomain: 'salePage/subdomain',
      customer: 'salePage/customer',
      purchases: 'cart/purchases',
      setPurchases: 'cart/setPurchases',
      selectedPurchase: 'cart/selected',
      checkout: 'salePage/checkout'
    }),
    isDemo () {
      return !this.subdomain
    },
    items () {
      return this.$_.concat(this.purchases, this.setPurchases)
    },
    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
    },
    totalQuantity () {
      let total = 0
      this.selectedPurchase.forEach((item) => {
        total += item.quantity
      })
      return total
    },
    totalPrice () {
      let total = 0
      this.selectedPurchase.forEach((item) => {
        total += item.price * item.quantity
      })
      return total
    },
    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: 'order/setOrder',
      clearOrder: 'order/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
    }
  }
}
</script>

<style scoped>
  .snt-checkout {
    min-height: calc(100vh - 100px);
  }
  .snt-checkout__title {
    margin-top: 1.25rem;
  }
  .snt-checkout__title {
    font-size: 1.25rem;
  }
  .snt-checkout-items {
    min-height: 100%;
  }
  .snt-checkout-total {
    display: flex;
    padding: 32px 16px;
  }
  .snt-checkout-total__price {
    color: var(--v-primary-base);
  }
  .snt-checkout__promocode {
    margin-bottom: 1.25rem;
  }
  .snt-checkout__shipping {
    margin-bottom: 1.25rem;
  }
  .snt-checkout__address {
    margin-bottom: 1.25rem;
  }
  .snt-checkout__payment-methods {
    margin-bottom: 1.25rem;
  }
  .snt-checkout__action {
    margin-bottom: 1.25rem;
  }
  .snt-checkout-action {
    display: flex;
    background-color: #ffffff;
    padding: 16px;
    align-items: center;
    justify-content: flex-end;
  }
  .snt-checkout-action__net-price {
    color: #4E4E4E;
    margin-right: 16px;
  }
  .snt-checkout-action__net-price-title {
    font-weight: 500;
  }
  .snt-checkout-action__net-price-text {
    color: var(--v-primary-base);
  }
  .snt-checkout-action__submit.v-btn {
    width: 210px;
    line-height: 27px;
    letter-spacing: 0.01em;
    color: #FFFFFF;
    background-color: var(--v-primary-base);
  }
</style>
