import '@things-factory/biz-ui'
import '@things-factory/grist-ui'
import '../../../components/attachment-viewer'
import '../release-extra-product-popup'
import '../../../components/popup-note'
import '../../release-order/tracking-information-popup'
import '@things-factory/component-ui'
import '@things-factory/import-ui'
import '../../../components/select-product-popup'

import gql from 'graphql-tag'
import { css, html } from 'lit-element'
import { connect } from 'pwa-helpers/connect-mixin'

import { MultiColumnFormStyles } from '@things-factory/form-ui'
import { i18next, localize } from '@things-factory/i18n-base'
import { openPopup } from '@things-factory/layout-base'
import { client, CustomAlert, navigate, PageView, store } from '@things-factory/shell'
import { CommonButtonStyles } from '@things-factory/styles'
import { isMobileDevice } from '@things-factory/utils'

import { fetchSettingRule } from '../../../../fetch-setting-value'
import { ORDER_STATUS, PICKING_STANDARD } from '../../../constants'

class B2CReleaseOrderDetail extends connect(store)(localize(i18next)(PageView)) {
  static get properties() {
    return {
      _isLmd: Boolean,
      _isCod: Boolean,
      _paidAmount: Number,
      _userType: String,
      _userRoles: Array,
      _releaseOrderNo: String,
      _roInfo: Object,
      // _template: Object,
      _ownTransport: Boolean,
      _crossDocking: Boolean,
      _ganNo: String,
      _exportOption: Boolean,
      _courierOption: Boolean,
      _packingOption: Boolean,
      roType: String,
      _orderMethod: String,
      customerBizplaceId: String,
      partnerBizplaceId: String,
      inventoryGristConfig: Object,
      inventoryData: Object,
      orderInventoryData: Object,
      _attachments: Array,
      _status: String,
      _mimetype: String,
      _doPath: String,
      _allowROAddProductSetting: Boolean,
      _releaseOrder: Object,
      _shippingOrder: Object,
      _containerArrivalDate: Date,
      _containerLeavingDate: Date,
      _beforeRemark: String,
      isUserBelongsDomain: Boolean,
      _isInBatchPicking: Boolean,

      /* Shipping Form Field */
      _contactPointId: String,
      _contactPointName: String,
      _companyName: String,
      _attentionTo: String,
      _deliveryCountry: String,
      _deliveryPostCode: Array,
      _deliveryState: String,
      _deliveryCity: String,
      _deliveryContact: String,
      _deliveryFullAddress: String,
      _selectedPostCode: String,
      _selectedDeliveryCountry: String,
      _billingCountry: String,
      _billingPostCode: Array,
      _billingState: String,
      _billingCity: String,
      _billingContact: String,
      _billingFullAddress: String,
      _selectedBillingPostCode: String,
      _deliveryAllCountry: Array,
      _containerClosureDate: Date,
      _recallOption: Boolean,

      // Refractor
      _shippingInfo: Object,
      _selectedCountry: String,
      _selectedBillingCountry: String,

      /* Tab Toggle*/
      _showReleasedOrderInfo: Boolean,
      _showShippingInfo: Boolean,
      _disableBillingAddress: Boolean,
      currentTab: Object
    }
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow-x: auto;
        }
        .container {
          flex: 1;
          display: flex;
          overflow-y: auto;
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        .guide-container {
          max-width: 30vw;
          display: flex;
          flex-direction: column;
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
        }

        .label-remind-container-departure {
          margin-left: 20px;
          width: 50%;
        }

        h2 {
          padding: var(--subtitle-padding);
          font: var(--subtitle-font);
          color: var(--subtitle-text-color);
          border-bottom: var(--subtitle-border-bottom);
        }
        .grist h2 {
          margin: var(--grist-title-margin);
          border: var(--grist-title-border);
          font: var(--grist-title-font);
          color: var(--secondary-color);
        }

        .grist h2 mwc-icon {
          vertical-align: middle;
          margin: var(--grist-title-icon-margin);
          font-size: var(--grist-title-icon-size);
          color: var(--grist-title-icon-color);
        }

        h2 + data-grist {
          padding-top: var(--grist-title-with-grid-padding);
        }

        [title] {
          margin-top: -5px;
          margin-bottom: -5px;
        }

        [options-wrap] *,
        [attachment-wrap] a * {
          vertical-align: middle;
        }
        [options-wrap] input[type='checkbox'] {
          left: 0;
        }
        [options-wrap] input[type='checkbox'] + label {
          margin-right: 20px;
          padding-left: 0;
        }
        [attachment-wrap] {
          grid-column: span 9 / auto;
        }
        [remind-wrap] {
          display: flex;
          flex-direction: row;
          grid-column: span 36 / auto;
        }
        [remind-wrap] label {
          width: 8%;
        }

        [attachment-wrap] a {
          display: block;
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          color: var(--primary-color);
          font-size: var(--fontsize-default);
        }
        [attachment-wrap] {
          margin: 0;
          padding: 0;
          list-style: none;
        }
        [attachment-wrap] a mwc-icon {
          font-size: var(--fontsize-default);
        }
        barcode-tag {
          width: 100px;
          height: 100px;
          margin: 10px;
        }
        .form-container {
          display: flex;
        }
        .form-container > form {
          flex: 1;
        }

        [hidden] {
          display: none;
        }

        .section-header {
          grid-column: span 36 / auto !important;
          text-align: left !important;
          margin-top: 10px !important;
          font-weight: 600 !important;
        }
        .quick-find-content-container {
          margin: 0 15px;
        }

        @media screen and (max-width: 480px) {
          .section-header {
            grid-column: span 12 / auto !important;
          }
          .quick-find-content-container {
            margin: 0;
          }
        }

        .header-with-checkbox {
          display: flex;
          align-self: flex-end;
          align-items: center;
          grid-column: span 36 / auto !important;
          text-align: left !important;
          margin-top: 10px !important;
          font-weight: 600 !important;
          margin-right: 2px; /* Spacing between header and checkbox */
        }

        .checkbox-container label {
          margin-left: 1px;
        }

        .checkbox-wrapper {
          margin-top: 10px;
        }

        .checkbox-wrapper::before {
          content: '('; /* Left bracket */
          margin-left: 2em;
          font-size: 0.9em; /* Adjust size as needed */
          font-weight: 100 !important;
        }

        .checkbox-wrapper::after {
          content: ')'; /* Right bracket */
          margin-left: 1em; /* Space between bracket and checkbox */
          font-size: 0.9em; /* Adjust size as needed */
          font-weight: 100 !important;
        }

        .checkbox-wrapper input[type='checkbox'] {
          width: 10px;
          height: 10px;
        }

        #matchDeliveryAddress {
          margin-top: 5px !important;
        }
      `
    ]
  }

  render() {
    const RELEASE_ORDER_TABS = {
      RELEASE_ORDER_INFO: i18next.t('label.order'),
      SHIPPING_INFO: i18next.t('label.shipment')
    }

    const orderSet = {
      [RELEASE_ORDER_TABS.RELEASE_ORDER_INFO]: {},
      [RELEASE_ORDER_TABS.SHIPPING_INFO]: {}
    }

    return html`
      <div class="quick-find-content-container">
        <quick-find-content
          id="order-items-list"
          name="quickFindContent"
          .data="${orderSet}"
          @tabChanged="${e => {
            this._tabChange(e.detail.currentTabKey)
          }}"
        ></quick-find-content>
      </div>

      <div ?hidden="${this._showReleasedOrderInfo}">
        <div class="form-container">
          <form name="releaseOrder" class="multi-column-form">
            <fieldset>
              <legend>${i18next.t('title.release_order_no')}: ${this._releaseOrderNo}</legend>

              <label>${i18next.t('label.options')}</label>
              <div options-wrap>
                <input
                  id="ownTransport"
                  type="checkbox"
                  name="lmdOption"
                  ?checked="${this._isLmd}"
                  ?disabled="${true}"
                />
                <label for="ownTransport">${i18next.t('label.lmd')}</label>

                <input type="checkbox" name="codOption" ?checked="${this._isCod}" ?disabled="${true}" />
                <label for="isCod">${i18next.t('label.cod')}</label>
              </div>

              <label>${i18next.t('label.company')}</label>
              <input name="bizplaceName" disabled />

              <label>${i18next.t('label.ref_no')}</label>
              <input name="refNo" ?readonly="${!this?._editable}" />

              <label>${i18next.t('label.ref_no_2')}</label>
              <input name="refNo2" ?readonly="${!this?._editable}" />

              <label>${i18next.t('label.ref_no_3')}</label>
              <input name="refNo3" ?readonly="${!this?._editable}" />

              <label>${i18next.t('label.release_date')}</label>
              <input name="releaseDate" type="date" ?readonly="${!this?._editable}" />

              <label ?hidden="${!this._ownTransport}">${i18next.t('label.co_no')}</label>
              <input name="collectionOrderNo" ?hidden="${!this._ownTransport}" ?readonly="${!this?._editable}" />

              <label>${i18next.t('label.tracking_no')}</label>
              <input
                name="trackingNo"
                ?disabled="${!(this._roInfo?.orderPackages?.length === 1) || this._source !== 'OTHERS'}"
                ?readonly="${!this?._editable || this._manifestedAt == true}"
              />

              <label ?hidden="${!this?._isCod}">${i18next.t('label.paid_amount')} </label>
              <input
                name="paidAmount"
                type="number"
                ?hidden="${!this?._isCod}"
                ?readonly="${!this?._editable}"
                min="0"
              />

              ${this._crossDocking
                ? html`
                    <label for="ganNo">${i18next.t('label.arrival_notice')}</label>
                    <input disabled name="ganNo" .value="${this._ganNo}" />
                  `
                : ''}
              ${this._invoiceAttachments?.length > 0
                ? html`
                    <label>${i18next.t('label.invoice')}</label>
                    <ul attachment-wrap>
                      ${(this._invoiceAttachments || []).map(
                        invoiceAttachment =>
                          html`
                            <li>
                              <a href="${location.origin}/attachment/${invoiceAttachment.path}" download
                                ><mwc-icon>attach_file</mwc-icon> ${invoiceAttachment.name}</a
                              >
                            </li>
                          `
                      )}
                    </ul>
                  `
                : ''}
              ${this._awbAttachments?.length > 0
                ? html`
                    <label>${i18next.t('label.awb')}</label>
                    <ul attachment-wrap>
                      ${(this._awbAttachments || []).map(
                        awbAttachment =>
                          html`
                            <li>
                              <a href="${location.origin}/attachment/${awbAttachment.path}" download>
                                <mwc-icon>attach_file</mwc-icon> ${awbAttachment.name}
                              </a>
                            </li>
                          `
                      )}
                    </ul>
                  `
                : ''}
            </fieldset>
          </form>

          <barcode-tag bcid="qrcode" .value=${this._releaseOrderNo} showLogo="true"></barcode-tag>
        </div>
      </div>

      <form name="shippingInfo" ?hidden="${this._showShippingInfo}" class="multi-column-form" autocomplete="off">
        <legend>${i18next.t('title.shipping_information')} (${this._releaseOrderNo})</legend>

        <label>${i18next.t('label.attention_to')}</label>
        <input name="attentionTo" .value="${this._releaseOrder.attentionTo}" ?readonly="${!this?._editable}" />

        <label>${i18next.t('label.contact')}</label>
        <input name="phone1" value="${this._releaseOrder.phone1}" />

        <!-- delivery -->

        <div class="header-with-checkbox">
          <label class="section-header">${i18next.t('label.delivery_address')}</label>
          <div class="checkbox-wrapper">
            <input
              type="checkbox"
              id="matchDeliveryAddress"
              name="matchDeliveryAddressInput"
              ?checked="${this._disableBillingAddress}"
              @change=${e => {
                this._disableBillingAddress = e.currentTarget.checked
              }}
            />

            <label for="matchDeliveryAddress">${i18next.t('label.use_as_billing_address')}</label>
          </div>
        </div>

        <label>${i18next.t('label.delivery_address_1')}</label>
        <textarea name="deliveryAddress1" .value="${this._releaseOrder.deliveryAddress1}"></textarea>

        <label>${i18next.t('label.delivery_address_2')}</label>
        <textarea name="deliveryAddress2" .value="${this._releaseOrder.deliveryAddress2}"></textarea>

        <label>${i18next.t('label.delivery_address_3')}</label>
        <textarea name="deliveryAddress3" .value="${this._releaseOrder.deliveryAddress3}"></textarea>

        <label>${i18next.t('label.delivery_address_4')}</label>
        <textarea name="deliveryAddress4" .value="${this._releaseOrder.deliveryAddress4}"></textarea>

        <label>${i18next.t('label.delivery_address_5')}</label>
        <textarea name="deliveryAddress5" .value="${this._releaseOrder.deliveryAddress5}"></textarea>

        <label>${i18next.t('label.country')}</label>
        <select
          name="country"
          @change=${e => {
            this._validateCountry(e)
          }}
        >
          ${this._deliveryAllCountry?.map(
            (country, key) =>
              html`<option value=${country.description} ?selected=${country.description === this._selectedCountry}>
                ${country.name}
              </option>`
          )}
        </select>

        <label>${i18next.t('label.zip_postal_code')}</label>
        ${this._selectedCountry !== 'MY'
          ? html` <input name="postalCode" .value="" /> `
          : html`<select
              name="postalCode"
              @change=${e => {
                this._getStateAndCityByPostCode(e.target.value, e.target.name)
              }}
              value=${this?._selectedPostCode || ''}
            >
              <option value=""></option>
              ${this._deliveryPostCode.map(
                (country, key) =>
                  html`<option
                    ?selected=${(this._selectedPostCode.length > 0
                      ? this._selectedPostCode
                      : this._releaseOrder.postalCode) == country.postalCode}
                    value=${country.postalCode}
                  >
                    ${country.postalCode}
                  </option>`
              )}
            </select>`}

        <label>${i18next.t('label.state')}</label>
        <input name="state" .value="${this._releaseOrder.state}" />

        <label>${i18next.t('label.city')}</label>
        <input name="city" .value="${this._releaseOrder.city}" />

        <!-- billing -->

        <label ?hidden=${this._disableBillingAddress} class="section-header"
          >${i18next.t('label.billing_address')}</label
        >

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.billing_address_1')}</label>
        <textarea
          ?hidden=${this._disableBillingAddress}
          name="billingAddress"
          .value="${this._releaseOrder.billingAddress}"
        ></textarea>

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.billing_address_2')}</label>
        <textarea
          ?hidden=${this._disableBillingAddress}
          name="billingAddress2"
          .value="${this._releaseOrder.billingAddress2}"
        ></textarea>

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.billing_address_3')}</label>
        <textarea
          ?hidden=${this._disableBillingAddress}
          name="billingAddress3"
          .value="${this._releaseOrder.billingAddress3}"
        ></textarea>

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.billing_address_4')}</label>
        <textarea
          ?hidden=${this._disableBillingAddress}
          name="billingAddress4"
          .value="${this._releaseOrder.billingAddress4}"
        ></textarea>

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.billing_address_5')}</label>
        <textarea
          ?hidden=${this._disableBillingAddress}
          name="billingAddress5"
          .value="${this._releaseOrder.billingAddress5}"
        ></textarea>

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.country')}</label>
        <select
          ?hidden=${this._disableBillingAddress}
          name="billingCountry"
          ?disabled="${this._disableBillingAddress}"
          @change=${e => {
            this._validateBillingCountry(e)
          }}
        >
          ${this._deliveryAllCountry.map(
            (country, key) =>
              html`<option
                value=${country.description}
                ?selected=${country.description === this._selectedBillingCountry}
              >
                ${country.name}
              </option>`
          )}
        </select>

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.zip_postal_code')}</label>

        ${this._selectedBillingCountry !== 'MY'
          ? html`
              <input
                ?hidden=${this._disableBillingAddress}
                name="billingPostalCode"
                .value=${this._releaseOrder.billingPostalCode || this._releaseOrder.postalCode}
              />
            `
          : html`<select
              ?hidden="${this._disableBillingAddress}"
              name="billingPostalCode"
              @change=${e => {
                this._getStateAndCityByPostCode(e.target.value, e.target.name)
              }}
              value=${this._releaseOrder.billingPostalCode || this._releaseOrder.postalCode}
            >
              <option value=""></option>

              ${this._billingPostCode.map(
                (country, key) =>
                  html`<option
                    ?selected=${(this._releaseOrder.billingPostalCode || this._releaseOrder.postalCode) ==
                    country.postalCode}
                    value=${country.postalCode}
                  >
                    ${country.postalCode}
                  </option>`
              )}
            </select>`}

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.state')}</label>
        <input ?hidden=${this._disableBillingAddress} name="billingState" .value="${this._releaseOrder.billingState}" />

        <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.city')}</label>
        <input ?hidden=${this._disableBillingAddress} name="billingCity" .value="${this._releaseOrder.billingCity}" />
      </form>

      <div class="container" ?hidden=${!this._showShippingInfo}>
        <div class="grist">
          <!-- release product list-->
          <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.release_product_list')}</h2>
          <data-grist
            id="inventory-grist"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.inventoryGristConfig}
            .data=${this.inventoryData}
          ></data-grist>
        </div>
      </div>
    `
  }

  constructor() {
    super()
    this._clearPage()
    this._deliveryAllCountry = []
    this._editable = false
    this._disableTransport = false
    this._shippingOrder = null
    this._showReleasedOrderInfo = false
    this._showShippingInfo = true
    this._attentionTo = ''
    this._source = ''
    this._manifestedAt = false
    this._companyName = ''
    this._deliveryPostCode = []
    this._deliveryState = ''
    this._deliveryCity = ''
    this._deliveryFullAddress = ''
    this._deliveryContact = ''
    this._billingPostCode = []
    this._billingState = ''
    this._billingCity = ''
    this._billingFullAddress = ''
    this._billingContact = ''
    this._selectedPostCode = ''
    this._selectedBillingPostCode = ''
    this._disableBillingAddress = true
    this.currentTab = {
      selected: 'order'
    }
    this._containerClosureDate = ''
  }

  _openTrackingInformation() {
    openPopup(
      html`
        <tracking-information-popup
          .releaseGoodId="${this._roInfo.id}"
          .bizplaceId="${this.partnerBizplaceId}"
        ></tracking-information-popup>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: i18next.t('title.tracking_information')
      }
    )
  }

  get context() {
    var actions = [
      {
        title: i18next.t('button.back_to_list'),
        action: () => navigate(`b2c_order_requests`),
        ...CommonButtonStyles.back
      }
    ]

    if (this._roInfo?.orderPackages?.length) {
      actions.push({
        title: i18next.t('button.tracking_no'),
        action: this._openTrackingInformation.bind(this),
        ...CommonButtonStyles.arrived
      })
    }

    if (this.isUserBelongsDomain) {
      if (this._status === ORDER_STATUS.PENDING_RECEIVE.value && !this._crossDocking) {
        actions.push(
          {
            title: i18next.t('button.reject'),
            action: this._rejectReleaseOrder.bind(this),
            ...CommonButtonStyles.reject
          },
          {
            title: i18next.t('button.receive'),
            action: this._receiveReleaseOrder.bind(this),
            ...CommonButtonStyles.confirm
          }
        )
      }

      if (this._status === ORDER_STATUS.PENDING_CANCEL.value && !this._crossDocking) {
        actions.push(
          {
            title: i18next.t('button.approve_cancellation'),
            action: this._confirmCancellationReleaseOrder.bind(this),
            ...CommonButtonStyles.cancel
          },
          {
            title: i18next.t('button.reject_cancellation'),
            action: this._rejectCancellationReleaseOrder.bind(this),
            ...CommonButtonStyles.reject
          }
        )
      }

      if (this._status === ORDER_STATUS.PENDING_WORKSHEET.value && !this._crossDocking) {
        actions.push({
          title: i18next.t('button.generate_picking_worksheet'),
          action: this._generateSinglePickingWorksheet.bind(this),
          ...CommonButtonStyles.generate
        })
      }

      if (this._crossDocking) {
        const params = new URLSearchParams()
        params.append('name', this._ganNo)
        actions.push({
          title: i18next.t('button.move_to_x', { state: { x: i18next.t('title.arrival_notice') } }),
          action: () => navigate(`arrival_notices?${params.toString()}`)
        })
      }

      if (this._editable) {
        actions.push({
          title: i18next.t('button.update_order_details'),
          action: this._updateReleaseGoodDetails.bind(this),
          ...CommonButtonStyles.add
        })
      }

      let addProductStatus = [ORDER_STATUS.PICKING.value, ORDER_STATUS.LOADING.value]
      if (
        addProductStatus.indexOf(this._status) >= 0 &&
        this._allowROAddProductSetting &&
        !this._isInBatchPicking &&
        this.roType !== 'b2c'
      ) {
        actions.push({
          title: i18next.t('button.edit'),
          action: this._openExtraProductPopup.bind(this),
          ...CommonButtonStyles.edit
        })
      }
    }

    if (this._status === ORDER_STATUS.PENDING.value) {
      actions.push(
        {
          title: i18next.t('button.delete'),
          action: this._deleteReleaseOrder.bind(this),
          ...CommonButtonStyles.delete
        },
        {
          title: i18next.t('button.confirm'),
          action: this._confirmReleaseOrder.bind(this),
          ...CommonButtonStyles.confirm
        }
      )
    }

    let cancelOrderStatus = [
      ORDER_STATUS.PICKING.value,
      ORDER_STATUS.PENDING_WORKSHEET.value,
      ORDER_STATUS.READY_TO_PICK.value,
      ORDER_STATUS.LOADING.value
    ]

    if (cancelOrderStatus.indexOf(this._status) >= 0) {
      actions.push({
        title: i18next.t('button.cancel_order'),
        action: this._submitCancellationReleaseOrder.bind(this),
        ...CommonButtonStyles.cancel
      })
    }

    return {
      title: i18next.t('title.release_order_detail'),
      actions,
      printable: {
        accept: ['preview'],
        content: this
      }
    }
  }

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

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

  get _containerClosureDateInput() {
    return this.shadowRoot.querySelector('input[name=containerClosureDate]')
  }

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

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

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

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

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

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

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

  get _ownTransportInput() {
    return this.shadowRoot.querySelector('input[name=ownTransport]')
  }

  get _warehouseTransportInput() {
    return this.shadowRoot.querySelector('input[name=warehouseTransport]')
  }

  get _remarkInput() {
    return this.shadowRoot.querySelector('textarea[name=remark]')
  }

  get _exportInput() {
    return this.shadowRoot.querySelector('input[name=exportOption]')
  }

  get _containerArrivalDateInput() {
    return this.shadowRoot.querySelector('input[name=containerArrivalDate]')
  }

  get _containerLeavingDateInput() {
    return this.shadowRoot.querySelector('input[name=containerLeavingDate]')
  }

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

  get matchDeliveryAddressInput() {
    return this.shadowRoot?.querySelector('input[name=matchDeliveryAddressInput]')
  }

  get _cityInput() {
    return this.shadowRoot.querySelector('input[name=city]')
  }

  get _stateInput() {
    return this.shadowRoot.querySelector('input[name=state]')
  }

  get _cityBillingInput() {
    return this.shadowRoot.querySelector('input[name=billingCity]')
  }

  get _stateBillingInput() {
    return this.shadowRoot.querySelector('input[name=billingState]')
  }

  get deliveryCountryInput() {
    return this.shadowRoot?.querySelector('select[name=country]')
  }

  get deliveryPostalCodeSelectInput() {
    return this.shadowRoot?.querySelector('select[name=postalCode]')
  }

  get deliveryPostalCodeInput() {
    return this.shadowRoot?.querySelector('input[name=postalCode]')
  }

  get deliveryStateInput() {
    return this.shadowRoot?.querySelector('input[name=state]')
  }

  get deliveryCityInput() {
    return this.shadowRoot?.querySelector('input[name=city]')
  }

  get deliveryAddressInput() {
    return this.shadowRoot?.querySelector('textarea[name=deliveryAddress1]')
  }

  get deliveryContactInput() {
    return this.shadowRoot?.querySelector('input[name=phone1]')
  }

  get billingCountryInput() {
    return this.shadowRoot?.querySelector('select[name=billingCountry]')
  }

  get billingPostalCodeSelectInput() {
    return this.shadowRoot?.querySelector('select[name=billingPostalCode]')
  }

  get billingPostalCodeInput() {
    return this.shadowRoot?.querySelector('input[name=billingPostalCode]')
  }

  get billingStateInput() {
    return this.shadowRoot?.querySelector('input[name=billingState]')
  }

  get billingCityInput() {
    return this.shadowRoot?.querySelector('input[name=billingCity]')
  }

  get billingAddressInput() {
    return this.shadowRoot?.querySelector('textarea[name=billingAddress]')
  }

  get attentionToInput() {
    return this.shadowRoot?.querySelector('input[name=attentionTo]')
  }

  get paidAmountInput() {
    return this.shadowRoot?.querySelector('input[name=paidAmount]')
  }

  async pageUpdated(changes) {
    if (this.active) {
      if (changes.resourceId) {
        this._releaseOrderNo = changes.resourceId
      }
      this._clearPage()

      if (this._releaseOrderNo) {
        await this._fetchReleaseOrder(this._releaseOrderNo)
        this.updateContext()
      }
    }
  }

  async pageInitialized() {
    await this._getAllPostCode()
    await this.fetchCountry()

    this.isUserBelongsDomain = await this._checkUserBelongsDomain()
    let [allowROAddProductSetting, userRoles] = [fetchSettingRule('allow-ro-add-product'), this.fetchUserRoleHandler()]
    let [enableTransportationServiceSetting] = await Promise.all([fetchSettingRule('enable-transportation-service')])

    this._enableTransportationServiceSetting = enableTransportationServiceSetting

    this._clearPage()

    this.inventoryGristConfig = {
      pagination: { infinite: true },
      rows: { selectable: { multiple: true }, appendable: false },
      list: { fields: ['sku', 'productName', 'batchId', 'invStatus', 'packingType', 'releaseQty', 'releaseUomValue'] },
      columns: [
        { name: 'releaseUomValue', hidden: true },
        { name: 'remainUomValue', hidden: true },
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'boolean',
          name: 'invStatus',
          header: i18next.t('field.missing'),
          imex: { header: i18next.t('field.missing'), key: 'invStatus', width: 20, type: 'string' },
          sortable: true,
          width: 100
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 100
        },
        {
          type: 'string',
          name: 'productSKU',
          header: i18next.t('field.sku'),
          width: 100
        },
        {
          type: 'string',
          name: 'productName',
          header: i18next.t('field.product'),
          width: 150
        },
        {
          type: 'string',
          name: 'productBrand',
          header: i18next.t('field.brand'),
          width: 100
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 150
        },
        {
          type: 'number',
          name: 'packingSize',
          header: i18next.t('field.packing_size'),
          width: 140
        },
        {
          type: 'float',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          width: 130
        },
        {
          type: 'string',
          name: 'releaseUomValueWithUom',
          header: i18next.t('field.release_uom_value'),
          width: 150
        },
        {
          type: 'string',
          name: 'roundedUomValue',
          header: i18next.t('field.rounded_uom_value'),
          width: 150
        },
        {
          type: 'string',
          name: 'batchIdRef',
          header: i18next.t('field.batch_no_ref'),
          width: 100
        }
      ]
    }
    this._allowROAddProductSetting = await allowROAddProductSetting
    this._userRoles = await userRoles
  }

  async _fetchReleaseOrder() {
    if (!this._releaseOrderNo) return
    const response = await client.query({
      query: gql`
        query releaseGoodDetail($name: String!) {
          releaseGoodDetail(name: $name) {
            id
            name
            truckNo
            type
            attentionTo
            attentionCompany
            phone1
            deliveryAddress1
            deliveryAddress2
            deliveryAddress3
            deliveryAddress4
            deliveryAddress5
            billingAddress
            billingAddress2
            billingAddress3
            billingAddress4
            billingAddress5
            billingCity
            billingCountry
            billingPostalCode
            billingState
            city
            state
            postalCode
            country
            remark
            source
            bizplace {
              id
              name
            }
            orderMethod
            invStatus
            status
            refNo
            refNo2
            refNo3
            lmdOption
            codOption
            paidAmount
            crossDocking
            arrivalNotice {
              name
            }
            exportOption
            courierOption
            packingOption
            recall
            releaseDate
            collectionOrderNo
            invoiceAttachment {
              id
              name
              refBy
              path
              mimetype
            }
            awbAttachment {
              id
              name
              refBy
              path
              mimetype
            }
            bizplace {
              id
              name
              description
            }
            orderPackages {
              id
              name
              trackingNo
              manifestedAt
            }
            orderProducts {
              id
              name
              batchId
              batchIdRef
              packingType
              packingSize
              product {
                id
                sku
                brand
                name
                description
              }
              productDetail {
                id
                name
              }
              productBundle {
                name
                description
                sku
              }
              uom
              releaseQty
              releaseUomValue
              status
            }
            inventoryInfos {
              id
              name
              batchId
              batchIdRef
              palletId
              product {
                id
                sku
                brand
                name
                description
              }
              productDetail {
                id
              }
              productName
              packingType
              packingSize
              qty
              lockedQty
              lockedUomValue
              uomValue
              releaseQty
              releaseUomValue
              uom
              location {
                id
                name
              }
              status
              refWorksheetId
            }
            shippingOrderInfo {
              id
              containerNo
              containerLeavingDate
              containerArrivalDate
              containerClosureDate
              containerSize
              remindContainerDeparture
              shipName
              remark
            }
          }
        }
      `,
      variables: { name: this._releaseOrderNo }
    })

    if (!response.errors) {
      const releaseOrder = response.data.releaseGoodDetail
      const shippingOrder = releaseOrder.shippingOrderInfo
      const orderPackages = releaseOrder.orderPackages
      const orderProducts = releaseOrder.orderProducts.map(op => {
        let roundedUomValue = parseFloat(op.releaseUomValue.toFixed(3))
        return {
          ...op,
          productSKU: op?.product?.sku || op?.productBundle?.sku || '',
          productName: op?.product?.name
            ? `${op?.product?.name} (${op?.product?.description})`
            : op?.productBundle?.name
            ? `${op?.productBundle?.name} (${op?.productBundle?.description})`
            : '',
          productBrand: op?.product?.brand || '',
          roundedUomValue: `${roundedUomValue} ${op.uom}`,
          releaseUomValueWithUom: op.releaseUomValue + ' ' + op.uom
        }
      })

      this._isLmd = response.data.releaseGoodDetail.lmdOption
      this._isCod = response.data.releaseGoodDetail.codOption
      this._roInfo = releaseOrder
      this.roType = releaseOrder.type
      this._orderMethod = releaseOrder.orderMethod
      this._source = releaseOrder.source
      this._manifestedAt = orderPackages.some(op => op.manifestedAt)
      this._isInBatchPicking = releaseOrder.inventoryInfos.some(inventoryInfo => inventoryInfo.refWorksheetId)
      const orderInventories = releaseOrder.inventoryInfos.map(inventoryInfo => {
        let roundedUomValue = parseFloat(inventoryInfo.releaseUomValue.toFixed(3))
        return {
          ...inventoryInfo,
          productSKU: inventoryInfo?.product?.sku || '',
          productBrand: inventoryInfo?.product?.brand || '',
          inventory: {
            id: inventoryInfo.id,
            name: inventoryInfo.name,
            palletId: inventoryInfo.palletId,
            product: inventoryInfo.product,
            productDetail: inventoryInfo.productDetail,
            batchId: inventoryInfo.batchId,
            batchIdRef: inventoryInfo.batchIdRef,
            location: inventoryInfo.location,
            packingType: inventoryInfo.packingType,
            remainQty: inventoryInfo.qty,
            remainUomValue: inventoryInfo.uomValue,
            releaseUomValue: inventoryInfo.releaseUomValue,
            releaseUomValueWithUom: inventoryInfo.releaseUomValue + ' ' + inventoryInfo.uom
          },
          qty: inventoryInfo.qty,
          remainQty: inventoryInfo.qty - inventoryInfo.lockedQty,
          uomValue: inventoryInfo.uomValue, //total
          releaseUomValue: inventoryInfo.releaseUomValue,
          remainUomValue: inventoryInfo.uomValue - inventoryInfo.lockedUomValue,
          availableUomValueWithUom: `${inventoryInfo.uomValue /*+ inventoryInfo.releaseUomValue*/} ${
            inventoryInfo.uom
          }`, //total
          releaseUomValueWithUom: inventoryInfo.releaseUomValue + ' ' + inventoryInfo.uom,
          remainUomValueWithUom: `${inventoryInfo.uomValue - inventoryInfo.releaseUomValue} ${inventoryInfo.uom}`,
          status: inventoryInfo.status,
          invStatus: inventoryInfo.status == 'MISSING',
          existing: true,
          roundedUomValue: `${roundedUomValue} ${inventoryInfo.uom}`,
          addableQty: inventoryInfo.qty - inventoryInfo.lockedQty,
          addableUomValue: inventoryInfo.uomValue - inventoryInfo.lockedUomValue
        }
      })

      this._releaseOrder = {
        ...releaseOrder
      }

      this._releaseOrderId = releaseOrder.id
      this.partnerBizplaceId = releaseOrder.bizplace.id
      this._exportOption = releaseOrder.exportOption
      this._recallOption = releaseOrder.recall

      this._beforeRemark = releaseOrder?.remark
      this._courierOption = releaseOrder.courierOption
      this._packingOption = releaseOrder.packingOption
      this._crossDocking = releaseOrder?.crossDocking

      if (
        releaseOrder?.postalCode === releaseOrder?.billingPostalCode &&
        releaseOrder?.billingAddress === releaseOrder.deliveryAddress1 &&
        releaseOrder?.billingAddress2 === releaseOrder.deliveryAddress2 &&
        releaseOrder?.billingAddress3 === releaseOrder.deliveryAddress3 &&
        releaseOrder?.billingAddress4 === releaseOrder.deliveryAddress4 &&
        releaseOrder?.billingAddress5 === releaseOrder.deliveryAddress5
      ) {
        this._disableBillingAddress = true
      } else {
        this._disableBillingAddress = false
      }

      await this.updateComplete

      this._ganNo = releaseOrder?.arrivalNotice?.name
      this._status = releaseOrder.status

      this._fillupRGForm({
        ...releaseOrder,
        bizplaceName: releaseOrder.bizplace?.name,
        trackingNo: orderPackages.length > 0 ? orderPackages.map(op => op.trackingNo).join(', ') : ''
      })

      this._fillupDAForm(releaseOrder)

      if (this._exportOption) {
        this._ownTransport = true
        this._ownTransportInput.checked = true
      } else if (!this._exportOption) {
        this._ownTransport = releaseOrder.ownTransport
      }

      if (releaseOrder && releaseOrder?.invoiceAttachment) {
        this._invoiceAttachments = [releaseOrder && releaseOrder.invoiceAttachment]
      }

      if (releaseOrder && releaseOrder?.awbAttachment) {
        this._awbAttachments = [releaseOrder && releaseOrder.awbAttachment]
      }

      const nonEditableStatus = ['DONE', 'PACKING', 'PICKING', 'READY_TO_PACK']

      if (!nonEditableStatus.includes(releaseOrder.status) && this.isUserBelongsDomain) {
        this._editable = true
      } else {
        this._editable = false
      }
      this.inventoryData = {
        records: this._orderMethod == PICKING_STANDARD.SELECT_BY_PRODUCT.value ? orderProducts : orderInventories
      }
      this.orderInventoryData = {
        records: orderInventories
      }
    }
  }

  async _rejectReleaseOrder() {
    const popup = openPopup(
      html`
        <popup-note
          .title="${i18next.t('title.remark')}"
          @submit="${async e => {
            try {
              if (!e.detail.value) throw new Error(i18next.t('text.remark_is_empty'))
              const result = await CustomAlert({
                title: i18next.t('title.are_you_sure'),
                text: i18next.t('text.reject_release_order'),
                confirmButton: { text: i18next.t('button.confirm') },
                cancelButton: { text: i18next.t('button.cancel') }
              })

              if (!result.value) {
                return
              }

              if (this._crossDocking) {
                const result = await CustomAlert({
                  title: i18next.t('title.cross_docking'),
                  text: i18next.t('text.related_order_will_be_rejected'),
                  confirmButton: { text: i18next.t('button.confirm') },
                  cancelButton: { text: i18next.t('button.cancel') }
                })

                if (!result.value) return
              }

              const response = await client.mutate({
                mutation: gql`
                  mutation rejectReleaseGood($name: String!, $patch: ReleaseGoodPatch!) {
                    rejectReleaseGood(name: $name, patch: $patch) {
                      name
                    }
                  }
                `,
                variables: { name: this._releaseOrderNo, patch: { remark: e.detail.value } }
              })

              if (!response.errors) {
                navigate(`b2c_order_requests`)
                this._showToast({ message: i18next.t('text.release_order_rejected') })
              }
            } catch (e) {
              this._showToast(e)
            }
          }}"
        ></popup-note>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: i18next.t('title.reject_release_order')
      }
    )
  }

  async _receiveReleaseOrder() {
    try {
      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.accept_release_order'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) {
        return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation receiveReleaseGood($name: String!) {
            receiveReleaseGood(name: $name) {
              name
              status
            }
          }
        `,
        variables: { name: this._releaseOrderNo }
      })

      if (!response.errors) {
        this._status = response.data.receiveReleaseGood.status
        this.updateContext()
        this._showToast({ message: i18next.t('text.release_order_received') })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _confirmCancellationReleaseOrder() {
    try {
      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.you_wont_be_able_to_revert_this'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation confirmCancellationReleaseOrder($name: String!) {
            confirmCancellationReleaseOrder(name: $name)
          }
        `,
        variables: { name: this._releaseOrderNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.release_order_has_been_cancelled') })
        navigate(`b2c_order_requests`)
      }
    } catch (e) {
      throw e
    }
  }

  async _rejectCancellationReleaseOrder() {
    try {
      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.you_wont_be_able_to_revert_this'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation rejectCancellationReleaseOrder($name: String!) {
            rejectCancellationReleaseOrder(name: $name)
          }
        `,
        variables: { name: this._releaseOrderNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.cancellation_request_has_been_rejected') })
        navigate(`b2c_order_requests`)
      }
    } catch (e) {
      throw e
    }
  }

  async _generateSinglePickingWorksheet() {
    try {
      const response = await client.mutate({
        mutation: gql`
          mutation generateReleaseGoodWorksheet($releaseGoodNo: String!, $currentStatus: String) {
            generateReleaseGoodWorksheet(releaseGoodNo: $releaseGoodNo, currentStatus: $currentStatus) {
              pickingWorksheet {
                name
              }
            }
          }
        `,
        variables: { releaseGoodNo: this._releaseOrderNo, currentStatus: this._status }
      })

      if (!response.errors) {
        navigate('single_outbound_worksheets')
        this._showToast({ message: i18next.t('text.worksheet_has_been_generated') })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  get _isDownloadable() {
    return this._status !== ORDER_STATUS.PENDING.value
  }

  _fillupRGForm(data) {
    this._fillupForm(this.releaseOrderForm, data)
  }

  _fillupDAForm(data) {
    this._fillupForm(this.shippingInfoForm, data)
    this._selectedCountry = data.country
    this._selectedBillingCountry = data.billingCountry || data.country
    this._releaseOrder.billingPostalCode = data.billingPostalCode
  }

  _fillupForm(form, data) {
    if (form) {
      form.reset()
      for (let key in data) {
        Array.from(form.querySelectorAll('input, textarea')).forEach(field => {
          if (field.name === key && field.type === 'checkbox') {
            field.checked = data[key]
          } else if (field.name === key && field.type === 'datetime-local') {
            const datetime = Number(data[key])
            const timezoneOffset = new Date(datetime).getTimezoneOffset() * 60000
            field.value = new Date(datetime - timezoneOffset).toISOString().slice(0, -1)
          } else if (field.name === key) {
            if (data[key] instanceof Object) {
              const objectData = data[key]
              field.value = `${objectData.name} ${objectData.description ? `(${objectData.description})` : ''}`
            } else {
              field.value = data[key]
            }
          }
        })
      }
    }
  }

  _clearPage() {
    this._showReleasedOrderInfo = false
    this._showShippingInfo = true
    this._source = ''
    this._manifestedAt = false
    this._releaseOrder = {}
    this._status = null
    this.roType = ''
    this._orderMethod = PICKING_STANDARD.SELECT_BY_PRODUCT.value
    this._isInBatchPicking = false
    this._exportOption = false
    this._courierOption = false
    this._packingOption = false
    this._ownTransport = true
    this._downloadable = true
    this._beforeRemark = null
    this._attachments = []
    this._invoiceAttachments = []
    this._awbAttachments = []

    this.inventoryData = { records: [] }
    this.orderInventoryData = { records: [] }
  }

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

      if (!result.value) return

      if (this._crossDocking) {
        result = await CustomAlert({
          title: i18next.t('label.cross_docking'),
          text: i18next.t('text.related_arrival_notice_will_be_deleted'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation deleteReleaseGood($name: String!) {
            deleteReleaseGood(name: $name)
          }
        `,
        variables: { name: this._releaseOrderNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.release_order_has_been_deleted') })
        navigate(`b2c_order_requests`)
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _submitCancellationReleaseOrder() {
    try {
      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.you_wont_be_able_to_revert_this'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation pendingCancellationReleaseOrder($name: String!) {
            pendingCancellationReleaseOrder(name: $name)
          }
        `,
        variables: { name: this._releaseOrderNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.release_order_is_submitted_for_cancellation') })
        navigate(`b2c_order_requests`)
      }
    } catch (e) {
      throw e
    }
  }

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

    if (!result.value) return

    if (this._crossDocking) {
      result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.arrival_notice_will_be_confirmed'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return
    }

    try {
      const response = await client.mutate({
        mutation: gql`
          mutation confirmReleaseGood($name: String!) {
            confirmReleaseGood(name: $name) {
              name
            }
          }
        `,
        variables: { name: this._releaseOrderNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.release_order_confirmed') })
        navigate(`b2c_order_requests`)
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _checkUserBelongsDomain() {
    try {
      const response = await client.query({
        query: gql`
          query checkUserBelongsDomain {
            checkUserBelongsDomain
          }
        `
      })

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

  _openExtraProductPopup() {
    openPopup(
      html`
        <release-extra-product-popup
          .releaseGoodNo="${this._releaseOrderNo}"
          .bizplace="${this.partnerBizplaceId}"
          .existingInventoryData="${this.orderInventoryData}"
          .recall="${this._recallOption}"
          @completed="${e => {
            this._fetchReleaseOrder(this._releaseOrderNo)
            this.updateContext()
          }}"
        ></release-extra-product-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.extra_product')
      }
    )
  }

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

  async fetchUserRoleHandler() {
    const response = await client.query({
      query: gql`
        query myRoles {
          myRoles {
            id
            name
            description
          }
        }
      `
    })

    if (!response.errors?.length) {
      return response.data.myRoles
    }

    return []
  }

  async _updateReleaseGoodDetails() {
    try {
      this._paidAmount = this.paidAmountInput

      this._validateForm()

      let releaseOrder = this._getFormInfo()

      delete releaseOrder.warehouseTransport
      delete releaseOrder.bizplaceId
      delete releaseOrder.bizplaceName
      delete releaseOrder.status
      delete releaseOrder.ganNo
      delete releaseOrder.recall
      delete releaseOrder.lmdOption
      let oldResorder = this._releaseOrder

      let shippingOrderInfo = {}

      let contactPointInfo = this._serializeForm(this.shippingInfoForm)

      shippingOrderInfo = {
        ...contactPointInfo
      }

      delete shippingOrderInfo['']
      delete shippingOrderInfo.matchDeliveryAddressInput

      // If match delivery address is ticked, all the billing address info will be the same with delivery address info
      if (this._disableBillingAddress) {
        shippingOrderInfo.billingAddress = contactPointInfo.deliveryAddress1
        shippingOrderInfo.billingAddress2 = contactPointInfo.deliveryAddress2
        shippingOrderInfo.billingAddress3 = contactPointInfo.deliveryAddress3
        shippingOrderInfo.billingAddress4 = contactPointInfo.deliveryAddress4
        shippingOrderInfo.billingAddress5 = contactPointInfo.deliveryAddress5
        shippingOrderInfo.billingPostalCode = contactPointInfo.postalCode
        shippingOrderInfo.billingCity = contactPointInfo.city
        shippingOrderInfo.billingState = contactPointInfo.state
        shippingOrderInfo.billingCountry = contactPointInfo.country
      }

      let releaseOrderChanged = this._compareObjects(releaseOrder, oldResorder)
      let shippingOrderChanged = this._compareObjects(shippingOrderInfo, oldResorder)

      if (releaseOrderChanged == true || shippingOrderChanged == true) {
        releaseOrderChanged = true
      }

      if (!releaseOrderChanged) {
        throw new Error(i18next.t('text.there_is_nothing_changed'))
      }

      let afterRemarkValue
      if (releaseOrder?.remark) {
        afterRemarkValue = releaseOrder.remark = releaseOrder.remark.trimStart()
      }

      if (this.roType === 'b2c') {
        if (this._beforeRemark != null && this._beforeRemark !== afterRemarkValue) {
          if (!afterRemarkValue) {
            const remarkResult = await CustomAlert({
              title: i18next.t('title.removing_order_remark'),
              text: i18next.t('text.do_you_want_to_proceed'),
              confirmButton: { text: i18next.t('button.proceed') },
              cancelButton: { text: i18next.t('button.cancel') }
            })

            if (!remarkResult.value) return
          }
        }
      }

      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.update_release_order_details'),
        confirmButton: { text: i18next.t('button.submit') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation updateReleaseGoodDetails(
            $releaseOrder: ReleaseGoodPatch!
            $shippingOrder: ShippingOrderPatch
            $shippingOrderInfo: ShippingOrderInfoPatch
          ) {
            updateReleaseGoodDetails(
              releaseGood: $releaseOrder
              shippingOrder: $shippingOrder
              shippingOrderInfo: $shippingOrderInfo
            ) {
              id
              name
            }
          }
        `,
        variables: {
          releaseOrder: {
            ...releaseOrder,
            id: this._releaseOrderId,
            name: this._releaseOrderNo,
            ownTransport: this._importCargo ? true : this._ownTransport,
            paidAmount: parseFloat(this.paidAmountInput.value)
          },
          shippingOrder: this._exportOption ? this._serializeForm(this.exportInfoForm) : null,
          shippingOrderInfo: shippingOrderInfo ? shippingOrderInfo : null
        }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.release_order_details_updated') })
        await this._fetchReleaseOrder()
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _compareObjects(object1, object2) {
    let formChanged = false

    for (const key in object1) {
      if (object1?.orderPackages?.length > 0) {
        if (key == 'trackingNo' && object1[key] !== object2.orderPackages[0].trackingNo) {
          if (
            !(
              (object1[key] == '' || object1[key] == null) &&
              (object2.orderPackages[0].trackingNo == '' || object2.orderPackages[0].trackingNo == null)
            )
          ) {
            if (this._roInfo?.orderPackages.length === 1) {
              formChanged = true
              break
            } else {
              throw new Error(i18next.t('text.does_not_support_multi_package'))
            }
          }
        }
      } else if (object1.hasOwnProperty(key) && object1[key] !== object2[key]) {
        if (!((object1[key] == '' || object1[key] == null) && (object2[key] == '' || object2[key] == null))) {
          formChanged = true
          break
        }
      }
    }

    return formChanged
  }

  _openContactPointSelector() {
    openPopup(
      html`
        <contact-points-popup
          @selected="${e => {
            this._fillUpDeliveryInfo(e.detail)
          }}"
        ></contact-points-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_destination')
      }
    )
  }

  matchDeliveryAddress() {
    this._billingFullAddress = ''
    this._billingState = ''
    this._billingCity = ''
  }

  async _getAllPostCode() {
    try {
      const response = await client.query({
        query: gql`
          query geoAreasAllPostCode {
            geoAreasAllPostCode {
              items {
                postalCode
              }
              total
            }
          }
        `
      })

      if (!response.errors) {
        const items = response.data.geoAreasAllPostCode.items
        this._deliveryPostCode = items
        this._billingPostCode = items

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

  async _getStateAndCityByPostCode(value, name) {
    const postCode = value

    // If user select the first empty postal code, the city and state will change to empty
    if (postCode == '') {
      if (name == 'postalCode') {
        this._cityInput.value = ''
        this._stateInput.value = ''
        if (this.matchDeliveryAddressInput.value === 'on') {
          this._cityBillingInput.value = ''
          this._stateBillingInput.value = ''
          this._billingPostCode.value = ''
        }
        return
      } else if (name == 'billingPostalCode') {
        this._cityBillingInput.value = ''
        this._stateBillingInput.value = ''
        return
      }
    }

    try {
      const response = await client.query({
        query: gql`
          query geoAreasGetStateAndCityByPosCode($postCode: String!) {
            geoAreasGetStateAndCityByPosCode(postCode: $postCode) {
              stateName
              cityName
            }
          }
        `,
        variables: {
          postCode
        }
      })

      if (!response.errors) {
        const { stateName, cityName } = response.data.geoAreasGetStateAndCityByPosCode

        switch (name) {
          case 'postalCode':
            this._cityInput.value = stateName
            this._stateInput.value = cityName.toUpperCase()
            // may be deleted as the new field is hidden (previously only disable)
            // if (this.matchDeliveryAddressInput.value === 'on') {
            //   this._cityBillingInput.value = stateName
            //   this._stateBillingInput.value = cityName.toUpperCase()
            //   this._billingPostCode.value = postcode
            // }
            this._releaseOrder = { ...this._releaseOrder, city: cityName.toUpperCase(), state: stateName }
            break

          case 'billingPostalCode':
            this._releaseOrder = { ...this._releaseOrder, billingCity: cityName.toUpperCase(), billingState: stateName }

          default:
            break
        }
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async fetchCountry() {
    const response = await client.query({
      query: gql`
        query geoCountriesWithoutParam {
          geoCountriesWithoutParam {
            items {
              id
              name
              description
            }
          }
        }
      `
    })

    if (!response.error) {
      this._billingAllCountry = response.data.geoCountriesWithoutParam.items
      this._deliveryAllCountry = response.data.geoCountriesWithoutParam.items
    }
  }

  _getFormInfo() {
    let formData = this._serializeForm(this.releaseOrderForm)
    delete formData.importedOrder
    delete formData.vas

    return formData
  }

  _serializeForm(form) {
    let obj = {}
    Array.from(form.querySelectorAll('input, select, textarea')).forEach(field => {
      if (!field.hasAttribute('hidden')) {
        obj[field.name] = field.type === 'checkbox' ? field.checked : field.value
      }
    })

    return obj
  }

  _validateForm() {
    if (!this.releaseOrderForm.checkValidity()) {
      throw new Error(i18next.t('text.release_order_form_invalid'))
    }

    if (this._isCod) {
      if (!this._paidAmount.value) {
        throw new Error(i18next.t('text.paid_amount_is_empty_please_fill_in_the_data_to_proceed_creating_order'))
      }
    }

    if (this._isLmd) {
      const checkShipmentFields = (
        attentionToInput,
        postalCodeInput,
        stateInput,
        cityInput,
        addressInput,
        contactInput
      ) => {
        if (
          !attentionToInput.value &&
          !postalCodeInput.value &&
          !stateInput.value &&
          !cityInput.value &&
          !addressInput.value &&
          !contactInput.value
        ) {
          throw new Error(i18next.t('text.please_fill_in_the_shipping_information_in_shipment_tab'))
        }

        if (!attentionToInput.value) {
          throw new Error(i18next.t('text.attention_to_is_empty_please_fill_in_the_data_before_proceed_create_order'))
        }

        if (!postalCodeInput.value) {
          throw new Error(
            i18next.t('text.zip/postal_code_is_empty_please_fill_in_the_data_before_proceed_create_order')
          )
        }

        if (!stateInput.value) {
          throw new Error(i18next.t('text.state_is_empty_please_fill_in_the_data_before_proceed_create_order'))
        }

        if (!cityInput.value) {
          throw new Error(i18next.t('text.city_is_empty_please_fill_in_the_data_before_proceed_create_order'))
        }

        if (!addressInput.value) {
          throw new Error(
            i18next.t('text.delivery_address_is_empty_please_fill_in_the_data_before_proceed_create_order')
          )
        }

        if (!contactInput.value) {
          throw new Error(i18next.t('text.contact_is_empty_please_fill_in_the_data_before_proceed_create_order'))
        }
      }

      if (this.deliveryCountryInput.value == 'MY') {
        checkShipmentFields(
          this.attentionToInput,
          this.deliveryPostalCodeSelectInput,
          this.deliveryStateInput,
          this.deliveryCityInput,
          this.deliveryAddressInput,
          this.deliveryContactInput
        )
      } else {
        checkShipmentFields(
          this.attentionToInput,
          this.deliveryPostalCodeInput,
          this.deliveryStateInput,
          this.deliveryCityInput,
          this.deliveryAddressInput,
          this.deliveryContactInput
        )
      }

      if (!this.billingAddressInput.value && !this.matchDeliveryAddressInput.checked) {
        throw new Error(i18next.t('text.billing_address_is_empty_please_fill_in_the_data_before_proceed_create_order'))
      }
    }

    //    - condition: export is ticked
    if (this.shippingOrderForm) {
      if (!this.shippingOrderForm.checkValidity()) {
        throw new Error(i18next.t('text.shipping_order_form_invalid'))
      }
    }
  }

  validateDate(e) {
    let inputDate = e.currentTarget.value
    let todayDate = this._getStdDate()
    if (inputDate < todayDate) {
      this._showToast({
        message: 'Invalid date'
      })
    }
    return inputDate
  }

  checkInventoryValidity() {
    const inventories = this.inventoryGrist?.dirtyData?.records
    if (!inventories?.length) throw new Error(i18next.t('text.there_is_no_inventory'))

    if (this._pickingStd === PICKING_STANDARD.SELECT_BY_PALLET && inventories.some(record => !record?.inventory?.id))
      throw new Error(i18next.t('text.invalid_inventory'))

    if (inventories.some(record => !record.releaseQty)) throw new Error(i18next.t('text.invalid_release_qty'))
  }

  _getStdDate() {
    let date = new Date()
    date.setDate(date.getDate())
    return date.toISOString().split('T')[0]
  }

  _tabChange(key) {
    if (key == 'order') {
      this._showReleasedOrderInfo = false
      this._showShippingInfo = true
    } else if (key == 'shipment') {
      this._showReleasedOrderInfo = true
      this._showShippingInfo = false
    }
    this.updateContext()
  }

  _fillUpDeliveryInfo(data) {
    // remapping according release good table
    const remapData = {
      attentionCompany: data.companyName || '',
      attentionTo: data.name || '',
      city: data.city || '',
      state: data.state || '',
      postalCode: data.postCode || '',
      country: 'MY',
      phone1: data.phone || '',
      deliveryAddress1: data.address ? data.address : '' + data.address2 ? data.address2 : '',
      billingAddress: data.billingAddress
    }

    this._selectedPostCode = data.postCode

    this._fillupForm(this.shippingInfoForm, remapData)
  }

  _validateCountry(e) {
    if (e.target.value != 'MY') {
      this._selectedCountry = e.target.value
    } else {
      this._selectedCountry = e.target.value
    }
  }

  _validateBillingCountry(e) {
    if (e.target.value != 'MY') {
      this._selectedBillingCountry = e.target.value
    } else {
      this._selectedBillingCountry = e.target.value
    }
  }

  sortByNameField(items, nameField, nameField2) {
    if (nameField2) {
      items?.sort((a, b) => {
        if (a[nameField] == b[nameField]) {
          return a[nameField2] > b[nameField2] ? 1 : a[nameField2] < b[nameField2] ? -1 : 0
        } else {
          return a[nameField] > b[nameField] ? 1 : a[nameField] < b[nameField] ? -1 : 0
        }
      })
    } else {
      items?.sort((a, b) => (a[nameField] > b[nameField] ? 1 : a[nameField] < b[nameField] ? -1 : 0))
    }

    return items
  }
}

window.customElements.define('b2c-release-order-detail', B2CReleaseOrderDetail)
