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

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

import { getCodeByName } from '@things-factory/code-base'
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
} from '@things-factory/shell'
import { CommonButtonStyles } from '@things-factory/styles'
import { isMobileDevice } from '@things-factory/utils'

import { fetchSettingRule } from '../../../fetch-setting-value'

class CreateDeliveryOrder extends localize(i18next)(PageView) {
  static get properties() {
    return {
      /**
       * @description
       * flag for whether use transportation from warehouse or not.
       * true =>
       */
      _bizplaces: Object,
      _bizplaceId: String,
      _bizplaceName: String,
      _checkTransport: Boolean,
      _disableTransport: Boolean,
      _enableTransportationServiceSetting: Boolean,
      _enableTransportForCustomClearanceSetting: Boolean,
      _files: Array,
      _otherDestination: Boolean,
      _ownCollection: Boolean,
      _showOtherDestination: Boolean,
      _showOwnCollectionField: Boolean,
      _showWarehouseTransportField: Boolean,
      _transportDriver: String,
      _transportVehicle: String,
      _warehouseTransport: Boolean,
      contactPointInput: String,
      productData: Object,
      productGristConfig: Object,
      selectedCP: String
    }
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow-x: auto;
        }
        .container {
          flex: 1;
          display: flex;
          overflow: hidden;
          min-height: 50vh;
        }
        [options-wrap] {
          grid-column: span 21 / auto;
        }
        [options-wrap] * {
          vertical-align: middle;
        }
        [options-wrap] input[type='checkbox'] {
          left: 0;
        }
        [options-wrap] input[type='checkbox'] + label {
          margin-right: 20px;
          padding-left: 0;
        }
        [attachment-wrap] {
          display: flex;
          flex-direction: row;
          grid-column: span 24;
        }
        [attachment-wrap] label {
          width: 8%;
        }
        [attachment-wrap] file-uploader {
          flex: 1;
          margin: 0 var(--margin-wide) 0 var(--margin-narrow);
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
        }
        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);
        }

        [hidden] {
          display: none;
        }
        @media screen and (max-width: 460px) {
          [attachment-wrap] {
            grid-column: span 12;
          }
        }
        @media screen and (min-width: 1201px) and (max-width: 2000px) {
          [options-wrap] {
            grid-column: span 33 / auto;
          }
          [attachment-wrap] {
            grid-column: span 36;
          }
        }
        @media screen and (min-width: 2001px) {
          [options-wrap] {
            grid-column: span 45 / auto;
          }
          [attachment-wrap] {
            grid-column: span 48;
          }
          [attachment-wrap] label {
            width: 6%;
          }
        }
      `
    ]
  }

  get context() {
    return {
      title: i18next.t('title.create_delivery_order'),
      actions: [
        {
          title: i18next.t('button.submit'),
          action: this._createDeliveryOrder.bind(this),
          ...CommonButtonStyles.submit
        }
      ],
      help: 'operato-wms/transport-order/create-delivery-order'
    }
  }

  render() {
    return html`
      <form name="deliveryOrder" class="multi-column-form" autocomplete="off">
        <fieldset>
          <legend>${i18next.t('title.delivery_order')}</legend>

          <label>${i18next.t('label.options')}</label>
          <div options-wrap>
            <input
              id="ownCollection"
              type="checkbox"
              name="ownCollection"
              ?checked="${this._ownCollection}"
              ?disabled="${this._disableTransport}"
              @change="${e => {
                this._ownCollection = e.currentTarget.checked
                if (this._ownCollection) {
                  this._warehouseTransportInput.checked = false
                  this._warehouseTransport = false
                } else {
                  this._warehouseTransportInput.checked = true
                  this._warehouseTransport = true
                }
                this._fieldsToggle()
              }}"
            />
            <label for="ownCollection">${i18next.t('label.own_transport')}</label>

            <input
              id="warehouseTransport"
              type="checkbox"
              name="warehouseTransport"
              ?disabled="${this._disableTransport}"
              ?checked="${this._warehouseTransport}"
              @change="${e => {
                this._warehouseTransport = e.currentTarget.checked
                if (this._warehouseTransport) {
                  this._ownCollectionInput.checked = false
                  this._ownCollection = false
                } else {
                  this._ownCollectionInput.checked = true
                  this._ownCollection = true
                }
                this._fieldsToggle()
              }}"
            />
            <label for="warehouseTransport">${i18next.t('label.warehouse_transport')}</label>

            <input
              id="otherDestBoolean"
              name="otherDestBoolean"
              type="checkbox"
              ?checked="${this._otherDestination}"
              ?hidden="${!this._checkTransport}"
              @change="${e => {
                this._otherDestination = e.currentTarget.checked
                this._showOtherDestination = e.currentTarget.checked
              }}"
            />
            <label for="otherDestBoolean" ?hidden="${!this._checkTransport}"
              >${i18next.t('label.other_destination')}</label
            >
          </div>
        </fieldset>

        <label ?hidden="${!this._checkTransport}">${i18next.t('label.company')}</label>
        <input
          readonly
          type="text"
          name="bizplaceName"
          value="${this._bizplaceName}"
          ?hidden="${!this._checkTransport}"
          @click="${this._openBizplacesSelector.bind(this)}"
        />
        <label ?hidden="${!this._checkTransport}">${i18next.t('label.ref_no')}</label>
        <input name="refNo" ?hidden="${!this._checkTransport}" />

        <label ?hidden="${!this._checkTransport}">${i18next.t('label.delivery_date')}</label>
        <input name="deliveryDate" type="date" ?hidden="${!this._checkTransport}" required />

        <label ?hidden="${!this._checkTransport}">${i18next.t('label.driver_name')}</label>
        <input name="ownDriver" value="" ?hidden="${!this._showOwnCollectionField}" />
        <input
          name="warehouseDriver"
          ?hidden="${!this._showWarehouseTransportField}"
          readonly
          @click="${this._openDriverSelector.bind(this)}"
        />

        <label ?hidden="${!this._checkTransport}">${i18next.t('label.driver_code')}</label>
        <input name="ownDriverCode" value="" ?hidden="${!this._showOwnCollectionField}" />
        <input
          name="warehouseDriverCode"
          ?hidden="${!this._showWarehouseTransportField}"
          readonly
          @click="${this._openDriverSelector.bind(this)}"
        />

        <label ?hidden="${!this._checkTransport}">${i18next.t('label.truck_no')}</label>
        <input name="ownTruck" ?hidden="${!this._showOwnCollectionField}" />
        <input
          readonly
          name="warehouseTruck"
          ?hidden="${!this._showWarehouseTransportField}"
          @click="${this._openTruckSelector.bind(this)}"
        />

        <label ?hidden="${this._showOtherDestination}">${i18next.t('label.delivery_address')}</label>
        <input
          readonly
          name="contactPoint"
          ?hidden="${this._showOtherDestination}"
          @click="${this._openCPSelector.bind(this)}"
        />

        <label ?hidden="${!this._checkTransport}">${i18next.t('label.overall_remark')}</label>
        <textarea name="remark" ?hidden="${!this._checkTransport}"></textarea>

        <label ?hidden="${this._isDisabled}">${i18next.t('label.reusable_pallet')}</label>
        <textarea
          name="reusablePallet"
          ?hidden="${this._isDisabled}"
          ?disabled="${this._isDisabled}"
          placeholder="(${i18next.t('text.optional')})"
        ></textarea>

        <div attachment-wrap>
          <label ?hidden="${!this._checkTransport}">${i18next.t('label.upload_documents')}</label>
          <file-uploader
            name="attachments"
            id="uploadDocument"
            label="${i18next.t('label.select_file')}"
            accept="*"
            multiple="true"
            ?hidden="${!this._checkTransport}"
            custom-input
          ></file-uploader>
        </div>

        <fieldset>
          <legend ?hidden="${!this._otherDestination}"></legend>
          <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="otherBillingAddress"
            ?hidden="${!this._otherDestination}"
            placeholder="(${i18next.t('text.optional')})"
          ></textarea>
        </fieldset>
      </form>

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

          <data-grist
            id="product-grist"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.productGristConfig}
            .data="${this.productData}"
            @record-change="${this._onProductChangeHandler.bind(this)}"
          ></data-grist>
        </div>
      </div>
    `
  }

  constructor() {
    super()
    this._checkTransport = false
    this._disableTransport = false
    this._enableTransportationServiceSetting = false
    this._enableTransportForCustomClearanceSetting = false
    this._isDisabled = true
    this._orderType = null
    this._otherDestination = false
    this._ownCollection = false
    this._showOtherDestination = true
    this._warehouseTransport = false
    this.productData = { records: [] }
  }

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

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

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

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

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

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

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

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

  get _document() {
    return this.shadowRoot.querySelector('#uploadDocument')
  }

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

  async pageInitialized() {
    this._enableTransportationServiceSetting = await fetchSettingRule('enable-transportation-service')
    this._enableTransportForCustomClearanceSetting = await fetchSettingRule('enable-custom-clearance-transportation')
    this._isDisabled = await fetchSettingRule('disable-reusable-pallet')

    await this.fetchBizplaces()
    this._configureProductGrist()
    this._fieldsToggle()

    this.uomValueUnits = await getCodeByName('WEIGHT_UNITS')
    this.packingTypes = await getCodeByName('PACKING_TYPES')
  }

  _configureProductGrist() {
    this.productGristConfig = {
      pagination: { infinite: true },
      list: { fields: ['batch_no', 'product', 'packingType', 'totalUomValue'] },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'gutter',
          gutterName: 'button',
          icon: 'close',
          handlers: {
            click: (columns, data, column, record, rowIndex) => {
              this.productData = {
                ...this.productData,
                records: data.records.filter((_, idx) => idx !== rowIndex)
              }
            }
          }
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          record: { editable: true },
          width: 150
        },
        {
          type: 'object',
          name: 'productDetails',
          header: i18next.t('field.product'),
          record: {
            editable: true,
            options: {
              queryName: 'productDetails',
              basicArgs: { filters: [{ name: 'bizplace_id', operator: 'eq', value: this._bizplaceId }] },
              nameField: 'name',
              descriptionField: 'description',
              select: [
                { name: 'id', hidden: true },
                { name: 'sku', header: i18next.t('field.sku') },
                { name: 'name', header: i18next.t('field.name') },
                { name: 'description', header: i18next.t('field.description') },
                { name: 'packingType', header: i18next.t('field.packing_type') },
                { name: 'uom', header: i18next.t('field.uom') },
                { name: 'uomValue', header: i18next.t('field.uom_value') },
                { name: 'productId', hidden: true }
              ],
              list: { fields: ['sku', 'name', 'description', 'packingType'] }
            }
          },
          width: 350
        },
        {
          type: 'select',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          record: {
            editable: true,
            rowOptionField: 'rowOptionPackingType'
          },
          width: 150
        },
        {
          type: 'select',
          name: 'uom',
          header: i18next.t('field.uom'),
          record: {
            editable: true,
            rowOptionField: 'rowOptionUom'
          },
          width: 80
        },
        {
          type: 'float',
          name: 'uomValue',
          header: i18next.t('field.uom_value'),
          record: { editable: true, options: { min: 0 } },
          width: 100
        },
        {
          type: 'integer',
          name: 'packQty',
          header: i18next.t('field.pack_qty'),
          record: { editable: true, options: { min: 0 } },
          width: 80
        },
        {
          type: 'integer',
          name: 'palletQty',
          header: i18next.t('field.pallet_qty'),
          record: { editable: true, options: { min: 0 } },
          width: 80
        },
        {
          type: 'string',
          name: 'remark',
          header: i18next.t('field.remark'),
          record: { editable: true },
          width: 300
        }
      ]
    }
  }

  _onProductChangeHandler(event) {
    try {
      this._checkProductDuplication()
      let changeRecord = event.detail.after
      changeRecord['packingType'] = changeRecord.productDetails?.packingType || ''
      const changedColumn = event.detail.column.name

      if (event.detail.column.name == 'productDetails') {
        let uomValue = !!changeRecord.productDetails?.uomValue
        changeRecord.uomValue = uomValue ? changeRecord.productDetails.uomValue : null
        let uom = !!changeRecord.productDetails?.uom
        changeRecord.uom = uom ? changeRecord.productDetails.uom : ''
        let packingType = !!changeRecord.productDetails?.packingType
        changeRecord.packingType = packingType ? changeRecord.productDetails.packingType : ''
        ;(changeRecord.rowOptionUom = {
          options: [
            ...(uom
              ? [
                  {
                    display: changeRecord.productDetails.uom,
                    value: changeRecord.productDetails.uom
                  }
                ]
              : [
                  {
                    display: '',
                    value: ''
                  },
                  ...this.uomValueUnits.map(unit => {
                    return { display: unit.name, value: unit.name }
                  })
                ])
          ]
        }),
          (changeRecord.rowOptionPackingType = {
            options: [
              ...(packingType
                ? [
                    {
                      display: changeRecord.productDetails.packingType,
                      value: changeRecord.productDetails.packingType
                    }
                  ]
                : [
                    {
                      display: '',
                      value: ''
                    },
                    ...this.packingTypes.map(type => {
                      return { display: type.name, value: type.name }
                    })
                  ])
            ]
          })
      }

      const amountRelatedColumns = ['uomValue', 'uom', 'packQty', 'palletQty']
      if (amountRelatedColumns.indexOf(changedColumn) >= 0) {
        const calcedAmount = this._calcAmount(changedColumn, changeRecord)
        for (let key in calcedAmount) {
          changeRecord[key] = calcedAmount[key]
        }
      }
    } catch (e) {
      const beforeValue = event.detail.before && event.detail.before[event.detail.column.name]
      if (beforeValue) {
        event.detail.after[event.detail.column.name] = beforeValue
      } else {
        delete event.detail.after[event.detail.column.name]
      }

      this._showToast(e)
    }
  }

  _openBizplacesSelector() {
    openPopup(
      html`
        <popup-partner-bizplaces-selector
          @selected="${e => {
            this._bizplaceId = e.detail.id
            this._bizplaceName = e.detail.name
            this.productGrist.reset()
            this._configureProductGrist()
          }}"
        ></popup-partner-bizplaces-selector>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: i18next.t('title.select_company')
      }
    )
  }

  _openCPSelector() {
    if (!this._bizplaceId) {
      this._showToast({
        level: 'error',
        message: i18next.t('text.company_was_not_selected')
      })
    } else {
      const bizplace = { id: this._bizplaceId }
      openPopup(
        html`
          <contact-point-selector-popup
            .bizplace="${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
            this._transportVehicle = e.detail.id
          }}"
        ></transport-vehicles-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_truck')
      }
    )
  }

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

  _checkProductDuplication() {
    // batchId, product.id, packingType
    let isDuplicated = false
    const completedRows = this.productGrist.dirtyData.records
    .filter(record => record.batchId && record.productDetails && record.productDetails.id && record.packingType)
    .map(record => `${record.batchId}-${record.productDetails.id}-${record.packingType}`)

    completedRows.forEach((row, idx, rows) => {
      if (rows.lastIndexOf(row) !== idx) {
        isDuplicated = true
      }
    })

    if (isDuplicated) {
      throw new Error(i18next.t('text.there_is_duplicated_products'))
    }
  }

  _calcAmount(changedColumn, changeRecord) {
    let calcedRecord = {}
    let { uomValue, uom, packQty, releaseQty, releaseUomValue, palletQty } = changeRecord

    if (changedColumn === 'uomValue' && (!uomValue || uomValue < 0))
      throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.uom_value') } }))
    if (changedColumn === 'packQty' && (!packQty || packQty < 0))
      throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.pack_qty') } }))
    if (changedColumn === 'palletQty' && (!palletQty || palletQty < 0))
      throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.pallet_qty') } }))
    if (changedColumn === 'uom' && !uom)
      throw new Error(i18next.t('text.x_is_empty', { state: { x: i18next.t('label.uom') } }))

    if (uomValue && uom && packQty) {
      calcedRecord.totalUomValue = `${(uomValue * packQty).toFixed(2)} ${uom}`
    } else {
      calcedRecord.totalUomValue = ''
    }

    return calcedRecord
  }

  async _createDeliveryOrder() {
    try {
      this._validateForm()
      this._validateProducts()

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

      if (!result.value) return

      const attachments = this._document?.files ? this._document.files : undefined

      const response = await client.mutate({
        mutation: gql`
          mutation createDeliveryOrder(
            $orderInfo: NewDeliveryOrder
            $customerBizplace: ObjectRef
            $targetInventories: [NewOrderInventory!]
            $attachments: [Upload!]
          ) {
            createDeliveryOrder(
              orderInfo: $orderInfo
              customerBizplace: $customerBizplace
              targetInventories: $targetInventories
              file: $attachments
            ) {
              id
              name
            }
          }
        `,
        variables: {
          orderInfo: this._getFormInfo(),
          targetInventories: this._getOrderInventories(),
          customerBizplace: { id: this._bizplaceId, name: this._bizplaceName },
          attachments
        },
        context: {
          hasUpload: true
        }
      })

      if (!response.errors) {
        this._clearView()
        const doNo = response.data.createDeliveryOrder.name
        navigate(`view_delivery_note/${doNo}`)

        this._showToast({ message: i18next.t('text.delivery_order_created') })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _fieldsToggle() {
    //Check if warehouse provide transport
    if (this._ownCollection || this._warehouseTransport) {
      this._checkTransport = true
      this._showOwnCollectionField = false
      this._showWarehouseTransportField = false

      if (this._otherDestination) {
        this._showOtherDestination = true
      }
      // if other destination is false (but not undefined)
      else if (this._otherDestination === false) {
        this._showOtherDestination = false
      }
    }

    // to toggle warehouse or third party driver and truck fields
    if (this._ownCollection && !this._warehouseTransport) {
      this._showOwnCollectionField = true
    } else if (!this._ownCollection && this._warehouseTransport) {
      this._showWarehouseTransportField = true
    }
  }

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

    if (this._ownCollection) {
      if (this._getInputByName('ownDriver').value.trim().length <= 0) {
        throw new Error(i18next.t('text.driver_is_empty'))
      }

      if (this._getInputByName('ownTruck').value.trim().length <= 0) {
        throw new Error(i18next.t('text.truck_no_is_empty'))
      }
    } else {
      if (this._truckDriverInput.value.trim().length <= 0) {
        throw new Error(i18next.t('text.driver_is_not_selected'))
      }

      if (this._getInputByName('warehouseTruck').value.trim().length <= 0) {
        throw new Error(i18next.t('text.truck_is_not_selected'))
      }
    }

    if (this._otherDestination) {
      if (this._getInputByName('contactName').value.trim().length <= 0) {
        throw new Error(i18next.t('text.contact_is_empty'))
      }

      if (this._getInputByName('otherDestination').value.trim().length <= 0) {
        throw new Error(i18next.t('text.destination_is_empty'))
      }

      if (this._getInputByName('otherBillingAddress').value.trim().length <= 0) {
        this._getInputByName('otherBillingAddress').value = this._getInputByName('otherDestination').value
      }

      if (this._getInputByName('contactPhone').value.trim().length <= 0) {
        this._getInputByName('contactPhone').value = ''
      }

      if (this._getInputByName('contactEmail').value.trim().length <= 0) {
        this._getInputByName('contactEmail').value = '-'
      }

      if (this._getInputByName('contactType').value.trim().length <= 0) {
        throw new Error(i18next.t('text.please_select_the_contact_type'))
      }
    } else {
      if (this._getInputByName('contactPoint').value.trim().length <= 0) {
        throw new Error(i18next.t('text.destination_is_not_selected'))
      }
    }

    if (this._ownCollection && this._warehouseTransport) {
      throw new Error(i18next.t('text.you_can_only_select_one_transport_type'))
    } else if (!this._ownCollection && !this._warehouseTransport) {
      throw new Error(i18next.t('text.please_select_transport_type'))
    }
  }

  _validateProducts() {
    // no records
    const records = this.productGrist.dirtyData.records
    if (!records?.length) throw new Error(i18next.t('text.no_products'))

    const checkRequiredFields = ({ batchId, packingType, uomValue, uom, packQty }) =>
      !batchId || !packingType || !uomValue || !uom || !packQty

    // required field (batchId, packingType, uomValue, uom, packQty)
    if (records.some(checkRequiredFields)) {
      throw new Error(i18next.t('text.empty_value_in_list'))
    }

    if (records.some(({ palletQty, packQty }) => palletQty > packQty)) {
      throw new Error(
        i18next.t('text.a_cannot_exceed_b', {
          state: {
            a: i18next.t('field.pallet_qty'),
            b: i18next.t('field.pack_qty')
          }
        })
      )
    }
  }

  _getFormInfo() {
    let formData = this._serializeForm(this.deliveryOrderForm)

    if (this._warehouseTransport) {
      formData = {
        ...formData,
        truckNo: formData.warehouseTruck,
        transportDriver: this._transportDriver,
        transportVehicle: this._transportVehicle
      }

      delete formData.warehouseTruck
      delete formData.warehouseDriver
      delete formData.warehouseDriverCode
    } else {
      formData = {
        ...formData,
        truckNo: formData.ownTruck,
        otherDriver: formData.ownDriver,
        otherDriverCode: formData.ownDriverCode,
        transportDriver: null,
        transportVehicle: null
      }

      delete formData.ownTruck
      delete formData.ownDriverCode
      delete formData.ownDriver
    }

    if (!this._otherDestination) formData.contactPointRefId = this.selectedCP

    delete formData.bizplaceName
    delete formData.otherDestBoolean
    delete formData.warehouseTransport
    delete formData.contactPoint

    return formData
  }

  _getOrderInventories() {
    return this.productGrist.dirtyData.records.map(record => {
      let orderInventory = {
        batchId: record.batchId,
        product: { id: record.productDetails?.productId },  
        productDetail: {
          id: record.productDetails?.id,
          sku: record.sku
        },
        packingType: record.packingType,
        releaseUomValue: record?.uomValue ? record?.uomValue : 0,
        uom: record.uom,
        releaseQty: record.packQty,
        remark: record?.remark ? record.remark : null,
        palletQty: record?.palletQty ? record?.palletQty : 0
      }

      return orderInventory
    })
  }

  async fetchBizplaces() {
    const filters = []
    const response = await client.query({
      query: gql`
        query partnersBizplaces($filters: [Filter!]) {
          partnersBizplaces(filters: $filters) {
            items {
              id
              name
              description
            }
          }
        }
      `,
      variables: { filters }
    })

    if (!response.errors) {
      const bizplaces = response.data.partnersBizplaces.items
      if (bizplaces.length == 1) {
        this._bizplaceId = bizplaces[0].id
        this._bizplaceName = bizplaces[0].name
      } else {
        this._bizplaceId = ''
        this._bizplaceName = ''
      }

      return bizplaces
    }
  }

  _clearView() {
    this.deliveryOrderForm.reset()
    this.productData = { ...this.productData, records: [] }
    if (this._document?._files) {
      this._document._files = []
    }
  }

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

    return obj
  }

  checkProductValidity() {
    if (!this.productGrist.dirtyData.records || !this.productGrist.dirtyData.records.length)
      throw new Error(i18next.t('text.there_is_no_product'))

    if (this.productGrist.dirtyData.records.some(record => !record.batchId))
      throw new Error(i18next.t('text.invalid_batch_no'))

      if (this.productGrist.dirtyData.records.some(record => !record.productDetails || !record.productDetails.id))
      throw new Error(i18next.t('text.invalid_product'))

    if (this.productGrist.dirtyData.records.some(record => !record.packingType))
      throw new Error(i18next.t('text.invalid_packing_type'))

    if (this.productGrist.dirtyData.records.some(record => !record.uomValue))
      throw new Error(i18next.t('text.invalid_uom_value'))

    if (this.productGrist.dirtyData.records.some(record => !record.packQty))
      throw new Error(i18next.t('text.invalid_pack_qty'))

    return true
  }

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

window.customElements.define('create-delivery-order', CreateDeliveryOrder)
