import '@things-factory/grist-ui'
import '@things-factory/import-ui'
import '@things-factory/component-ui'
import '@things-factory/biz-ui'
import '../../outbound/transport-vehicles-popup'
import './contact-point-selector-popup'
import './transport-driver-popup'

import gql from 'graphql-tag'
import {
  css,
  html,
  LitElement
} from 'lit-element'

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

import { ORDER_STATUS } from '../../../../../operato-mms/client/pages/constants'
import { fetchSettingRule } from '../../../fetch-setting-value'

class DeliveryNotePopup extends localize(i18next)(LitElement) {
  static get properties() {
    return {
      _driverList: Array,
      _isDisabled: Boolean,
      _otherDestination: Boolean,
      _ownCollection: Boolean,
      _truckExist: Boolean,
      _truckList: Array,
      _truckNo: String,
      bizplace: Object,
      doData: Object,
      doGristConfig: Object,
      doNo: String,
      manualDo: Boolean,
      selectedCP: String,
      status: String,
      orderInfo: Object,
      contactPointInput: String,
      roNo: String,
      refNo: String,
      coNo: String,
      totalPalletQty: String,
      _transportType: Array,
      _statusOwnTransport: Boolean,
      /* Shipping Form Field */
      _contactPointId: String,
      _contactPointName: String,
      _companyName: String,
      _deliveryCountry: String,
      _deliveryPostCode: Array,
      _deliveryState: String,
      _deliveryCity: String,
      _deliveryContact: String,
      _selectedPostCode: String,
      _billingCountry: String,
      _billingPostCode: Array,
      _billingState: String,
      _billingCity: String,
      _billingContact: String,
      _selectedBillingPostCode: String,
      _selectedOwnTransport: Boolean,
      _valueOfTransportType: String,
      _showCoNumber: Boolean,
      _exportOption: Boolean,
      _selectedDeliveryCountry: String,
      _deliveryAllCountry: Array,
      _billingAllCountry: Array,
      _determineOwnCollection: String,

      //  Export Form Field

      _containerArrivalDate: Date,
      _containerLeavingDate: Date,
      _containerNo: String,
      _shipName: String,

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

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

  constructor() {
    super()
    this._deliveryAllCountry = []
    this._otherDestination = false
    this._isDisabled = true
    this._showReleasedOrderInfo = false
    this._showShippingInfo = true
    this._exportOption = false
    this._companyName = ''
    this._deliveryCountry = 'MY'
    this._deliveryPostCode = []
    this._deliveryState = ''
    this._deliveryCity = ''
    this._deliveryContact = ''
    this._billingCountry = 'MY'
    this._billingPostCode = []
    this._billingState = ''
    this._billingCity = ''
    this._billingContact = ''
    this._selectedPostCode = ''
    this._selectedBillingPostCode = ''
    this._disableBillingAddress = true
    this._selectedTransportType = ''
    this.status = ''
    this._transportType = ['Own Transport', 'Warehouse Transport']
    this._switchDeliveryCountryInput = false
    this._switchBillingCountryInput = false
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow: hidden;
          background-color: white;
        }
        .container {
          flex: 1;
          display: flex;
          overflow-y: auto;
          min-height: 20vh;
        }

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

        [export] {
          margin-top: -10px;
        }

        .grist {
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        .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);
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
        }
        h2 {
          padding: var(--subtitle-padding);
          font: var(--subtitle-font);
          color: var(--subtitle-text-color);
          border-bottom: var(--subtitle-border-bottom);
        }
        .grist h2 {
          font: var(--grist-title-font);
        }
        .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);
        }

        .content-container {
          overflow-y: auto;
        }

        [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;
          }
        }

        .new-line{
          grid-column: span 12 / auto !important;
        }

        .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: 1px;
          font-size: 0.9em; /* Adjust size as needed */
          font-weight: 100 !important;
        }

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

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

      `
    ]
  }

  async firstUpdated() {
    this._ownCollection = this.orderInfo.ownCollection
    this._truckNo = this.orderInfo.truckNo || ''
    const deliverTo = this.orderInfo.deliverTo || {}
    this.selectedCP = deliverTo.id || null
    // this.contactPointInput.value = deliverTo.contactName && deliverTo.address ? `${deliverTo.contactName}, ${deliverTo.address}` : ''
    await this.fetchCountry()
    await this._getAllPostCode()

    await this.fetchDeliveryInfo(this.manualDo)
    const roResponse = await this._fetchReleaseOrder(this.roNo)
    const doRepsonse = await this._fetchDeliveryOrder(this.doNo)

    this.totalPalletQty = doRepsonse.data.deliveryOrder.palletQty

    roResponse !== undefined
      ? roResponse.ownTransport == true
        ? (this._showCoNumber = true)
        : (this._showCoNumber = false)
      : ''

    this._isDisabled = await fetchSettingRule('disable-reusable-pallet')

    this.doGristConfig = {
      list: {
        fields: ['productName', 'batchId', 'packingType', 'releaseQty', 'releaseUomValue', 'systemRemark', 'remark']
      },
      pagination: { infinite: true },
      rows: { appendable: false },
      columns: [
        {
          type: 'string',
          name: 'productId',
          hidden: true
        },
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'productName',
          header: i18next.t('field.product'),
          width: 220
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 120
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 100
        },
        {
          type: 'integer',
          name: 'releaseQty',
          header: i18next.t('field.qty'),
          width: 80
        },
        {
          type: 'integer',
          name: 'releaseUomValue',
          header: i18next.t('field.uom_value'),
          width: 80
        },
        {
          type: 'string',
          name: 'systemRemark',
          header: i18next.t('field.system_remark'),
          width: 150
        },
        {
          type: 'string',
          name: 'remark',
          header: i18next.t('field.remark'),
          record: { editable: true },
          width: 180
        }
      ]
    }
  }

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

    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 class="content-container">
        <div ?hidden="${this._showReleasedOrderInfo}">
          <form id="input-form" name="doForm" class="multi-column-form">
            <legend>${i18next.t('title.delivery_information')} - ${this.doNo}</legend>
            <label>${i18next.t('label.delivery_date')}</label>
            <input
              name="deliveryDate"
              type="date"
              min=${this.status === ORDER_STATUS.READY_TO_DISPATCH.value
                ? `${this._getStdDate()}`
                : `${this.orderInfo.createdDate}`}
              value="${this.orderInfo.deliveryDate}"
              required
            />

            <label>${i18next.t('label.release_good_no')}</label>
            <input name="releaseGoodNo" ?disabled="${true}" value="${this.roNo}" />

            <label>${i18next.t('label.ref_no')}</label>
            <input name="refNo" ?disabled="${true}" value="${this.refNo}" />

            <label>${i18next.t('label.transport_type')}</label>
            <select
              name="transportType"
              @change=${e => {
                this._setTransportType(e.target.value, e.target.name)
              }}
            >
              ${this._transportType.map(
                (tp, key) => html`<option value=${tp} ?selected=${this._determineOwnCollection === tp}>${tp}</option>`
              )}
            </select>

            <label ?hidden="${this._showCoNumber}">${i18next.t('label.co_no')}</label>
            <input name="coNo" ?hidden="${this._showCoNumber}" value="${this.coNo}" />

            <label>${i18next.t('label.driver_name')}</label>
            <input name="otherDriver" value="${this.orderInfo.otherDriver}" ?hidden="${!this._ownCollection}" />
            <input
              name="ownDriver"
              ?hidden="${this._ownCollection}"
              value="${this.orderInfo.driverName}"
              @click="${this._openDriverSelector.bind(this)}"
              readonly
            />

            <label>${i18next.t('label.driver_code')}</label>
            <input name="otherDriverCode" value="${this.orderInfo.otherDriverCode}" ?hidden="${!this._ownCollection}" />
            <input
              name="ownDriverCode"
              ?hidden="${this._ownCollection}"
              value="${this.orderInfo.driverCode}"
              @click="${this._openDriverSelector.bind(this)}"
              readonly
            />

            <label>${i18next.t('label.vehicle_no')}</label>
            <input name="otherTruck" ?hidden="${!this._ownCollection}" value="${this._truckNo}" />
            <input
              name="ownTruck"
              readonly
              ?hidden="${this._ownCollection}"
              @click="${this._openBufferSelector.bind(this)}"
              value="${this.orderInfo.truckNo || ''}"
            />

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.contact_name')}</label>
            <input name="contactName" ?hidden="${!this._otherDestination}" />

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.contact_phone_no')}</label>
            <input
              name="contactPhone"
              ?hidden="${!this._otherDestination}"
              placeholder="(${i18next.t('text.optional')})"
            />

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.contact_email')}</label>
            <input
              name="contactEmail"
              ?hidden="${!this._otherDestination}"
              placeholder="(${i18next.t('text.optional')})"
            />

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.company_name')}</label>
            <input
              name="contactCompany"
              ?hidden="${!this._otherDestination}"
              placeholder="(${i18next.t('text.optional')})"
            />

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.contact_type')}</label>
            <select name="contactType" ?hidden="${!this._otherDestination}">
              <option value="">-- ${i18next.t('text.please_select_the_contact_type')} --</option>
              <!-- Temporarily use hardcoded value -->
              <option value="CUSTOMER">${i18next.t('text.customer')}</option>
              <option value="SUPPLIER">${i18next.t('text.supplier')}</option>
            </select>

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.delivery_address')}</label>
            <textarea name="otherDestination" ?hidden="${!this._otherDestination}"></textarea>

            <label ?hidden="${!this._otherDestination}">${i18next.t('label.billing_address')}</label>
            <textarea name="billingAddress" ?hidden="${!this._otherDestination}"></textarea>

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

            <label>${i18next.t('label.overall_remark')}</label>
            <textarea name="remark" value="${this.orderInfo.remark}">${this.orderInfo.remark}</textarea>

            <input
              id="exportOption"
              type="checkbox"
              name="exportOption"
              ?hidden=${this._determineOwnCollection == 'Warehouse Transport'}
              ?checked="${this._exportOption}"
              @change="${e => {
                this._exportOption = e.currentTarget.checked
                if (this._exportOption == true) {
                  this._exportOption = true
                  this._valueOfTransportType = 'Own Transport'
                  this._showCoNumber = false
                }
                if (this._exportOption == false) {
                  this._exportOption = false
                  this._showCoNumber = true
                  this._valueOfTransportType = 'Warehouse Transport'
                }
              }}"
            />
            <label for="exportOption" ?hidden=${this._determineOwnCollection == 'Warehouse Transport'}
              >${i18next.t('label.export')}</label
            >
          </form>
        </div>

        <div class="so-form-container" export ?hidden=${!this._exportOption}>
          <form name="shippingOrder" class="multi-column-form">
            <fieldset>
              <legend>${i18next.t('title.export_order')}</legend>
              <label>${i18next.t('label.container_no')}</label>
              <input name="containerNo" .value="${this._containerNo}" required />

              <label>${i18next.t('label.container_arrival_date')}</label>
              <input
                name="containerArrivalDate"
                type="date"
                .value="${this._containerArrivalDate}"
                @change="${e => {
                  this._containerLeavingDateInput.setAttribute('min', e.currentTarget.value)
                }}"
                required
              />

              <label>${i18next.t('label.container_leaving_date')}</label>
              <input
                name="containerLeavingDate"
                type="date"
                .value="${this._containerLeavingDate}"
                @change="${e => {
                  this._containerArrivalDateInput.setAttribute('max', e.currentTarget.value)
                }}"
                required
              />

              <label>${i18next.t('label.ship_name')}</label>
              <input name="shipName" .value="${this._shipName}" required />
            </fieldset>
          </form>
        </div>

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

          <label>${i18next.t('label.company')}</label>
          <input name="attentionCompany" .value="${this._deliveryOrder?.attentionCompany}" />

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

          <button type="button" @click="${this._openContactPointSelector.bind(this)}">import</button>

          <label>&nbsp</label>
          <label>&nbsp</label>
          <label>&nbsp</label>

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

          <!-- delivery -->
          <label class="section-header">${i18next.t('label.delivery_address')}</label>

          <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} 
                @click=${e => {
                  this._disableBillingAddress = e.currentTarget.checked;
                }}
              />
              <label for="matchDeliveryAddress">${i18next.t('label.use_as_billing_address')}</label>
            </div>
          </div>


          <label>${i18next.t('label.address_1')}</label>
          <textarea name="deliveryAddress1" required .value="${this._deliveryOrder?.deliveryAddress1}"></textarea>

          <label>${i18next.t('label.address_2')}</label>
          <textarea name="deliveryAddress2" required .value="${this._deliveryOrder?.deliveryAddress2}"></textarea>

          <label>${i18next.t('label.address_3')}</label>
          <textarea name="deliveryAddress3" required .value="${this._deliveryOrder?.deliveryAddress3}"></textarea>

          <label>${i18next.t('label.address_4')}</label>
          <textarea name="deliveryAddress4" required .value="${this._deliveryOrder?.deliveryAddress4}"></textarea>

          <label>${i18next.t('label.address_5')}</label>
          <textarea name="deliveryAddress5" required .value="${this._deliveryOrder?.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._deliveryOrder.postalCode) == country.postalCode}
                      value=${country.postalCode}
                    >
                      ${country.postalCode}
                    </option>`
                )}
              </select>`}

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

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

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

          <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.address_1')}</label>
          <textarea
            ?hidden=${this._disableBillingAddress}
            ?disabled=${this._disableBillingAddress}
            name="billingAddress"
            required
            .value="${this._deliveryOrder?.billingAddress}"
          ></textarea>

          <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.address_2')}</label>
          <textarea
            ?hidden=${this._disableBillingAddress}
            ?disabled=${this._disableBillingAddress}
            name="billingAddress2"
            required
            .value="${this._deliveryOrder?.billingAddress2}"
          ></textarea>

          <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.address_3')}</label>
          <textarea
            ?hidden=${this._disableBillingAddress}
            ?disabled=${this._disableBillingAddress}
            name="billingAddress3"
            required
            .value="${this._deliveryOrder?.billingAddress3}"
          ></textarea>

          <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.address_4')}</label>
          <textarea
            ?hidden=${this._disableBillingAddress}
            ?disabled=${this._disableBillingAddress}
            name="billingAddress4"
            required
            .value="${this._deliveryOrder?.billingAddress4}"
          ></textarea>

          <label ?hidden=${this._disableBillingAddress}>${i18next.t('label.address_5')}</label>
          <textarea
            ?hidden=${this._disableBillingAddress}
            ?disabled=${this._disableBillingAddress}
            name="billingAddress5"
            required
            .value="${this._deliveryOrder?.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}
                  ?disabled=${this._disableBillingAddress}
                  name="billingPostalCode"
                  .value=${this._deliveryOrder?.billingPostalCode}
                />
              `
            : html`<select
                ?hidden=${this._disableBillingAddress}
                ?disabled=${this._disableBillingAddress}
                name="billingPostalCode"
                @change=${e => {
                  this._getStateAndCityByPostCode(e.target.value, e.target.name)
                }}
                value=${this._deliveryOrder?.billingPostalCode}
              >
                <option value=""></option>

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

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

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

        <div class="container">
          <div class="grist">
            <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.edit_remark')}</h2>

            <data-grist
              id="do-grist"
              .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
              .config=${this.doGristConfig}
              .data=${this.doData}
            ></data-grist>
          </div>
        </div>
      </div>
      <div class="button-container">
        <mwc-button
          @click="${this._saveDeliveryInfo.bind(this)}"
          label="${this.status === ORDER_STATUS.READY_TO_DISPATCH.value
            ? `${i18next.t('button.dispatch')}`
            : `${i18next.t('button.update')}`}"
          raised
        ></mwc-button>
      </div>
    `
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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 _truckDriverInput() {
    return this.shadowRoot.querySelector('input[name=ownDriver]')
  }

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

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

  _getInputByName(name) {
    return this.shadowRoot.querySelector(`textarea[name=${name}], select[name=${name}], input[name=${name}]`)
  }

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

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

    // to set default value of contact phone, email and delivery address
    if (this._otherDestination) {
      obj = {
        ...obj,
        contactPhone: obj.contactPhone || '-',
        contactEmail: obj.contactEmail || '-',
        billingAddress: obj.billingAddress ? obj.billingAddress : obj.otherDestination
      }
    }

    return obj
  }

  _setTransportType(e, v) {
    if (e == 'Own Transport') {
      this._showCoNumber = false
      this._ownCollection = true
      this._determineOwnCollection = 'Own Transport'
      this._otherTruckInput.value = ''
      this.otherDriverInput.value = ''
    } else {
      this._showCoNumber = true
      this._exportOption = false
      this._exportOptionInput.checked = false
      this._ownCollection = false
      this._determineOwnCollection = 'Warehouse Transport'
      this._truckNoInput.value = ''
      this._truckDriverInput.value = ''
      this._truckDriverCodeInput.value = ''
    }
  }

  _openCPSelector() {
    openPopup(
      html`
        <contact-point-selector-popup
          .bizplace="${this.bizplace}"
          @selected="${e => {
            this.contactPointInput.value = `${e.detail.name}, ${e.detail.address}`
            this.selectedCP = e.detail.id
          }}"
        ></contact-point-selector-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_destination')
      }
    )
  }

  _openTruckSelector() {
    openPopup(
      html`
        <transport-vehicles-popup
          @selected="${e => {
            this._truckNoInput.value = e.detail.name
          }}"
        ></transport-vehicles-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_truck')
      }
    )
  }

  async _openBufferSelector() {
    openPopup(
      html`
        <transport-vehicles-popup
          @selected="${e => {
            this._truckNoInput.value = e.detail.name
          }}"
        ></transport-vehicles-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('label.lorry_no')
      }
    )
  }

  _openDriverSelector() {
    openPopup(
      html`
        <transport-driver-popup
          @selected="${e => {
            this._truckDriverInput.value = e.detail.name
            this._truckDriverCodeInput.value = e.detail.driverCode
          }}"
        ></transport-driver-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_driver')
      }
    )
  }

  _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')
      }
    )
  }

  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
      }
    } 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 = ''
        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 = cityName
            this._stateInput.value = stateName.toUpperCase()
            break

          case 'billingPostalCode':
            this._cityBillingInput.value = cityName
            this._stateBillingInput.value = stateName.toUpperCase()

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

  async _fetchTruckDriver() {
    const response = await client.query({
      query: gql`
        query transportDrivers($filters: [Filter!], $sortings: [Sortings!]) {
          transportDrivers(filters: $filters, sortings: $sortings) {
            items {
              id
              name
              driverCode
            }
          }
        }
      `,
      variables: {
        filters: [],
        sortings: [{ name: 'name' }]
      }
    })

    if (!response.errors) {
      return response.data.transportDrivers.items || []
    }
  }

  async _fetchTrucks() {
    const response = await client.query({
      query: gql`
        query transportVehicles($filters: [Filter!], $sortings: [Sortings!]) {
          transportVehicles(filters: $filters, sortings: $sortings) {
            items {
              id
              name
            }
          }
        }
      `,
      variables: {
        filters: [],
        sortings: [{ name: 'name' }]
      }
    })

    if (!response.errors) {
      this._truckExist = false
      const trucks = response.data.transportVehicles.items || []
      let filteredTrucks = trucks.filter(truck => truck.name != this._truckNo)

      if (trucks.length > filteredTrucks.length) this._truckExist = true
      return filteredTrucks
    }
  }

  async fetchDeliveryInfo(isManualDO) {
    let responseData = ''
    if (isManualDO) {
      const response = await client.query({
        query: gql`
          query manualDeliveryOrderItems($name: String!) {
            manualDeliveryOrderItems(name: $name) {
              items {
                releaseQty
                releaseUomValue
                status
                remark
                palletQty
                systemRemark
                batchId
                productId
                productName
                packingType
                pallet
              }
            }
          }
        `,
        variables: {
          name: this.doNo
        }
      })

      if (!response.errors) {
        this.doData = {
          records: response.data.manualDeliveryOrderItems.items || []
        }
        this.totalPalletQty = this.doData.palletQty
      }
      responseData = response
    } else {
      const response = await client.query({
        query: gql`
          query deliveryOrderItems($name: String!) {
            deliveryOrderItems(name: $name) {
              items {
                releaseQty
                releaseUomValue
                status
                remark
                palletQty
                systemRemark
                batchId
                productName
                packingType
                pallet
              }
            }
          }
        `,
        variables: {
          name: this.doNo
        }
      })

      if (!response.errors) {
        this.doData = {
          records: response.data.deliveryOrderItems.items || []
        }

        this.totalPalletQty = this.doData.palletQty
      }
      responseData = response
    }

    return responseData
  }

  async _saveDeliveryInfo() {
    try {
      let shippingOrderInfo = {}

      let contactPointInfo = this._serializeForm(this.shippingInfoForm)

      let deliveryInfo = this._getDeliveryInfo()

      let exportInfo = {}
      if (this.shippingOrderForm != null) {
        exportInfo = this._serializeForm(this.shippingOrderForm)

        if (!exportInfo.containerNo && deliveryInfo.exportOption) {
          throw new Error(i18next.t('text.container_no_is_empty'))
        }
      } else {
        exportInfo = {}
      }

      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 response = null
      if (this.manualDo) {
        response = await client.mutate({
          mutation: gql`
            mutation dispatchManualDeliveryOrder($orderInfo: DeliveryOrderPatch, $orderItems: [OrderInventoryPatch!]) {
              dispatchManualDeliveryOrder(orderInfo: $orderInfo, orderItems: $orderItems) {
                id
                name
                description
                status
              }
            }
          `,
          variables: {
            orderInfo: { ...deliveryInfo },
            orderItems: this._getOrderItems()
          }
        })
      } else {
        response = await client.mutate({
          mutation: gql`
            mutation dispatchDeliveryOrder(
              $orderInfo: DeliveryOrderPatch
              $orderItems: [OrderInventoryPatch!]
              $shippingInfo: ShippingOrderInfoPatch
              $exportInfo: ExportInformationPatch
            ) {
              dispatchDeliveryOrder(
                orderInfo: $orderInfo
                orderItems: $orderItems
                shippingInfo: $shippingInfo
                exportInfo: $exportInfo
              ) {
                id
                name
                description
                status
              }
            }
          `,
          variables: {
            orderInfo: { ...deliveryInfo },
            orderItems: this._getOrderItems(),
            shippingInfo: shippingOrderInfo ? shippingOrderInfo : null,
            exportInfo: exportInfo ? exportInfo : null
          }
        })
      }

      if (!response.errors) {
        window.history.back()
        this.dispatchEvent(new CustomEvent('delivery-dispatched'))
        if (this.status === ORDER_STATUS.READY_TO_DISPATCH.value) {
          this._showToast({ message: i18next.t('text.delivery_has_been_dispatched') })
        } else {
          this._showToast({ message: i18next.t('text.delivery_order_info_has_been_updated') })
        }
      }
    } 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
    }
  }

  async _fetchReleaseOrder(roNo) {
    if (!roNo) 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
            bizplace {
              id
              name
            }
            invStatus
            status
            refNo
            refNo2
            refNo3
            ownTransport
            crossDocking
            arrivalNotice {
              name
            }
            exportOption
            courierOption
            packingOption
            releaseDate
            collectionOrderNo
            attachment {
              id
              name
              refBy
              path
              mimetype
            }
            bizplace {
              id
              name
              description
            }
            inventoryInfos {
              id
              name
              batchId
              batchIdRef
              palletId
              product {
                id
                sku
                brand
                name
                description
              }
              productName
              packingType
              packingSize
              qty
              lockedQty
              lockedUomValue
              uomValue
              releaseQty
              releaseUomValue
              uom
              location {
                id
                name
              }
              status
            }
            shippingOrderInfo {
              id
              containerNo
              containerLeavingDate
              containerArrivalDate
              shipName
            }
            orderVass {
              vas {
                name
                operationGuide
                operationGuideType
              }
              set
              targetType
              targetBatchId
              targetProduct {
                id
                name
                description
              }
              packingType
              qty
              uomValue
              otherTarget
              description
              remark
              status
              operationGuide
            }
          }
        }
      `,
      variables: { name: roNo }
    })

    if (!response.errors) {
      const releaseOrder = response.data.releaseGoodDetail
      // shipment info
      this._companyName = releaseOrder?.attentionCompany
      this._deliveryCity = releaseOrder?.city
      this._deliveryState = releaseOrder?.state
      this._deliveryCountry = releaseOrder?.country
      this._deliveryContact = releaseOrder?.phone1
      this._selectedBillingPostCode = releaseOrder?.billingPostalCode
      this._billingCity = releaseOrder?.billingCity
      this._billingState = releaseOrder?.billingState
      this._billingCountry = releaseOrder?.billingCountry
      this._selectedOwnTransport = releaseOrder?.ownTransport
      this.coNo = releaseOrder?.collectionOrderNo
      this._containerArrivalDate = releaseOrder?.shippingOrderInfo.containerArrivalDate
      this._containerLeavingDate = releaseOrder?.shippingOrderInfo.containerLeavingDate
      this._containerNo = releaseOrder?.shippingOrderInfo.containerNo
      this._shipName = releaseOrder?.shippingOrderInfo.shipName
      this._exportOption = releaseOrder?.exportOption

      return releaseOrder
    }
  }

  async _fetchDeliveryOrder(doNo) {
    if (!doNo) return

    const response = await client.query({
      query: gql`
        query deliveryOrder($name: String!) {
          deliveryOrder(name: $name) {
            palletQty
            ownCollection
            attentionTo
            attentionCompany
            city
            state
            postalCode
            country
            phone1
            deliveryAddress1
            deliveryAddress2
            deliveryAddress3
            deliveryAddress4
            deliveryAddress5
            billingAddress
            billingAddress2
            billingAddress3
            billingAddress4
            billingAddress5
            billingCountry
            billingPostalCode
            billingState
            billingCity
          }
        }
      `,
      variables: { name: doNo }
    })

    this._ownCollection = response.data.deliveryOrder.ownCollection

    const deliveryOrder = response.data.deliveryOrder

    this._deliveryOrder = {
      ...deliveryOrder
    }

    this._fillupDAForm(deliveryOrder)

    this._fillupBLForm(deliveryOrder)

    this._fillupCPForm(deliveryOrder)

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

    if (response.data.deliveryOrder.ownCollection) {
      this._determineOwnCollection = 'Own Transport'
    } else {
      this._determineOwnCollection = 'Warehouse Transport'
    }

    return response
  }

  initProperties() {
    this._transportType = ['Own Transport', 'Warehouse Transport']
  }

  _validateDeliveryInfo() {
    let errorFields = []

    // transport field entries
    const transportFields = this._ownCollection
      ? {
          otherDriver: i18next.t('field.driver_name'),
          otherTruck: i18next.t('field.vehicle_no')
        }
      : {
          ownDriver: i18next.t('field.driver_name'),
          ownTruck: i18next.t('field.vehicle_no')
        }

    // destination field entries
    const destinationFields = this._otherDestination
      ? {
          contactName: i18next.t('field.contact_name'),
          otherDestination: i18next.t('field.delivery_address'),
          contactType: i18next.t('field.contact_type')
        }
      : {
          contactPoint: i18next.t('field.contact_point')
        }

    const validationFields = {
      ...transportFields,
      ...destinationFields
    }

    for (const [field, message] of Object.entries(validationFields)) {
      if (this._getInputByName(field).value.trim().length <= 0) {
        errorFields.push(message)
      }
    }

    if (errorFields.length === 1) {
      throw new Error(`${i18next.t('text.field')} ${errorFields.join(', ')} ${i18next.t('text.is_empty')}`)
    } else if (errorFields.length > 1) {
      throw new Error(`${i18next.t('text.fields')} ${errorFields.join(', ')} ${i18next.t('text.are_empty')}`)
    }
  }

  _getDeliveryInfo() {
    if (this.shadowRoot.querySelector('form').checkValidity()) {
      // this._validateDeliveryInfo()

      if (this._ownCollection) {
        if (this.otherDriverInput.value == '') {
          throw new Error(i18next.t('text.driver_is_empty'))
        }

        if (this.otherTruckInput.value == '') {
          throw new Error(i18next.t('text.vehicle_no_is_empty'))
        }
      } else {
        if (this._truckNoInput.value == '') {
          throw new Error(i18next.t('text.vehicle_no_is_empty'))
        }

        if (this._truckDriverInput.value == '') {
          throw new Error(i18next.t('text.driver_is_empty'))
        }
      }

      const deliveryInfo = this._serializeForm(this.doForm)
      delete deliveryInfo.otherDestBoolean

      return {
        ...deliveryInfo,
        name: this.doNo,
        contactPoint: this._otherDestination ? null : this.selectedCP,
        otherTruck:
          this._ownCollection && deliveryInfo.otherTruck
            ? deliveryInfo.otherTruck.toUpperCase().replace(/\s+/g, '')
            : null
      }
    } else {
      throw new Error(i18next.t('text.delivery_info_not_valid'))
    }
  }

  _getOrderItems() {
    if (this.doGrist.dirtyData && this.doGrist.dirtyData.records && this.doGrist.dirtyData.records.length > 0) {
      return this.doGrist.dirtyData.records.map(record => {
        let newRecord = {
          productId: record.productId || '',
          pallet: record.pallet,
          productName: record.productName,
          releaseQty: record.releaseQty,
          releaseUomValue: record.releaseUomValue,
          batchId: record.batchId,
          packingType: record.packingType,
          remark: record?.remark ? record.remark : ''
        }
        return newRecord
      })
    }
  }

  async _tabChange(key) {
    if (key == 'order') {
      this._showReleasedOrderInfo = false
      this._showShippingInfo = true
      this.initProperties()
    } else {
      await this._getAllPostCode()
      this._showReleasedOrderInfo = true
      this._showShippingInfo = false
      this._exportOption = false
    }
  }

  _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)
  }

  _resetShippingInfoForm() {
    this.getContactPointForm.reset()
  }

  _fillupForm(form, data) {
    if (form) {
      form.reset()
      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.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]
            }
          }
        })
      }
    }
  }

  _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
    }
  }

  _fillupDAForm(data) {
    this._fillupForm(this.deliveryAddressForm, data)
    this._selectedCountry = data.country || 'MY'
    this._deliveryOrder.postalCode = data.postalCode
  }

  _fillupBLForm(data) {
    this._fillupForm(this.billingAddressForm, data)
    this._selectedBillingCountry = data.billingCountry || 'MY'
    this._deliveryOrder.billingPostalCode = data.billingPostalCode
  }

  _fillupCPForm(data) {
    this._fillupForm(this.contactPointForm, data)
  }

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

    return obj
  }

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

window.customElements.define('delivery-note-popup', DeliveryNotePopup)