import { getCodeByName } from '@things-factory/code-base'
import { MultiColumnFormStyles } from '@things-factory/form-ui'
import '@things-factory/grist-ui'
import { i18next, localize } from '@things-factory/i18n-base'
import { openPopup } from '@things-factory/layout-base'
import { client, CustomAlert } from '@things-factory/shell'
import gql from 'graphql-tag'
import { css, html, LitElement } from 'lit-element'
import { PLATFORM } from '../../constants'
import './branch-logistics-popup'
import './pickup-logistics-popup'

class LogisticsInitPopup extends localize(i18next)(LitElement) {
  static get properties() {
    return {
      config: Object,
      data: Object,
      orderInformation: Object,
      shippingProviders: Array,
      deliveryTypes: Array,
      logisticsParam: Object,
      logisticsDetail: Object,
      branchList: Array,
      addressList: Array,
      timeSlotList: Array,
      pickupInformation: Object,
      dropoffInformation: Object,
      pickupTimeId: String,
      _type: String
    }
  }

  constructor() {
    super()
    this.logisticsParam = {}
    this.logisticsDetail = {}
    this.dropoffInformation = {}
    this.shippingProviders = []
    this.deliveryTypes = []
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          padding: 10px;
          display: flex;
          flex-direction: column;
          overflow-x: overlay;
          background-color: var(--main-section-background-color);
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
        }
        .button-container {
          padding: var(--button-container-padding);
          margin: var(--button-container-margin);
          text-align: var(--button-container-align);
          background-color: var(--button-container-background);
          height: var(--button-container-height);
        }
      `
    ]
  }

  render() {
    return html`
      <form id="input-form" name="marketplaceOrder" class="multi-column-form">
        <fieldset>
          <legend>${i18next.t('title.shipping_information')}</legend>
          ${this.orderInformation.marketplaceStore.platform === PLATFORM.LAZADA.value
            ? html`
                <label>${i18next.t('label.shipping_provider')}</label>
                <select name="shippingProvider" required>
                  <option value="">${i18next.t('text.select_a_shipping_provider')}</option>
                  ${(this.shippingProviders || []).map(
                    shippingProvider => html`
                      <option value="${shippingProvider.name}">${shippingProvider.name}</option>
                    `
                  )}
                </select>

                <label>${i18next.t('label.delivery_type')}</label>
                <select name="deliveryType" required>
                  <option value="">${i18next.t('text.select_a_delivery_type')}</option>
                  ${(this.deliveryTypes || []).map(
                    deliveryType => html` <option value="${deliveryType.name}">${deliveryType.name}</option> `
                  )}
                </select>
              `
            : ''}
          ${this.orderInformation.marketplaceStore.platform === PLATFORM.SHOPEE.value
            ? html`
                <label>${i18next.t('label.type')}</label>
                <select name="logisticsType" @change=${e => (this._type = e.target.value)}>
                  <option value="">${i18next.t('text.select_a_logistics_type')}</option>
                  ${Object.keys(this.logisticsParam).map(key => html` <option value="${key}">${key}</option> `)}
                </select>

                ${this._type === 'dropoff' && this.logisticsParam.dropoff.includes('branch_id')
                  ? html` <label>${i18next.t('label.branch_id')}</label>
                      <input id="dropOff" name="dropOff" readonly @click="${this._openBranchSelector.bind(this)}" />`
                  : ''}
                ${this._type === 'pickup' && this.logisticsParam.pickup.includes('address_id')
                  ? html`
                      <label>${i18next.t('label.address_id')}</label>
                      <input id="address" name="address" readonly @click="${this._openAddressSelector.bind(this)}" />

                      <label>${i18next.t('label.pickup_date')}</label>
                      <input id="pickupDate" name="pickupDate" readonly />
                    `
                  : ''}
                ${this._type === 'non_integrated'
                  ? html` <label>${i18next.t('label.tracking_no')}</label>
                      <input id="trackingNo" name="trackingNo" />`
                  : ''}
              `
            : ''}
        </fieldset>
      </form>

      <div class="button-container">
        <mwc-button
          @click="${this.initLogistics.bind(this)}"
          raised
          label="${i18next.t('button.initialise')}"
        ></mwc-button>
      </div>
    `
  }

  get grist() {
    return this.shadowRoot.querySelector('data-grist')
  }

  get shippingProviderInput() {
    return this.shadowRoot.querySelector('select[name=shippingProvider]')
  }

  get deliveryTypeInput() {
    return this.shadowRoot.querySelector('select[name=deliveryType]')
  }

  get dropOffField() {
    return this.shadowRoot.querySelector('input#dropOff')
  }

  get addressField() {
    return this.shadowRoot.querySelector('input#address')
  }

  get timeSlotField() {
    return this.shadowRoot.querySelector('input#pickupDate')
  }

  get trackingNoField() {
    return this.shadowRoot.querySelector('input#trackingNo')
  }

  get marketplaceOrderForm() {
    return this.shadowRoot.querySelector('form[name=marketplaceOrder]')
  }

  get logisticsTypeSelector() {
    return this.shadowRoot.querySelector('select[name=logisticsType]')
  }

  async firstUpdated() {
    await this._marketplaceLogisticsInitParam()
  }

  async _marketplaceLogisticsInitParam() {
    if (this.orderInformation.marketplaceStore.platform === PLATFORM.SHOPEE.value) {
      this.logisticsParam = await this.fetchLogisticsParam()
    } else if (this.orderInformation.marketplaceStore.platform === PLATFORM.LAZADA.value) {
      this.deliveryTypes = await getCodeByName('DELIVERY_TYPES')
      this.shippingProviders = await this.fetchShippingProvider()
    }
  }

  async fetchShippingProvider() {
    try {
      const response = await client.query({
        query: gql`
          query getStoreLogistics($storeId: String!) {
            getStoreLogistics(storeId: $storeId) {
              name
              isDefault
            }
          }
        `,
        variables: { storeId: this.orderInformation.marketplaceStore.id }
      })

      if (!response.errors) {
        return response.data.getStoreLogistics
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async fetchLogisticsParam() {
    try {
      const response = await client.query({
        query: gql`
          query getLogisticsParam($storeId: String!, $orderNo: String!) {
            getLogisticsParam(storeId: $storeId, orderNo: $orderNo) {
              pickup
              dropoff
              non_integrated
              logisticsDetail {
                pickup {
                  addressId
                  country
                  state
                  city
                  address
                  zipcode
                  district
                  timeSlot {
                    pickupTimeId
                    pickupDate
                    timeText
                  }
                }
                dropoff {
                  branchId
                  country
                  state
                  city
                  address
                  zipcode
                  district
                }
              }
            }
          }
        `,
        variables: { storeId: this.orderInformation.marketplaceStore.id, orderNo: this.orderInformation.orderNo }
      })

      if (!response.errors) {
        const logisticsType = response.data.getLogisticsParam
        this.logisticsDetail = logisticsType.logisticsDetail
        const logisticsParam = {}
        if (logisticsType.pickup !== null) logisticsParam = { ...logisticsParam, pickup: true }
        if (logisticsType.dropoff !== null) logisticsParam = { ...logisticsParam, dropoff: true }
        if (logisticsType.non_integrated !== null) logisticsParam = { ...logisticsParam, non_integrated: true }

        return logisticsParam
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async initLogistics() {
    let result = await CustomAlert({
      title: i18next.t('title.are_you_sure'),
      text: i18next.t('text.initialise_logistics'),
      confirmButton: { text: i18next.t('button.confirm') },
      cancelButton: { text: i18next.t('button.cancel') }
    })

    if (!result.value) return

    try {
      this._validateInput()
      let response

      if (this.orderInformation.marketplaceStore.platform === PLATFORM.LAZADA.value) {
        response = await client.mutate({
          mutation: gql`
            mutation updateOrderReadyToShip($shippingProvider: String!, $deliveryType: String!, $orderNo: String!) {
              updateOrderReadyToShip(
                shippingProvider: $shippingProvider
                deliveryType: $deliveryType
                orderNo: $orderNo
              )
            }
          `,
          variables: {
            shippingProvider: this.shippingProviderInput.value,
            deliveryType: this.deliveryTypeInput.value,
            orderNo: this.orderInformation.name
          }
        })
      } else if (this.orderInformation.marketplaceStore.platform === PLATFORM.SHOPEE.value) {
        let deliveryType = {}
        if (this.logisticsTypeSelector.value === 'dropoff') {
          this.dropoffInformation && this.dropoffInformation?.dropOff && this.dropoffInformation?.dropoff?.branchId
            ? (deliveryType = this.dropoffInformation)
            : (deliveryType = { ...deliveryType, dropoff: {} })
        }

        if (this.logisticsTypeSelector.value === 'pickup') {
          deliveryType = this.pickupInformation
        }

        if (this.logisticsTypeSelector.value === 'non_integrated') {
          var trackingNo = this.trackingNoField.value
          deliveryType = {
            non_integrated: { trackingNo }
          }
        }

        response = await client.mutate({
          mutation: gql`
            mutation initialiseLogistics($deliveryType: LogisticsInit!, $orderNo: String!) {
              initialiseLogistics(deliveryType: $deliveryType, orderNo: $orderNo)
            }
          `,
          variables: {
            deliveryType,
            orderNo: this.orderInformation.name
          }
        })
      }

      if (!response.errors) {
        this.dispatchEvent(new CustomEvent('order-initialised'))
        history.back()
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _openBranchSelector() {
    openPopup(
      html`
        <branch-logistics-popup
          .orderInformation="${this.orderInformation}"
          @selected="${e => {
            var selectedBranchId = e.detail.branchId
            var data = {
              branchId: selectedBranchId
            }

            this.dropoffInformation = {
              dropoff: { branchId: selectedBranchId }
            }
            this._fillupMOForm(data)
          }}"
        ></branch-logistics-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.branch_logistics')
      }
    )
  }

  _openAddressSelector() {
    openPopup(
      html`
        <pickup-logistics-popup
          .orderInformation="${this.orderInformation}"
          @selected="${e => {
            var nonFormattedDate = new Date(parseInt(e.detail.timeslot.pickupDate))
            var formattedDate = this._convertDateFormat(nonFormattedDate)
            var data = {
              address: `${e.detail.addressInfo.address} ${e.detail.addressInfo.zipcode} ${e.detail.addressInfo.city}, ${e.detail.addressInfo.state}`,
              pickupDate: formattedDate
            }
            var addressId = e.detail.addressInfo.addressId
            var pickupTimeId = e.detail.timeslot.pickupTimeId
            this.pickupInformation = {
              pickup: { addressId, pickupTimeId }
            }
            this._fillupMOForm(data)
          }}"
        ></pickup-logistics-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.pickup_logistics')
      }
    )
  }

  _convertDateFormat(nonFormattedDate) {
    let formattedDate = ''
    if (nonFormattedDate) {
      const dateTime = new Date(nonFormattedDate)
      var year = dateTime.getFullYear()

      var month = (1 + dateTime.getMonth()).toString()
      month = month.length > 1 ? month : '0' + month

      var day = dateTime.getDate().toString()
      day = day.length > 1 ? day : '0' + day

      formattedDate = day + '/' + month + '/' + year
    }
    return formattedDate
  }

  _fillupMOForm(data) {
    this._fillupForm(this.marketplaceOrderForm, data)
  }

  _fillupForm(form, data) {
    for (let key in data) {
      Array.from(form.querySelectorAll('input, textarea, select')).forEach(field => {
        if (field.name === key && field.type === 'checkbox') {
          field.checked = data[key]
        } else if (field.name === key) {
          field.value = data[key]
        }
      })
    }
  }

  _validateInput() {
    if (this.orderInformation.marketplaceStore.platform === PLATFORM.LAZADA.value) {
      if (!this.shippingProviderInput.value) {
        throw new Error(i18next.t('text.shipping_provider_is_empty'))
      }

      if (!this.deliveryTypeInput.value) {
        throw new Error(i18next.t('text.delivery_type_is_empty'))
      }
    } else if (this.orderInformation.marketplaceStore.platform === PLATFORM.SHOPEE.value) {
      if (!this.logisticsTypeSelector.value) {
        throw new Error(i18next.t('text.no_selection_in_type'))
      }

      if (this._type === 'dropoff' && this.logisticsParam.dropoff.includes('branch_id')) {
        if (!this.dropOffField.value) throw new Error(i18next.t('text.branch_is_not_selected'))
      }

      if (this._type === 'pickup' && this.logisticsParam.pickup.includes('address_id')) {
        if (!this.addressField.value) throw new Error(i18next.t('text.address_is_empty'))
        if (!this.timeSlotField.value) throw new Error(i18next.t('text.pickup_date_is_empty'))
      }

      if (this._type === 'non_integrated') {
        if (!this.trackingNoField.value) throw new Error(i18next.t('text.tracking_no_is_empty'))
      }
    }
  }

  _showToast({ type, message }) {
    document.dispatchEvent(
      new CustomEvent('notify', {
        detail: {
          type,
          message
        }
      })
    )
  }
}

window.customElements.define('logistics-init-popup', LogisticsInitPopup)
