import '@things-factory/grist-ui'
import '@things-factory/biz-ui'
import '@things-factory/warehouse-ui'
import '@things-factory/import-ui'

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

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 { fetchSettingRule } from '@things-factory/setting-ui'
import { client, CustomAlert, navigate, PageView, store } from '@things-factory/shell'
import { CommonButtonStyles } from '@things-factory/styles'
import { flattenObject, isMobileDevice } from '@things-factory/utils'

import { DRAFT_RELEASE_ORDER_STATUS, PRODUCT_GROUP_TYPES } from '../../../constants'

class DraftReleaseGoodDetail extends connect(store)(localize(i18next)(PageView)) {
  static get properties() {
    return {
      /* Draft RO Form Fields */
      _ownTransport: Boolean,
      _warehouseTransport: Boolean,
      _crossDocking: Boolean,
      _exportOption: Boolean,
      _bizplaces: Object,
      _bizplaceId: String,
      _bizplaceName: String,
      _productData: Object,
      refNo: String,
      refNo2: String,
      refNo3: String,
      releaseDate: Date,
      collectionOrderNo: String,
      /* Draft RO Form Fields */

      _draftOrderData: Object,
      _enableTransportationServiceSetting: Boolean,
      _enableTransportForCustomClearanceSetting: Boolean,
      _disableTransport: Boolean,
      _editable: Boolean,
      _files: Array,
      _attachments: Array,
      _orderProductGristConfig: Object
    }
  }

  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] * {
          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);
        }

        [attachment-wrap] ul a * {
          vertical-align: middle;
        }
        [attachment-wrap] ul {
          grid-column: span 9 / auto;
        }
        [attachment-wrap] ul a {
          display: block;
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          color: var(--primary-color);
          font-size: var(--fontsize-default);
        }
        [attachment-wrap] ul {
          margin: 0;
          padding: 0;
          list-style: none;
        }
        [attachment-wrap] ul a mwc-icon {
          font-size: var(--fontsize-default);
        }

        .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) {
          [attachment-wrap] {
            grid-column: span 36;
          }
        }
        @media screen and (min-width: 2001px) {
          [attachment-wrap] {
            grid-column: span 48;
          }
          [attachment-wrap] label {
            width: 6%;
          }
        }
      `
    ]
  }

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

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

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

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

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

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

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

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

  // disable file upload feature. Unable to delete insert / upsert file
  // get _document() {
  //   return this.shadowRoot.querySelector('#uploadDocument')
  // }

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

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

  get _productColumns() {
    return this._productGrist.columns
  }

  get context() {
    let actions = []

    // first time getting the draft order data
    if (this._draftOrderData) {
      actions = [
        {
          title: i18next.t('button.to_listing'),
          action: this._navigateToList.bind(this),
          ...CommonButtonStyles.back
        }
      ]

      if (
        this._draftOrderData?.status != DRAFT_RELEASE_ORDER_STATUS.PENDING &&
        this._draftOrderData?.status != DRAFT_RELEASE_ORDER_STATUS.PARTIAL_RELEASED &&
        this._draftOrderData?.status != DRAFT_RELEASE_ORDER_STATUS.SUBMITTED &&
        this._draftOrderData?.status != DRAFT_RELEASE_ORDER_STATUS.CANCELLED
      ) {
        actions = [
          {
            title: i18next.t('button.draft'),
            action: this._updateDraftOrder.bind(this, DRAFT_RELEASE_ORDER_STATUS.DRAFT),
            ...CommonButtonStyles.draft
          },
          // {
          //   title: i18next.t('button.create_ro'),
          //   action: this._updateDraftOrder.bind(this, DRAFT_RELEASE_ORDER_STATUS.SUBMITTED),
          //   ...CommonButtonStyles.submit
          // },
          ...actions
        ]
      }
    }

    return {
      title: `${i18next.t('title.draft_release_order_detail')} `,
      actions,
      help: 'operato-wms/draft-release-order-detail'
    }
  }

  async pageInitialized() {
    let [enableTransportationServiceSetting, bizplaces, packingTypes] = await Promise.all([
      fetchSettingRule('enable-transportation-service'),
      this.fetchBizplaces(),
      getCodeByName('PACKING_TYPES')
    ])

    this._enableTransportationServiceSetting = enableTransportationServiceSetting
    this._bizplaces = bizplaces
    this.packingTypes = packingTypes

    this._editable = false

    this._clearView()

    if (!this._enableTransportationServiceSetting)
      this._enableTransportationServiceSetting = await fetchSettingRule('enable-transportation-service')

    if (!this._bizplaces) this._bizplaces = await this.fetchBizplaces()

    if (!this._packingTypes) this._packingTypes = await getCodeByName('PACKING_TYPES')
  }

  render() {
    return html`
      <form name="draftReleaseOrder" class="multi-column-form" autocomplete="off">
        <fieldset>
          <legend>${i18next.t('title.draft_release_order')} (${this._orderNo || 'NEW'}) [${
      this._draftOrderData?.status
    }]</legend>

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

            <input
              id="warehouseTransport"
              type="checkbox"
              name="warehouseTransport"
              ?checked="${this._warehouseTransport}"
              ?disabled="${this._disableTransport}"
              @change="${e => {
                this._warehouseTransport = e.currentTarget.checked
                if (this._warehouseTransport) {
                  this._ownTransportInput.checked = false
                  this._ownTransport = false
                  this._exportOptionInput.checked = false
                  this._exportOption = false
                } else {
                  this._ownTransportInput.checked = true
                  this._ownTransport = true
                }
                this._validateTransport()
              }}"
            />
            <label for="warehouseTransport" ?hidden="${this._importedOrder}"
              >${i18next.t('label.warehouse_transport')}</label
            >

            <input
              id="exportOption"
              type="checkbox"
              name="exportOption"
              .checked="${this._exportOption}"
              ?hidden="${!this._checkTransport}"
              @change="${e => {
                this._exportOption = e.currentTarget.checked
                if (this._exportOption == true) {
                  this._warehouseTransportInput.checked = false
                  this._warehouseTransport = false
                  this._ownTransportInput.checked = true
                  this._ownTransport = true
                }
                if (this._warehouseTransport) {
                  this._exportOptionInput.checked = false
                  this._exportOption = false
                }
              }}"
            />
            <label for="exportOption" ?hidden="${!this._checkTransport}">${i18next.t('label.export')}</label>

            <input
              id="packingOption"
              type="checkbox"
              ?hidden="${!this._checkTransport}"
              name="packingOption"
              .checked="${this._packingOption}"
              disabled
            />
            <label for="packingOption" ?hidden="${!this._checkTransport}">${i18next.t('label.packing')}</label>
          </div>

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

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

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

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

          <label ?hidden="${!this._checkTransport}">${i18next.t('label.release_date')}</label>
          <input
            name="releaseDate"
            type="date"
            .value="${this.releaseDate}"
            required
            ?hidden="${!this._checkTransport}"
            @change="${this._validateDate}"
          />

          ${
            this._ownTransport
              ? html`
                  <label>${i18next.t('label.co_no')}</label>
                  <input name="collectionOrderNo" .value="${this.collectionOrderNo}" />
                `
              : ''
          }

          <!-- <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>
      </form>

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

            <label>${i18next.t('label.container_arrival_date')}</label>
            <input name="containerArrivalDate" type="date" .value="${this.containerArrivalDate}" required />

            <label>${i18next.t('label.container_leaving_date')}</label>
            <input name="containerLeavingDate" type="date" .value="${this.containerLeavingDate}" required />

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

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


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

  async pageUpdated(changes, lifecycle) {
    if (this.active) {
      try {
        this._clearView()

        if (!this._enableTransportationServiceSetting)
          this._enableTransportationServiceSetting = await fetchSettingRule('enable-transportation-service')

        if (!this._bizplaces) this._bizplaces = await this.fetchBizplaces()

        if (!this._packingTypes) this._packingTypes = await getCodeByName('PACKING_TYPES')

        // getting orderNo and see whether it's enw or existing draft order
        let orderNo = changes.resourceId || this._orderNo
        this._orderNo = orderNo == 'new' ? '' : orderNo
        await this._fetchOrder()

        this.updateContext()
      } catch (e) {
        this._showToast(e)
      } finally {
        this.updateContext()
      }
    }
  }

  _initProperties() {
    this._exportOption = false
    this.refNo = ''
    this.refNo2 = ''
    this.refNo3 = ''
    this.releaseDate = ''
    this.collectionOrderNo = ''
    this._bizplaceName = null
    this._bizplaceId = null
    this._files = []
    this.containerNo = ''
    this.containerArrivalDate = ''
    this.containerLeavingDate = ''
    this.shipName = ''
    this._productData = { ...this._productData, records: [] }
    this._initialiseProductGristConfig()
  }

  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

      return bizplaces
    }
  }

  _onProductFieldChanged(e) {
    this._productData = {
      ...this._productData,
      ...this._productGrist.dirtyData,
      records: this._productGrist.dirtyData.records.map((record, idx) => {
        let returnObj = {
          ...record,
          ...record.product,
          product: { ...record.product, id: record.product?.id || record.product.productId },
          productDetail: { id: record.productDetail?.id || record.product.productDetailId },
          name: record.name ? record.name : idx,
          releaseQty: record.releaseQty < 0 ? 0 : record.releaseQty,
          id: record.id
        }
        return returnObj
      })
    }
    this._updateProductGristConfig()
  }

  _initialiseProductGristConfig() {
    let bundleData = this._draftOrderData?.orderProducts?.find(op => op.productBundle)
    this._editable = this._draftOrderData?.status == DRAFT_RELEASE_ORDER_STATUS.DRAFT && !bundleData
    this._orderProductGristConfig = {
      pagination: { infinite: true },
      rows: {
        selectable: { multiple: false }
      },
      list: { fields: ['inventory', 'product', 'location', 'releaseQty'] },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'gutter',
          gutterName: 'button',
          icon: 'close',
          handlers: {
            click: (columns, data, column, record, rowIndex) => {
              try {
                const newData = data.records.filter((_, idx) => idx !== rowIndex)
                this._productData = { ...this._productData, records: newData }
                this._productGrist.dirtyData.records = newData
                this._updateProductGristConfig()
              } catch (e) {
                this._showToast(e)
              }
            }
          }
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 100
        },
        {
          type: 'object',
          name: 'product',
          header: i18next.t('field.product'),
          record: {
            editable: !!this._bizplaceId && this._editable,
            options: {
              queryName: 'allBizplaceProductInventory',
              basicArgs: {
                filters: [
                  { name: 'bizplace_id', operator: 'eq', value: this._bizplaceId },
                  { name: 'deleted_at', operator: 'eq', value: true }
                ]
              },
              nameField: 'productSKU',
              descriptionField: 'productName',
              select: [
                { name: 'id', hidden: true },
                { name: 'productId', hidden: true },
                { name: 'productDetailId', hidden: true },
                { name: 'remainUomValue', hidden: true },
                {
                  name: 'groupType',
                  header: i18next.t('field.group_type'),
                  ignoreCondition: true
                },
                {
                  name: 'productSKU',
                  header: i18next.t('field.sku'),
                  width: 150
                },
                {
                  name: 'productName',
                  header: i18next.t('field.product_info'),
                  width: 280
                },
                { name: 'productBrand', header: i18next.t('field.brand') },
                { name: 'packingType', header: i18next.t('field.packing_type') },
                { name: 'packingSize', header: i18next.t('field.packing_size') },
                { name: 'uom', header: i18next.t('field.uom') },
                {
                  name: 'remainQty',
                  header: i18next.t('field.remain_qty'),
                  ignoreCondition: true
                },
                {
                  name: 'remainUomValueWithUom',
                  header: i18next.t('field.remain_uom_value'),
                  ignoreCondition: true
                }
              ],
              list: {
                fields: ['groupType', 'productName', 'productBrand', 'packingType', 'remainQty', 'remainUomValue']
              }
            }
          },
          width: 300
        },
        {
          type: 'string',
          name: 'groupType',
          header: i18next.t('field.group_type'),
          width: 100
        },
        {
          type: 'string',
          name: 'productBrand',
          header: i18next.t('field.brand'),
          width: 100
        },
        {
          type: 'code',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          record: {
            codeName: 'PACKING_TYPES'
          },
          width: 150
        },
        {
          type: 'number',
          name: 'packingSize',
          header: i18next.t('field.packing_size'),
          width: 140
        },
        {
          type: 'string',
          name: 'uom',
          header: i18next.t('field.uom'),
          width: 100
        },
        {
          type: 'float',
          name: 'remainQty',
          header: i18next.t('field.available_qty'),
          width: 140
        },
        {
          type: 'string',
          name: 'remainUomValueWithUom',
          header: i18next.t('field.available_uom_value'),
          width: 140
        },
        {
          type: 'float',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          imex: { header: i18next.t('field.release_qty'), key: 'releaseQty', width: 25, type: 'float' },
          record: { editable: this._editable },
          width: 140
        },
        {
          type: 'string',
          name: 'remark',
          header: i18next.t('field.remark'),
          record: { editable: this._editable },
          width: 200
        },
        {
          type: 'string',
          name: 'status',
          header: i18next.t('field.status'),
          width: 200
        }
      ]
    }
  }

  _updateProductGristConfig() {
    const _selectedInv = (this._productData.records || []).map(record => {
      return {
        productId: record?.product?.id || record?.product?.productId,
        packingType: record?.packingType,
        packingSize: record?.packingSize,
        productDetail: record?.productDetail,
        uom: record?.uom,
        groupType: record?.groupType
      }
    })

    this._orderProductGristConfig = {
      ...this._orderProductGristConfig,
      columns: this._orderProductGristConfig.columns.map(column => {
        if (column.name === 'product') {
          column.record.options.basicArgs = {
            ...column.record.options.basicArgs,
            filters: [
              ...column.record.options.basicArgs.filters.filter(
                filter => filter.name !== 'product' && filter.name !== 'batch_bundle'
              )
            ]
          }
          if (_selectedInv.length) {
            const _selectedSingleInv = _selectedInv.filter(inv => inv.groupType === PRODUCT_GROUP_TYPES.SINGLE)
            const _selectedBundleInv = _selectedInv.filter(inv => inv.groupType === PRODUCT_GROUP_TYPES.BUNDLE)
            if (_selectedSingleInv.length)
              column.record.options.basicArgs.filters.push({
                name: 'product',
                value: _selectedSingleInv,
                operator: 'notin'
              })
            if (_selectedBundleInv.length)
              column.record.options.basicArgs.filters.push({
                name: 'batch_bundle',
                value: _selectedBundleInv,
                operator: 'notin'
              })
          }
        }
        return column
      })
    }
  }

  _onProductChangeHandler(event) {
    const changeRecord = event.detail.after
    const changedColumn = event.detail.column.name
    try {
      this._updateProductGristConfig()
    } 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)
    }
  }

  async _fetchOrder() {
    if (!this._orderNo) {
      this._draftOrderData = {
        bizplace:
          this._bizplaces?.length > 1
            ? { id: null, name: '' }
            : { id: this._bizplaces[0].id, name: this._bizplaces[0].name },
        status: DRAFT_RELEASE_ORDER_STATUS.DRAFT
      }
      return
    } else {
      const response = await client.query({
        query: gql`
          query draftReleaseGoodByName($name: String!) {
            draftReleaseGoodByName(name: $name) {
              id
              name
              truckNo
              type
              attentionTo
              phone1
              deliveryAddress1
              bizplace {
                id
                name
              }
              status
              refNo
              refNo2
              refNo3
              ownTransport
              packingOption
              releaseDate
              collectionOrderNo
              attachment {
                id
                name
                refBy
                path
                mimetype
              }
              bizplace {
                id
                name
                description
              }
              orderProducts {
                id
                name
                batchId
                product {
                  id
                  name
                  brand
                  sku
                  description
                }
                productDetail {
                  id
                }
                productBundle {
                  name
                  sku
                  description
                }
                packingType
                packingSize
                uomValue
                uom
                releaseQty
                totalUomValue
                remark
                remainQty
                remainUomValue
                remainUomValueWithUom
                groupType
                status
              }
              shippingOrder {
                id
                containerNo
                containerLeavingDate
                containerArrivalDate
                shipName
              }
              createdAt
              updatedAt
              updater {
                id
                name
                description
              }
              creator {
                id
                name
                description
              }
            }
          }
        `,
        variables: { name: this._orderNo }
      })

      if (!response.errors) {
        this._draftOrderData = {
          // this is where data is
          ...response.data.draftReleaseGoodByName
          // shippingOrder: this._exportOption ? this._serializeForm(this._shippingOrderForm) : null
        }
        this._productData = {
          records: response.data.draftReleaseGoodByName.orderProducts.map(itm => {
            return {
              ...itm,
              product: { ...itm.product, productSKU: itm.product.sku, productName: itm.product.name },
              brand: itm.product.brand,
              id: itm.id
            }
          })
        }

        if (response.data?.draftReleaseGoodByName?.shippingOrder) {
          this._exportOption = true
          this._fillUpForm(response.data.draftReleaseGoodByName.shippingOrder, this._shippingOrderForm)
        }

        if (this._draftOrderData && this._draftOrderData?.attachment) {
          this._attachments = this._draftOrderData.attachment

          // disable file upload feature. Unable to delete insert / upsert file
          // if (this._document) {
          //   this._document._files = data.attachment
          // }
        }

        this._ownTransport = this._draftOrderData.ownTransport
        this._bizplaceId = this._draftOrderData.bizplace.id
        this._bizplaceName = this._draftOrderData.bizplace.name

        this._draftOrderData.warehouseTransport = !!!this._draftOrderData.ownTransport || false
        this._warehouseTransport = this._draftOrderData.warehouseTransport

        this._fillUpForm(
          flattenObject({ ...this._draftOrderData, bizplaceId: this._bizplaceId, bizplaceName: this._bizplaceName })
        )
      }
    }
    this._initialiseProductGristConfig()
    this._validateTransport()
    this._updateProductGristConfig()
  }

  async _updateDraftOrder(status) {
    try {
      this._validateForm()
      this._validateProducts()

      if (this._draftOrderData.bizplace.id != null) {
        this._validateChanges()
      }

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

      if (!result.value) return

      let draftOrder = {
        ...this._draftOrderData,
        ...this._getFormInfo(),
        bizplace: { id: this._bizplaceId, name: this._bizplaceName }
      }

      // const fileUploader = this._document?.files ? this._document.files : undefined
      const fileUploader = undefined

      const objectNames = [
        'bizplace|name',
        'bizplaceId',
        'bizplaceName',
        'warehouseTransport',
        'orderProducts',
        'shippingOrderInfo',
        'shippingOrder',
        'attachment',
        'creator',
        'updater',
        'createdAt',
        'updatedAt'
      ]

      objectNames.forEach(objectName => {
        delete draftOrder[objectName]
      })

      let variables = {
        draftReleaseGood: {
          ...draftOrder,
          status,
          ownTransport: this._ownTransport
        },
        orderProducts: this._getOrderProducts(),
        files: fileUploader,
        shippingOrder: this._exportOption ? this._serializeForm(this._shippingOrderForm) : null
      }

      const response = await client.mutate({
        mutation: gql`
          mutation upsertDraftReleaseGood(
            $draftReleaseGood: DraftReleaseGoodPatch!
            $orderProducts: [OrderProductPatch!]!
            $files: [Upload!]
            $shippingOrder: ShippingOrderPatch
          ) {
            upsertDraftReleaseGood(
              draftReleaseGood: $draftReleaseGood
              orderProducts: $orderProducts
              files: $files
              shippingOrder: $shippingOrder
            ) {
              id
              name
            }
          }
        `,
        variables,
        context: { hasUpload: true }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.draft_order_saved') })
        this._clearView()
        this._navigateToList()
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _validateTransport() {
    //Check if warehouse provide transport
    if (this._enableTransportationServiceSetting != undefined && !this._enableTransportationServiceSetting) {
      this._disableTransport = true
      this._ownTransportInput.checked = true
      this._ownTransport = true
    }

    if (this._ownTransport || this._warehouseTransport) {
      this._checkTransport = true
    }
  }

  _validateForm() {
    if (!this._draftReleaseOrderForm.checkValidity()) throw new Error(i18next.t('text.draft_order_form_invalid'))

    // if (this._draftOrderData?.container && !this.containerNo.value)
    //   throw new Error(i18next.t('text.container_no_is_empty'))

    if (this._exportOption == true) {
      let e = ''
      if (
        isEmpty(this._shippingOrderForm.containerNo.value) ||
        isEmpty(this._shippingOrderForm.shipName.value) ||
        isEmpty(this._shippingOrderForm.containerArrivalDate.value) ||
        isEmpty(this._shippingOrderForm.containerLeavingDate.value)
      ) {
        if (isEmpty(this._shippingOrderForm.containerNo.value)) e = i18next.t('text.container_no_is_empty')

        if (isEmpty(this._shippingOrderForm.shipName.value)) e = i18next.t('text.ship_name_is_empty')

        if (isEmpty(this._shippingOrderForm.containerArrivalDate.value))
          e = i18next.t('text.container_arrival_date_is_empty')

        if (isEmpty(this._shippingOrderForm.containerLeavingDate.value))
          e = i18next.t('text.container_leaving_date_is_empty')
      }

      if (e != '') throw new Error(e)
    }
  }

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

    // const checkRequiredFields = ({ releaseQty, product }) => !releaseQty || !product
    // if (records.some(checkRequiredFields)) {
    //   throw new Error(i18next.t('text.empty_value_in_list'))
    // }
    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.product || !record.product.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.releaseQty))
      throw new Error(i18next.t('text.invalid_release_qty'))

    // data changes validator
    if (this._draftOrderData.bizplace.id != null) {
      // // check changes in form info
      // let checkFormInfoChange = this._serializeForm(this._draftReleaseOrderForm).refNo == this._draftOrderData.refNo && this._serializeForm(this._draftReleaseOrderForm).refNo2 == this._draftOrderData.refNo2 && this._serializeForm(this._draftReleaseOrderForm).refNo3 == this._draftOrderData.refNo3 && this._serializeForm(this._draftReleaseOrderForm).releaseDate == this._draftOrderData.releaseDate && this._serializeForm(this._draftReleaseOrderForm).collectionOrderNo == this._draftOrderData.collectionOrderNo
      // // check changes in product
      // let checkProductDataChange = this._compareArray(this._productGrist.dirtyData.records, this.___draftOrderData.orderProducts)
      // if (checkFormInfoChange == true && checkProductDataChange != true)
      //     throw new Error(i18next.t('text.nothing_changed'))
    }
    return true
  }

  _getFormInfo() {
    const formData = this._serializeForm(this._draftReleaseOrderForm)
    return formData
  }

  _compareArray(a, b) {
    // Comparing the length of each array
    if (a.length != b.length) return true
    else {
      for (var i = 0; i < a.length; i++) {
        // compare releaseQty of both array
        if (a[i].releaseQty != b[i].releaseQty) {
          return true
        }
        // compare product of both array
        if (a[i].product.id != b[i].product.id) {
          return true
        }
      }
    }
  }

  _getOrderProducts() {
    return this._productGrist.dirtyData.records.map(record => {
      let orderProduct = {
        id: record.id ? record.id.toString() : null,
        name: record.name ? record.name.toString() : null,
        product: { id: record?.groupType == 'SINGLE' ? record.product.id : record?.productBundle?.id },
        productDetail: { id: record.productDetailId || record?.productDetail?.id },
        packingType: record.packingType,
        packingSize: record.packingSize,
        uomValue: record?.uomValue ? record.uomValue : 0,
        uom: record.uom,
        releaseQty: record.releaseQty,
        totalUomValue: record?.uomValue ? `${(record.uomValue * record.packQty).toFixed(2)} ${record.uom}` : ``,
        remark: record?.remark || null
      }

      return orderProduct
    })
  }

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

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

  _validateChanges() {
    // check changes in form info
    let checkFormInfoChange =
      this._serializeForm(this._draftReleaseOrderForm).refNo == this._draftOrderData.refNo &&
      this._serializeForm(this._draftReleaseOrderForm).refNo2 == this._draftOrderData.refNo2 &&
      this._serializeForm(this._draftReleaseOrderForm).refNo3 == this._draftOrderData.refNo3 &&
      this._serializeForm(this._draftReleaseOrderForm).releaseDate == this._draftOrderData.releaseDate &&
      this._serializeForm(this._draftReleaseOrderForm).collectionOrderNo == this._draftOrderData.collectionOrderNo
    // check changes in shipping form info
    let checkShippingFormInfo =
      this._draftOrderData?.shippingOrder?.containerNo == this._shippingOrderForm.containerNo.value &&
      this._draftOrderData?.shippingOrder?.containerArrivalDate == this._shippingOrderForm.containerArrivalDate.value &&
      this._draftOrderData?.shippingOrder?.containerLeavingDate == this._shippingOrderForm.containerLeavingDate.value &&
      this._draftOrderData?.shippingOrder?.shipName == this._shippingOrderForm.shipName.value
    // check changes in product
    let checkProductDataChange = this._compareArray(this._productGrist.dirtyData.records, this._productData.records)
    if (checkFormInfoChange == true && checkProductDataChange != true && checkShippingFormInfo == true)
      throw new Error(i18next.t('text.nothing_changed'))
  }

  _clearView() {
    this.refNo = ''
    this.refNo2 = ''
    this.refNo3 = ''
    this.releaseDate = ''
    this.collectionOrderNo = ''
    this._bizplaceName = null
    this._bizplaceId = null
    this._files = []
    this.containerNo = ''
    this.containerArrivalDate = ''
    this.containerLeavingDate = ''
    this.shipName = ''

    this._checkTransport = null
    this._ownTransport = false
    this._warehouseTransport = false
    this._exportOption = false

    this._draftOrderData = null
    this._draftReleaseOrderForm.reset()
    this._attachments = []
    this._productData = { records: [] }

    this._initialiseProductGristConfig()
    this._validateTransport()
  }

  _serializeForm(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
  }

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

  _navigateToList() {
    navigate(`draft_release_goods`)
  }

  _fillUpForm(data, form = this._draftReleaseOrderForm) {
    data = flattenObject(data)
    // for (let key in data) {
    Array.from(form.querySelectorAll('input, textarea, select')).forEach(field => {
      if (field.type === 'checkbox') {
        field.checked = data[field.name] || false
      } else {
        field.value = data[field.name] || ''
      }
    })
    // }
  }

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

window.customElements.define('draft-release-good-detail', DraftReleaseGoodDetail)
