import '@things-factory/grist-ui'
import '@things-factory/biz-ui'
import '@things-factory/import-ui'
import '../../components/select-product-popup'
import '../../order/vas-order/popup/vas-create-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'
import { VAS_BATCH_AND_PRODUCT_TYPE, VAS_BATCH_NO_TYPE, VAS_PRODUCT_TYPE } from '../../constants'

//vas --inbound
class DuplicateArrivalNotice extends localize(i18next)(PageView) {
  static get properties() {
    return {
      /**
       * @description
       * flag for whether use transportation from warehouse or not.
       * true =>
       */
      _ganNo: String,
      _importedOrder: Boolean,
      _checkTransport: Boolean,
      _checkTransportCrossDocking: Boolean,
      _ownTransport: Boolean,
      _warehouseTransport: Boolean,
      _enableTransportationServiceSetting: Boolean,
      _enableTransportForCustomClearanceSetting: Boolean,
      _disableTransport: Boolean,
      _crossDocking: Boolean,
      _refNo: String,
      _refNo2: String,
      _refNo3: String,
      _containerNo: String,
      _containerSize: String,
      _etaDate: String,
      _hasContainer: Boolean,
      _looseItem: Boolean,
      _files: Array,
      _disableCrossDockingSetting: Boolean,
      _hideCrossDockingSetting: Boolean,
      containerSizes: Array,
      _deliveryOrderNo: String,
      _truckNo: String,
      productGristConfig: Object,
      vasGristConfig: Object,
      productData: Object,
      vasData: Object,
      _bizplaces: Object,
      _bizplaceId: String,
      _bizplaceName: String,
      _showAddProducts: Boolean,
      _vasExpanded: Boolean
    }
  }

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

        .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;
        }
        data-grist#vas-grist {
          padding-top: 0px;
          height: 100%;
        }
        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);
        }
        h2.vas-title {
          padding-bottom: 0px;
        }
        #button-add-products {
          padding: 10px 15px 0 0;
          float: right;
        }
        .button-div {
          margin: 0 0 -30px 0;
        }
        .vas[collapsable] {
          height: 40%;
        }
        .vas[collapsable][collapsed] {
          display: none;
        }
        [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 context() {
    this._vasExpanded = false

    if (this._bizplaceName) {
      this._showAddProducts = true
    }

    return {
      title: i18next.t('title.create_arrival_notice'),
      actions: [
        {
          title: i18next.t('button.submit'),
          action: this._generateArrivalNotice.bind(this),
          ...CommonButtonStyles.submit
        }
      ]
    }
  }

  render() {
    return html`
      <form name="arrivalNotice" class="multi-column-form">
        <fieldset>
          <legend>${i18next.t('title.arrival_notice')}</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._validateTransport()
      }}"
            />
            <label for="ownTransport">${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._ownTransportInput.checked = false
          this._ownTransport = false
        } else {
          this._ownTransportInput.checked = true
          this._ownTransport = true
        }
        this._validateTransport()
      }}"
            />
            <label for="warehouseTransport">${i18next.t('label.warehouse_transport')}</label>

            <input
              id="container"
              type="checkbox"
              name="container"
              ?checked="${this._hasContainer}"
              @change="${e => {
        this._hasContainer = e.currentTarget.checked
      }}"
              ?hidden="${!this._checkTransport}"
            />
            <label for="container" ?hidden="${!this._checkTransport}">${i18next.t('label.container')}</label>

            <input
              id="looseItem"
              type="checkbox"
              name="looseItem"
              ?checked="${this._looseItem}"
              ?hidden="${!this._checkTransport}"
            />
            <label for="looseItem" ?hidden="${!this._checkTransport}">${i18next.t('label.loose_item')}</label>

            <input
              id="importedOrder"
              type="checkbox"
              name="importCargo"
              ?checked="${this._importedOrder}"
              @change="${e => {
        this._importedOrder = e.currentTarget.checked
        this._validateImportCargo()
      }}"
              ?hidden="${!this._checkTransport}"
            />
            <label for="importedOrder" ?hidden="${!this._checkTransport}">${i18next.t('label.import_cargo')}</label>

            <input
              id="crossDocking"
              type="checkbox"
              name="crossDocking"
              ?checked="${this._crossDocking}"
              ?disabled="${this._disableCrossDockingSetting}"
              ?hidden="${!this._checkTransportCrossDocking}"
              @change="${e => (this._crossDocking = e.currentTarget.checked)}"
            />
            <label for="crossDocking" ?hidden="${!this._checkTransportCrossDocking}"
              >${i18next.t('label.cross_docking')}</label
            >
          </div>

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

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

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

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

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

          <label ?hidden="${!this._hasContainer}">${i18next.t('label.container_no')}</label>
          <input ?hidden="${!this._hasContainer}" type="text" name="containerNo" value="${this._containerNo}" />

          <label ?hidden="${!this._hasContainer}">${i18next.t('label.container_size')}</label>
          <select name="containerSize" ?hidden="${!this._hasContainer}">
            <option value="">--${i18next.t('label.please_select_a_container_size')}--</option>
            ${(this.containerSizes || []).map(
        containerSize =>
          html`
                  <option
                    ?selected=${this._containerSize === containerSize.name}
                    value="${containerSize && containerSize.name}"
                  >
                    ${containerSize && containerSize.name}
                  </option>
                `
      )}
          </select>

          <label ?hidden="${!this._ownTransport}">${i18next.t('label.do_no')}</label>
          <input name="deliveryOrderNo" value="${this._deliveryOrderNo}" ?hidden="${!this._ownTransport}" />

          <label ?hidden="${!this._ownTransport}">${i18next.t('label.truck_no')}</label>
          <input ?hidden="${!this._ownTransport}" value="${this._truckNo}" name="truckNo" />

          <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="container">
        <div class="grist">
          <div class="button-div">
            <mwc-button
              id="button-add-products"
              label=${i18next.t('button.bulk_select_products')}
              raised
              @click=${e => this._openBulkProductSelection(0)}
              ?disabled=${!this._showAddProducts}
            ></mwc-button>
          </div>
          <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>

          <h2
            @click="${e => {
        this._vasExpanded = !this._vasExpanded
      }}"
            class="vas-title"
          >
            <mwc-icon>list_alt</mwc-icon>${i18next.t('title.vas')}<mwc-icon
              >${this._vasExpanded ? 'expand_less' : 'expand_more'}</mwc-icon
            >
          </h2>
          <div class="vas" collapsable ?collapsed=${!this._vasExpanded}>
            <data-grist
              id="vas-grist"
              .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
              .config=${this.vasGristConfig}
              .data="${this.vasData}"
            ></data-grist>
          </div>
        </div>
      </div>
    `
  }

  constructor() {
    super()
    this.productData = { records: [] }
    this.vasData = { records: [] }
    this._bizplaceId = ''
    this._bizplaceName = ''
    this.containerSizes = []
    this._importedOrder = false
    this._hasContainer = false
    this._ownTransport = false
    this._warehouseTransport = false
    this._checkTransport = false
    this._checkTransportCrossDocking = false
    this._crossDocking = false
    this._orderType = null
    this._enableTransportationServiceSetting = false
    this._enableTransportForCustomClearanceSetting = false
    this._disableTransport = false
    this._strictProductSelection = false
    this._showAddProducts = false
    this._vasExpanded = false
  }

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

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

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

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

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

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

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

  async pageInitialized() {
    this._enableTransportationServiceSetting = await fetchSettingRule('enable-transportation-service')
    this._enableTransportForCustomClearanceSetting = await fetchSettingRule('enable-custom-clearance-transportation')
    this._disableCrossDockingSetting = await fetchSettingRule('disable-cross-dock')
    this._hideCrossDockingSetting = await fetchSettingRule('hide-cross-dock')
    this._bizplaces = await this.fetchBizplaces()

    this._validateTransport()

    this.containerSizes = await getCodeByName('CONTAINER_SIZES')
    this.uomValueUnits = await getCodeByName('WEIGHT_UNITS')
    this.packingTypes = await getCodeByName('PACKING_TYPES')
    this._configureProductGrist()

    this.vasGristConfig = {
      list: { fields: ['ready', 'targetType', 'targetDisplay', 'packingType'] },
      pagination: { infinite: true },
      rows: {
        handlers: {
          click: (columns, data, column, record, rowIndex) => {
            this._selectedVasRecord = record
            this._selectedVasRecordIdx = rowIndex
            if (column.name) {
              this.openVasCreatePopup(record)
            }
          }
        }
      },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'gutter',
          gutterName: 'button',
          icon: 'close',
          handlers: {
            click: (columns, data, column, record, rowIndex) => {
              this.vasData = { ...this.vasData, records: data.records.filter((_, idx) => idx !== rowIndex) }
            }
          }
        },
        {
          type: 'boolean',
          name: 'ready',
          header: i18next.t('field.ready'),
          width: 40
        },
        {
          type: 'string',
          name: 'targetType',
          header: i18next.t('field.target_type'),
          width: 150
        },
        {
          type: 'string',
          name: 'targetDisplay',
          header: i18next.t('field.target'),
          width: 250
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 250
        },
        {
          type: 'integer',
          name: 'qty',
          header: i18next.t('field.qty'),
          width: 100
        },
        {
          type: 'float',
          name: 'uomValue',
          header: i18next.t('field.uom_value'),
          width: 100
        },
        {
          type: 'integer',
          name: 'vasCount',
          header: i18next.t('field.vas_count'),
          width: 100
        }
      ]
    }
  }

  async pageUpdated(changes) {
    if (this.active && changes.resourceId) {
      this._ganNo = changes.resourceId
      await this._getOriginalArrivalNotice(this._ganNo)
      this._validateTransport()
    }
  }

  updated(changedProps) {
    if (changedProps.has('_crossDocking')) {
      this._configureProductGrist()
    }
  }

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

  /**
   * @description Configure product grist
   * Product grist columns should be change by value of _crossDocking
   */
  _configureProductGrist() {
    let editable = this._bizplaceId ? true : false
    let strictEditable = this._bizplaceId ? !this._strictProductSelection : false

    const crossDockingColumns = [
      {
        type: 'integer',
        name: 'releaseQty',
        header: i18next.t('field.release_qty'),
        record: { editable: editable },
        width: 160
      },
      {
        type: 'float',
        name: 'releaseUomValue',
        header: i18next.t('field.release_uom_value'),
        record: { editable: editable },
        width: 160
      }
    ]

    const productGristColumns = [
      { 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)
            }
            this._updateVasTargets()
          }
        }
      },
      {
        type: 'string',
        name: 'batchId',
        header: i18next.t('field.batch_id'),
        record: { editable: editable },
        width: 150
      },
      {
        type: 'string',
        name: 'productName',
        header: i18next.t('field.product'),
        handlers: {
          click: (columns, data, column, record, rowIndex) => {
            this._openProductSelection(rowIndex)
          }
        },
        width: 350
      },
      {
        type: 'string',
        name: 'productBrand',
        header: i18next.t('field.brand'),
        imex: { header: i18next.t('field.brand'), key: 'productBrand', width: 25, type: 'string' },
        width: 150
      },
      {
        type: 'object',
        name: 'product',
        hidden: true
      },
      {
        type: 'select',
        name: 'packingType',
        header: i18next.t('field.packing_type'),
        imex: {
          header: i18next.t('field.packing_type'),
          key: 'packingType',
          width: 20,
          type: 'array',
          arrData: this.packingTypes
        },
        record: {
          editable: strictEditable,
          options: [
            {
              display: '',
              value: ''
            },
            ...this.packingTypes.map(type => {
              return { display: type.name, value: type.name }
            })
          ]
        },
        width: 150
      },
      {
        type: 'select',
        name: 'uom',
        header: i18next.t('field.uom'),
        imex: {
          header: i18next.t('field.uom'),
          key: 'uom',
          width: 20,
          type: 'array',
          arrData: this.uomValueUnits
        },
        record: {
          editable: strictEditable,
          options: [
            {
              display: '',
              value: ''
            },
            ...this.uomValueUnits.map(unit => {
              return { display: unit.name, value: unit.name }
            })
          ]
        },
        width: 80
      },
      {
        type: 'float',
        name: 'uomValue',
        header: i18next.t('field.uom_value'),
        record: { editable: editable, options: { min: 0 } },
        width: 80
      },
      {
        type: 'float',
        name: 'packQty',
        header: i18next.t('field.pack_qty'),
        record: { editable: editable, options: { min: 0 } },
        width: 80
      },
      {
        type: 'float',
        name: 'totalUomValue',
        header: i18next.t('field.total_uom_value'),
        width: 120
      },
      {
        type: 'integer',
        name: 'palletQty',
        header: i18next.t('field.pallet_qty'),
        record: { editable: editable, options: { min: 0 } },
        width: 80
      },
      {
        type: 'date',
        name: 'manufactureDate',
        header: i18next.t('field.manufacture_date'),
        record: { editable: editable },
        width: 120
      },
      {
        type: 'string',
        name: 'batchIdRef',
        header: i18next.t('field.batch_no_ref'),
        record: { editable: editable },
        width: 150
      },
      {
        type: 'float',
        name: 'unitPrice',
        header: i18next.t('field.unit_price'),
        record: { editable: editable },
        sortable: true,
        width: 80
      },
      {
        type: 'string',
        name: 'remark',
        header: i18next.t('field.remark'),
        record: { editable: editable },
        width: 300
      }
    ]

    if (this._crossDocking) {
      const packQtyColumnIdx =
        productGristColumns.findIndex(column => column.name === 'packQty') || productGristColumns.length - 1
      productGristColumns.splice(packQtyColumnIdx + 1, 0, ...crossDockingColumns)
    }

    this.productGristConfig = {
      pagination: { infinite: true },
      list: { fields: ['batch_no', 'product', 'packingType', 'totalUomValue'] },
      columns: productGristColumns
    }
  }

  _openBulkProductSelection() {
    if (this._bizplaceId) {
      openPopup(
        html`
          <select-product-popup
            .bizplaceId="${this._bizplaceId}"
            .selectMultipleProducts="${this._showAddProducts}"
            @selected="${e => {
            let newRecords = []
            for (let i = 0; i < e.detail.multipleProducts.length; i++) {
              newRecords.push(e.detail.multipleProducts[i])
            }
            this.productData = {
              ...this.productData,
              records: [...this.productGrist.dirtyData.records, ...newRecords]
            }
          }}"
          ></select-product-popup>
        `,
        {
          backdrop: true,
          size: 'large',
          title: i18next.t('title.select_item')
        }
      )
    } else {
      this._showToast({ message: i18next.t('text.company_selection_is_empty') })
    }
  }

  _openProductSelection(rowIndex) {
    if (this._bizplaceId) {
      openPopup(
        html`
          <select-product-popup
            .bizplaceId="${this._bizplaceId}"
            @selected="${e => {
            // let newRecord = []
            // newRecord.push(e.detail)

            if (this.productGrist.dirtyData.records.length !== rowIndex) {
              // update existing product data records
              this.productGrist.dirtyData.records.splice(rowIndex, 1, {
                ...this.productGrist.dirtyData.records[rowIndex],
                ...e.detail
              })

              this.productGrist.dirtyData.records = this.productGrist.dirtyData.records.map(item => {
                return {
                  ...item,
                  totalUomValue:
                    item?.packQty > 0
                      ? item?.totalUomValue
                        ? item.totalUomValue
                        : `${parseFloat(item.packQty * e.detail.uomValue).toFixed(3)} ${e.detail.uom}`
                      : null
                }
              })

              this.productData = {
                ...this.productData,
                records: [...this.productGrist.dirtyData.records]
              }
            } else {
              this.productData = {
                ...this.productData,
                records: [...this.productGrist.dirtyData.records, e.detail]
              }
            }
          }}"
          ></select-product-popup>
        `,
        {
          backdrop: true,
          size: 'large',
          title: i18next.t('title.select_item')
        }
      )
    } else {
      this._showToast({ message: i18next.t('text.company_selection_is_empty') })
    }
  }

  _onProductChangeHandler(event) {
    try {
      this._checkProductDuplication()
      let changeRecord = event.detail.after
      const changedColumn = event.detail.column.name

      if (event.detail.column.name == 'product') {
        let primaryValue = !!changeRecord.product?.primaryValue
        changeRecord.uomValue = primaryValue ? changeRecord.product.primaryValue : null
        let primaryUnit = !!changeRecord.product?.primaryUnit
        changeRecord.uom = primaryUnit ? changeRecord.product.primaryUnit : ''
        let packingType = !!changeRecord.product?.packingType
        changeRecord.packingType = packingType ? changeRecord.product.packingType : ''
      }

      const amountRelatedColumns = ['uomValue', 'unit', 'packQty', 'releaseQty', 'releaseUomValue']
      if (amountRelatedColumns.indexOf(changedColumn) >= 0) {
        const calcedAmount = this._calcAmount(changedColumn, changeRecord)
        for (let key in calcedAmount) {
          changeRecord[key] = calcedAmount[key]
        }
      }

      if (changedColumn === 'unitPrice') {
        let unitPrice = changeRecord.unitPrice
        if (typeof unitPrice === undefined || unitPrice < 0) {
          throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.unit_price') } }))
        }
      }

      if (changedColumn === 'manufactureDate') {
        let manufactureDate = new Date(changeRecord.manufactureDate)
        let today = new Date()

        if (manufactureDate > today) {
          delete event.detail.after[event.detail.column.name]
          throw Error(i18next.t('text.manufacture-date-cannot-be-later-than-today'))
        }
      }

      this._updateVasTargets(true)
    } 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)
    }
  }

  _checkProductDuplication() {
    // batchId, product.id, packingType
    let isDuplicated = false
    const completedRows = this.productGrist.dirtyData.records
      .filter(record => record.batchId && record.product && record.product.id && record.packingType)
      .map(record => `${record.batchId}-${record.product.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'))
    }
  }

  _calcTotalUomValue(uomValue, unit, packQty) {
    if (uomValue && unit && packQty) {
      return `${(uomValue * packQty).toFixed(3)} ${unit}`
    } else {
      return null
    }
  }

  _calcAmount(changedColumn, changeRecord) {
    let calcedRecord = {}
    let { uomValue, uom, packQty, releaseQty, releaseUomValue } = 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 === '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 = ''
    }

    if (!this._crossDocking) return calcedRecord

    if (changedColumn === 'releaseQty' || changedColumn === 'releaseUomValue') {
      if (isNaN(releaseQty)) {
        releaseQty = 0
        calcedRecord.releaseQty = releaseQty
      }
      if (isNaN(releaseUomValue)) {
        releaseUomValue = 0
        calcedRecord.releaseUomValue = releaseUomValue
      }

      if (!uomValue)
        throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.uom_value') } }))
      if (!packQty)
        throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.pack_qty') } }))

      if (changedColumn === 'releaseQty') {
        if (typeof releaseQty === undefined || releaseQty < 0) {
          throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.release_qty') } }))
        }
        if (releaseQty > packQty) {
          throw new Error(i18next.t('text.x_exceed_limit', { state: { x: i18next.t('label.release_qty') } }))
        }
        calcedRecord.releaseUomValue = releaseQty * uomValue
      } else {
        if (releaseUomValue === undefined || releaseUomValue < 0) {
          throw new Error(
            i18next.t('text.x_should_be_positive', { state: { x: i18next.t('label.release_uom_value') } })
          )
        }

        if (releaseUomValue > packQty * uomValue) {
          throw new Error(i18next.t('text.x_exceed_limit', { state: { x: i18next.t('label.release_uom_value') } }))
        }

        if (releaseUomValue % uomValue) {
          throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('label.release_uom_value') } }))
        }

        calcedRecord.releaseQty = releaseUomValue / uomValue
      }
    }

    return calcedRecord
  }

  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
        this._showAddProducts = true
      } else {
        this._bizplaceId = ''
        this._bizplaceName = ''
      }

      return bizplaces
    }
  }

  async _getOriginalArrivalNotice(gan) {
    const response = await client.query({
      query: gql`
        query arrivalNotice($name: String!) {
          arrivalNotice(name: $name) {
            name
            bizplace {
              id
              name
            }
            containerNo
            containerSize
            ownTransport
            crossDocking
            releaseGood {
              id
            }
            etaDate
            looseItem
            deliveryOrderNo
            status
            truckNo
            refNo
            refNo2
            refNo3
            importCargo
            attachment {
              id
              name
              refBy
              path
              mimetype
            }
            orderProducts {
              id
              batchId
              batchIdRef
              adjustedBatchId
              adjustedBatchIdRef
              product {
                id
                name
                description
              }
              productDetail {
                id
              }
              remark
              unitPrice
              adjustedUnitPrice
              status
              packingType
              adjustedPackingType
              packingSize
              uomValue
              adjustedUomValue
              uom
              adjustedUom
              packQty
              adjustedPackQty
              totalUomValue
              adjustedTotalUomValue
              palletQty
              adjustedPalletQty
              manufactureDate
              releaseQty
              releaseUomValue
            }
            orderVass {
              vas {
                name
                operationGuide
                operationGuideType
              }
              set
              targetType
              targetBatchId
              targetProduct {
                id
                name
                description
              }
              packingType
              qty
              uomValue
              otherTarget
              description
              remark
              status
              operationGuide
            }
          }
        }
      `,
      variables: { name: gan }
    })

    if (!response.errors) {
      const arrivalNotice = response.data.arrivalNotice
      let orderProducts = arrivalNotice.orderProducts
      orderProducts = orderProducts.map(orderProduct => {
        return {
          ...orderProduct,
          productName: orderProduct.product.name
        }
      })

      this._refNo = arrivalNotice.refNo || ''
      this._refNo2 = arrivalNotice.refNo2 || ''
      this._refNo3 = arrivalNotice.refNo3 || ''
      this._containerNo = arrivalNotice.containerNo || ''
      this._containerSize = arrivalNotice.containerSize || ''
      this._bizplaces = arrivalNotice.bizplace
      this._bizplaceId = arrivalNotice.bizplace.id
      this._bizplaceName = arrivalNotice.bizplace.name

      this._hasContainer = arrivalNotice.containerNo ? true : false
      this._etaDate = arrivalNotice.etaDate
      this._deliveryOrderNo = arrivalNotice.deliveryOrderNo || ''
      this._truckNo = arrivalNotice.truckNo || ''
      this._ownTransport = arrivalNotice.ownTransport
      if (!this._ownTransport) {
        this._warehouseTransport = true
      }
      this._crossDocking = arrivalNotice.crossDocking
      this._importedOrder = arrivalNotice.importCargo
      this.productData = { records: orderProducts }
    }
  }

  async _generateArrivalNotice() {
    try {
      this._validateForm()
      this._validateProducts()
      this._validateVas()

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

      if (!result.value) return

      let arrivalNotice = this._getFormInfo()
      delete arrivalNotice.warehouseTransport
      arrivalNotice.orderProducts = this._getOrderProducts()
      const fileUploader = this._document?.files ? this._document.files : undefined

      if (arrivalNotice.orderProducts.some(orderProduct => !orderProduct.palletQty)) {
        const result = await CustomAlert({
          title: i18next.t('title.are_you_sure'),
          text: i18next.t('text.there_is_no_pallet_qty'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) return
      }
      await this._executeRelatedTrxs()
      arrivalNotice.orderVass = this._getOrderVass()

      delete arrivalNotice.bizplaceId
      delete arrivalNotice.bizplaceName

      const response = await client.mutate({
        mutation: gql`
          mutation generateArrivalNotice($arrivalNotice: NewArrivalNotice!, $files: [Upload!]) {
            generateArrivalNotice(arrivalNotice: $arrivalNotice, files: $files) {
              id
              name
              crossDocking
            }
          }
        `,
        variables: {
          arrivalNotice: {
            ...arrivalNotice,
            partnerBizplaceId: this._bizplaceId,
            ownTransport: this._importedOrder ? true : this._ownTransport
          },
          files: fileUploader
        },
        context: { hasUpload: true }
      })

      if (!response.errors) {
        this._clearView()
        const ganNo = response.data.generateArrivalNotice.name
        const isCrossDocking = response.data.generateArrivalNotice.crossDocking
        if (!isCrossDocking) {
          navigate(`arrival_notice_detail/${ganNo}`)
        } else {
          const result = await CustomAlert({
            title: i18next.t('title.move_to_page', { state: { page: i18next.t('title.create_release_order') } }),
            text: i18next.t('text.creating_release_order_is_required'),
            confirmButton: { text: i18next.t('button.move') },
            cancelButton: { text: i18next.t('button.cancel') }
          })

          if (!result.value) {
            navigate(`arrival_notice_detail/${ganNo}`)
          } else {
            navigate(`create_release_order/${ganNo}`)
          }
        }

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

  async _executeRelatedTrxs() {
    if (!this.vasGrist.dirtyData || !this.vasGrist.dirtyData.records || !this.vasGrist.dirtyData.records.length) return

    try {
      this.vasData = {
        ...this.vasData,
        records: await (async () => {
          const records = this.vasGrist.dirtyData.records
          for (let record of records) {
            const orderVass = record.orderVass
            for (let orderVas of orderVass) {
              if (orderVas.operationGuide && orderVas.operationGuide.transactions) {
                const trxs = orderVas.operationGuide.transactions
                for (let trx of trxs) {
                  orderVas.operationGuide = await trx(orderVas.operationGuide)
                }
              }
            }
          }
        })()
      }
    } catch (e) {
      throw e
    }
  }

  _validateImportCargo() {
    //Validation for Import Cargo
    if (this._importedOrder) {
      if (!this._enableTransportationServiceSetting) {
        this._disableTransport = true
        this._ownTransportInput.checked = true
        this._ownTransport = true
      } else {
        if (this._enableTransportForCustomClearanceSetting) {
          this._disableTransport = false
        } else {
          this._disableTransport = true
          this._ownTransportInput.checked = true
          this._ownTransport = true
          this._warehouseTransportInput.checked = false
          this._warehouseTransport = false
        }
      }
    } else {
      if (!this._enableTransportationServiceSetting) {
        this._disableTransport = true
        this._ownTransportInput.checked = true
        this._ownTransport = true
      } else {
        this._disableTransport = false
      }
    }
  }

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

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

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

    if (this._hasContainer) if (!this.containerNo.value) throw new Error(i18next.t('text.container_no_is_empty'))

    if (this._ownTransport && this._warehouseTransport)
      throw new Error(i18next.t('text.you_can_only_select_one_transport_type'))
    else if (!this._ownTransport && !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, palletQty)
    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')
          }
        })
      )
    }

    if (this._crossDocking && records.every(({ releaseQty, releaseUomValue }) => !releaseQty || !releaseUomValue)) {
      throw new Error(
        i18next.t('text.invalid_x', {
          state: {
            x: `${i18next.t('label.release_qty')}, ${i18next.t('label.release_uom_value')}`
          }
        })
      )
    }
  }

  _validateVas() {
    if (!this.vasGrist.dirtyData.records.every(record => record.ready)) throw new Error('there_is_not_ready_vas')
  }

  _updateVasTargets(isFieldChanged) {
    if (!this.vasGrist.dirtyData || !this.vasGrist.dirtyData.records || !this.vasGrist.dirtyData.records.length) return

    if (!this.productGrist.dirtyData?.records?.length) {
      this.vasData = { ...this.vasData, records: [] }
      return
    }

    const standardProductList = isFieldChanged ? this.productGrist.dirtyData.records : this.productData.records
    const batchPackPairs = standardProductList
      .filter(record => record.batchId && record.product && record.product.id && record.packingType)
      .map(record => `${record.batchId}-${record.packingType}`)

    const productPackPairs = standardProductList
      .filter(record => record.product && record.product.id)
      .map(record => `${record.product.id}-${record.packingType}`)

    const batchProductPackPairs = standardProductList
      .filter(record => record.batchId && record.product && record.product.id && record.packingType)
      .map(record => `${record.batchId}-${record.product.id}-${record.packingType}`)

    this.vasData = {
      ...this.vasData,
      records: this.vasGrist.dirtyData.records.map(record => {
        if (
          record.targetType === VAS_BATCH_NO_TYPE &&
          batchPackPairs.indexOf(`${record.target}-${record.packingType}`) < 0
        ) {
          return {
            ...record,
            ready: false,
            target: null,
            targetDisplay: null,
            packingType: null,
            qty: 1
          }
        } else if (
          record.targetType === VAS_PRODUCT_TYPE &&
          productPackPairs.indexOf(`${record.target}-${record.packingType}`) < 0
        ) {
          return {
            ...record,
            ready: false,
            target: null,
            targetDisplay: null,
            packingType: null,
            qty: 1
          }
        } else if (
          record.targetType === VAS_BATCH_AND_PRODUCT_TYPE &&
          batchProductPackPairs.indexOf(`${record.target.batchId}-${record.target.productId}-${record.packingType}`) < 0
        ) {
          return {
            ...record,
            ready: false,
            target: null,
            targetDisplay: null,
            packingType: null,
            qty: 1
          }
        } else {
          return record
        }
      })
    }
  }

  _getFormInfo() {
    const formData = this._serializeForm(this.arrivalNoticeForm)
    delete formData.importedOrder
    return formData
  }

  _getOrderProducts() {
    return this.productGrist.dirtyData.records.map(record => {
      let orderProduct = {
        batchId: record.batchId ? record.batchId.trim() : null,
        batchIdRef: record?.batchIdRef ? record.batchIdRef.trim() : null,
        product: { id: record.product.id },
        productDetail: { id: record?.productDetailId || record?.productDetail?.id },
        packingType: record.packingType,
        packingSize: record?.product?.packingSize ? record.product.packingSize : record.packingSize,
        uomValue: record?.uomValue ? record.uomValue : 0,
        uom: record.uom,
        packQty: parseFloat(record.packQty).toFixed(3),
        totalUomValue: record.totalUomValue,
        totalUomValue: record?.totalUomValue ? record?.totalUomValue : 0,
        unitPrice: record?.unitPrice ? record.unitPrice : 0,
        remark: record?.remark ? record.remark : null,
        manufactureDate: record?.manufactureDate ? record.manufactureDate : null
      }

      if (record.palletQty) orderProduct.palletQty = record.palletQty
      if (this._crossDocking && record.releaseQty !== undefined && record.releaseUomValue !== undefined) {
        orderProduct.releaseQty = record.releaseQty
        orderProduct.releaseUomValue = record.releaseUomValue
      }

      return orderProduct
    })
  }

  _getOrderVass() {
    if (!this.vasGrist.dirtyData?.records?.length) {
      return []
    }

    const records = this.vasGrist.dirtyData.records

    return records
      .map((record, idx) => {
        const orderVass = record.orderVass
        return orderVass.map(orderVas => {
          let result = {
            set: idx + 1,
            vas: { id: orderVas.vas.id },
            remark: orderVas.remark,
            targetType: record.targetType
          }

          if (orderVas.operationGuide && orderVas.operationGuide.data) {
            result.operationGuide = JSON.stringify(orderVas.operationGuide)
          }

          if (record.targetType === VAS_BATCH_NO_TYPE) {
            result.targetBatchId = record.target
            result.packingType = record.packingType
            result.qty = record.qty
          } else if (record.targetType === VAS_PRODUCT_TYPE) {
            result.targetProduct = { id: record.target }
            result.packingType = record.packingType
            result.qty = record.qty
          } else if (record.targetType === VAS_BATCH_AND_PRODUCT_TYPE) {
            result.targetBatchId = record.target.batchId
            result.targetProduct = { id: record.target.productId }
            result.targetProductDetail = { id: record.target.productDetailId }
            result.packingType = record.packingType
            result.qty = record.qty
            result.uomValue = record.uomValue
          } else {
            result.otherTarget = record.target
          }

          return result
        })
      })
      .flat()
  }

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

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

  openVasCreatePopup(record) {
    try {
      this.checkProductValidity()
      openPopup(
        html`
          <vas-create-popup
            .targetList="${this.productGrist.dirtyData.records
            .map(record => {
              let packQty = record.packQty - (record.releaseQty || 0)

              if (this.vasData.records.length > 0) {
                const existVasData = this.vasData.records.filter(vasRecord => {
                  switch (vasRecord.targetType) {
                    case VAS_BATCH_AND_PRODUCT_TYPE:
                      return (
                        record.batchId === vasRecord.target.batchId &&
                        record.product.id === vasRecord.target.productId
                      )
                    case VAS_BATCH_NO_TYPE:
                      return record.batchId === vasRecord.target
                    case VAS_PRODUCT_TYPE:
                      return record.product.id === vasRecord.target
                  }
                })

                if (existVasData.length > 0) {
                  let assignedQty = 0

                  existVasData.forEach(dt => {
                    assignedQty += dt.qty
                  })

                  packQty -= assignedQty
                }
              }

              delete record.__dirty__
              delete record.__dirtyfields__
              return {
                ...record,
                packQty,
                unitUomValue: record.uomValue,
                totalUomValue: record.uomValue * packQty
              }
            })
            .filter(record => record.packQty > 0)}"
            .vasList="${this.vasData.records}"
            .record="${record}"
            @completed="${e => {
            const newRecords = e.detail

            if (this.vasGrist.dirtyData.records.length !== this._selectedVasRecordIdx) {
              // update existing vasData records
              this.vasGrist.dirtyData.records.splice(this._selectedVasRecordIdx, 1, ...newRecords)

              this.vasData = {
                ...this.vasData,
                records: [...this.vasGrist.dirtyData.records]
              }
            } else {
              this.vasData = {
                ...this.vasData,
                records: [...this.vasGrist.dirtyData.records, ...newRecords]
              }
            }
          }}"
          ></vas-create-popup>
        `,
        {
          backdrop: true,
          size: 'large',
          title: i18next.t('title.vas_order')
        }
      )
    } catch (e) {
      this._showToast(e)
    }
  }

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

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

  excelColumns() {
    const productColumns = [
      {
        type: 'string',
        name: 'batchId',
        header: i18next.t('field.batch_id'),
        imex: { header: i18next.t('field.batch_id'), key: 'batchId', width: 25, type: 'string' },
        width: 100
      },
      {
        type: 'string',
        name: 'productSKU',
        header: i18next.t('field.sku'),
        imex: { header: i18next.t('field.sku'), key: 'productSKU', width: 25, type: 'string' },
        width: 100
      },
      {
        type: 'string',
        name: 'packingType',
        header: i18next.t('field.packing_type'),
        imex: { header: i18next.t('field.packing_type'), key: 'packingType', width: 25, type: 'string' },
        width: 100
      },
      {
        type: 'float',
        name: 'packQty',
        header: i18next.t('field.pack_qty'),
        imex: { header: i18next.t('field.pack_qty'), key: 'packQty', width: 25, type: 'float' },
        width: 100
      },
      {
        type: 'integer',
        name: 'palletQty',
        header: i18next.t('field.pallet_qty'),
        imex: { header: i18next.t('field.pallet_qty'), key: 'palletQty', width: 25, type: 'float' },
        width: 100
      },
      {
        type: 'date',
        name: 'manufactureDate',
        header: i18next.t('field.manufacture_date'),
        imex: { header: i18next.t('field.manufacture_date'), key: 'manufactureDate', width: 25, type: 'string' },
        width: 120
      },
      {
        type: 'string',
        name: 'batchIdRef',
        header: i18next.t('field.batch_id_ref'),
        imex: { header: i18next.t('field.batch_id_ref'), key: 'batchIdRef', width: 25, type: 'string' },
        width: 100
      },
      {
        type: 'float',
        name: 'unitPrice',
        header: i18next.t('field.unit_price'),
        imex: { header: i18next.t('field.unit_price'), key: 'unitPrice', width: 25, type: 'float' },
        width: 100
      },
      {
        type: 'string',
        name: 'remark',
        header: i18next.t('field.remark'),
        imex: { header: i18next.t('field.remark'), key: 'remark', width: 25, type: 'string' },
        width: 100
      }
    ]

    return productColumns
  }

  async _exportableData() {
    try {
      var headerSetting = [
        ...this.excelColumns()
          .filter(column => column.type !== 'gutter' && column.imex !== undefined)
          .map(column => {
            return column.imex
          })
      ]

      return { header: headerSetting, data: [] }
    } catch (e) {
      this._showToast(e)
    }
  }

  async bulkUploadValidateOrderProducts(patches) {
    const response = await client.query({
      query: gql`
        query bulkUploadValidateOrderProducts($orderProducts: [NewOrderProduct], $partnerBizplaceId: String!) {
          bulkUploadValidateOrderProducts(orderProducts: $orderProducts, partnerBizplaceId: $partnerBizplaceId) {
            id
            packingType
            packingSize
            uom
            uomValue
            totalUomValue
            packQty
            palletQty
            manufactureDate
            batchId
            batchIdRef
            unitPrice
            remark
            productSKU
            productName
            isError
            product {
              id
              name
              sku
              description
              type
              primaryUnit
              primaryValue
            }
          }
        }
      `,
      variables: { orderProducts: patches, partnerBizplaceId: this._bizplaceId }
    })

    if (!response.errors) {
      const data = response.data.bulkUploadValidateOrderProducts.map(item => {
        return {
          ...item,
          productName: item?.productName,
          unitPrice: parseFloat(item.unitPrice) || '',
          packQty: parseFloat(item.packQty).toFixed(3) || '',
          palletQty: parseFloat(item.palletQty) || ''
        }
      })
      this.productData = {
        ...this.productData,
        records: data.map((dt, idx) => {
          return {
            ...dt,
            id: idx,
            name: idx,
            __dirty__: '+'
          }
        })
      }

      this.productGrist.fetch()
    }
  }

  async importHandler(patches) {
    patches.map(itm => {
      if (itm?.batchId) itm.batchId = itm.batchId.trim()
      if (itm?.batchIdRef) itm.batchIdRef = itm.batchIdRef.trim()

      itm.unitPrice = parseFloat(itm.unitPrice) || ''
      if (itm.manufactureDate) {
        let mdt = new Date(itm.manufactureDate)
        itm.manufactureDate =
          mdt < new Date() ? `${mdt.getFullYear()}-${mdt.getMonth() + 1}-${mdt.getDate()}` || '' : ''
      } else {
        delete itm.manufactureDate
      }
      itm.packQty = parseFloat(itm.packQty).toFixed(3) || ''
      itm.palletQty = parseFloat(itm.palletQty) || ''
    })

    this.productData = {
      records: [...patches]
    }

    const orderProducts = patches.map(patch => {
      delete patch.cuFlag
      return {
        ...patch,
        unitPrice: parseFloat(patch.unitPrice) || 0,
        packQty: parseFloat(patch.packQty).toFixed(3) || 0,
        palletQty: parseFloat(patch.palletQty) || 0
      }
    })
    await this.bulkUploadValidateOrderProducts(orderProducts)
    history.back()
  }

  async _importableData(records) {
    try {
      if (this._bizplaceId) {
        records = records
          .filter(record => record.productSKU)
          .map(record => {
            return {
              ...record
            }
          })

        openPopup(
          html`
            <import-pop-up
              .records=${records}
              .config=${{
              rows: this.productGristConfig.rows,
              columns: [...this.excelColumns().filter(column => column.imex !== undefined)]
            }}
              .importHandler="${await this.importHandler.bind(this)}"
            ></import-pop-up>
          `,
          {
            backdrop: true,
            escapable: false,
            size: 'large',
            title: i18next.t('title.import')
          }
        )
      } else {
        throw new Error(i18next.t('text.please_select_a_company'))
      }
    } catch (e) {
      this._showToast(e)
    }
  }

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

window.customElements.define('duplicate-arrival-notice', DuplicateArrivalNotice)
