import '@things-factory/barcode-ui'
import '@things-factory/grist-ui'
import './return-pallet-check-popup'
import './transport-vehicles-popup'

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

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

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

class LoadingProduct extends connect(store)(localize(i18next)(PageView)) {
  static get properties() {
    return {
      _releaseGoodNo: String,
      _ownCollection: Boolean,
      pickedProductConfig: Object,
      pickedProductData: Object,
      deliveryOrderConfig: Object,
      deliveryOrderData: Object,
      loadedProductConfig: Object,
      loadedProductData: Object,
      _selectedTaskStatus: String,
      transportVehicles: Array,
      _hasVas: Boolean,
      _requireDeliveryInformation: Boolean,
      _enableLoadingSelectAll: Boolean
    }
  }

  static get styles() {
    return [
      SingleColumnFormStyles,
      MultiColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          overflow: auto;
          flex: 1;
        }
        .left-column {
          flex: 1;
          overflow: hidden;
          display: flex;
          flex-direction: column;
        }
        .right-column {
          flex: 1;
          overflow: auto;
          display: flex;
          flex-direction: column;
        }
        data-grist {
          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);
        }

        .select-all-button {
          margin: 10px;
          background-color: var(--button-background-color);
          border: var(--button-border);
          border-radius: var(--button-border-radius);
          padding: var(--button-padding);
          color: var(--button-color);
          font: var(--button-font);
          text-transform: var(--button-text-transform);
        }

        h2 + data-grist {
          padding-top: var(--grist-title-with-grid-padding);
        }
        fieldset[hidden] {
          display: none;
        }
        @media (max-width: 460px) {
          :host {
            display: block;
          }
          .grist {
            min-height: 500px;
          }
        }
      `
    ]
  }

  get context() {
    var actions = []
    if (this._releaseGoodNo) {
      actions.push({
        title: i18next.t('button.complete'),
        action: this._completeHandler.bind(this),
        ...CommonButtonStyles.submit
      })
    }

    if (
      this._selectedTaskStatus === 'EXECUTING' ||
      this.pickedProductData.records.filter(record => record['__selected__'] == true).length > 0
    ) {
      actions.push({
        title: i18next.t('button.load'),
        action: this._loading.bind(this),
        ...CommonButtonStyles.load
      })
    }

    if (this._selectedDeliveryOrder) {
      actions.push({
        title: i18next.t('button.undo'),
        action: this._undoLoading.bind(this),
        ...CommonButtonStyles.undo
      })
    }

    return {
      title: i18next.t('title.loading'),
      help: 'operato-wms/outbound/loading-product',
      actions
    }
  }

  get releaseGoodNoInput() {
    return this.shadowRoot.querySelector('barcode-scanable-input[name=releaseGoodNo]').shadowRoot.querySelector('input')
  }

  get infoForm() {
    return this.shadowRoot.querySelector('form#info-form')
  }

  get inputForm() {
    return this.shadowRoot.querySelector('form#input-form')
  }

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

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

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

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

  get deliveryOrderGrist() {
    return this.shadowRoot.querySelector('data-grist#delivery-order-grist')
  }

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

  get scannable() {
    return this._selectedTaskStatus && this._selectedTaskStatus === WORKSHEET_STATUS.EXECUTING.value
  }

  render() {
    return html`
      <form id="info-form" class="multi-column-form">
        <fieldset>
          <legend>${i18next.t('title.scan_area')}</legend>
          <label>${i18next.t('label.release_good_no')}</label>
          <barcode-scanable-input
            name="releaseGoodNo"
            custom-input
            @keypress="${async e => {
              if (e.keyCode === 13) {
                e.preventDefault()
                if (this.releaseGoodNoInput.value) {
                  this._clearView()
                  await this._fetchLoadingWorksheet(this.releaseGoodNoInput.value)
                  await this._fetchDeliveryOrders(this._releaseGoodNo)
                  if (!this._ownCollection) {
                    await this._fetchTransportVehicle()
                  }
                }
              }
            }}"
          ></barcode-scanable-input>
        </fieldset>

        <fieldset>
          <legend>${`${i18next.t('title.release_order')}: ${this._releaseGoodNo}`}</legend>

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

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

          <label>${i18next.t('label.started_at')}</label>
          <input name="startedAt" type="datetime-local" readonly />
        </fieldset>
      </form>

      <div class="grist">
        <div class="left-column">
          <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.loading')}</h2>
          ${isMobileDevice() && this._enableLoadingSelectAll
            ? html`
                <button type="button" class="select-all-button" @click="${this._selectAll.bind(this)}">
                  Select All
                </button>
              `
            : ''}
          <data-grist
            id="picked-product-grist"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.pickedProductConfig}
            .data=${this.pickedProductData}
            @record-change="${this._onProductChangeHandler.bind(this)}"
          ></data-grist>

          <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.delivery_orders')}</h2>
          <data-grist
            id="delivery-order-grist"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.deliveryOrderConfig}
            .data=${this.deliveryOrderData}
          ></data-grist>
        </div>

        <div class="right-column">
          <form id="input-form" class="single-column-form">
            <fieldset>
              <legend>${i18next.t('label.delivery_information')}</legend>
              <input
                id="ownCollection"
                type="checkbox"
                name="ownCollection"
                ?checked="${this._ownCollection}"
                @change="${e => (this._ownCollection = e.currentTarget.checked)}"
              />
              <label for="ownCollection">${i18next.t('label.own_collection')}</label>

              <label>${i18next.t('label.lorry_no')}</label>
              <input ?hidden=${!this._ownCollection} name="truckNo" />
              <input
                ?hidden=${this._ownCollection}
                name="warehouseTruck"
                readonly
                @click="${this._openBufferSelector.bind(this)}"
              />

              <label>${i18next.t('label.total_pallet_qty')}</label>
              <input name="palletQty" />
            </fieldset>
          </form>
          ${this._selectedDeliveryOrder
            ? html`
                <h2><mwc-icon>list_alt</mwc-icon>${this._selectedDeliveryOrder.name} - ${i18next.t('title.loaded')}</h2>
                <data-grist
                  id="loaded-product-grist"
                  .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
                  .config=${this.loadedProductConfig}
                  .data=${this.loadedProductData}
                ></data-grist>
              `
            : ''}
        </div>
      </div>
    `
  }

  constructor() {
    super()
    this.pickedProductData = { records: [] }
    this.deliveryOrderData = { records: [] }
    this.loadedProductData = { records: [] }
    this._releaseGoodNo = ''
    this._ownCollection = true
    this._selectedTaskStatus = null
    this._hasVas = false
  }

  updated(changedProps) {
    if (changedProps.has('_releaseGoodNo')) {
      this.updateContext()
    }
  }

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

  async pageInitialized() {
    this._hasVas = false

    let [enableToteScanning, enableLoadingDeliveryInformation, enableLoadingSelectAll] = await Promise.all([
      fetchSettingRule('enable-tote-scanning'),
      fetchSettingRule('enable-loading-delivery-information'),
      fetchSettingRule('enable-loading-select-all')
    ])
    this._requireDeliveryInformation = enableLoadingDeliveryInformation
    this._enableLoadingSelectAll = enableLoadingSelectAll || false

    const toteScanningValue = parseInt(enableToteScanning || '0', 10)

    let configColumns = [
      { type: 'gutter', gutterName: 'sequence' },
      { type: 'gutter', gutterName: 'row-selector', multiple: true }
    ]

    let fields = [
      'palletId',
      'productSku',
      'product',
      'packingType',
      'packingSize',
      'batchId',
      'batchIdRef',
      'releaseQty',
      'loadedQty'
    ]

    if (toteScanningValue >= 1) {
      configColumns.push({
        type: 'string',
        name: 'toteName',
        header: i18next.t('field.tote'),
        width: 140
      })

      fields = this._hasVas
        ? [
            'hasVas',
            'palletId',
            'productSku',
            'product',
            'packingType',
            'packingSize',
            'batchId',
            'batchIdRef',
            'releaseQty',
            'pickedQty',
            'loadedQty'
          ]
        : [
            'palletId',
            'productSku',
            'product',
            'packingType',
            'packingSize',
            'batchId',
            'batchIdRef',
            'pickedQty',
            'loadedQty'
          ]
    }

    if (this._hasVas) {
      configColumns.push({
        type: 'checkbox',
        name: 'hasVas',
        header: i18next.t('label.vas'),
        width: 40
      })
    }

    configColumns.push(
      {
        type: 'string',
        name: 'palletId',
        header: i18next.t('field.lot_id'),
        width: 140
      },
      {
        type: 'string',
        name: 'productSku',
        header: i18next.t('field.sku'),
        width: 140
      },
      {
        type: 'object',
        name: 'product',
        header: i18next.t('field.product'),
        width: 140
      },
      {
        type: 'string',
        name: 'packingType',
        header: i18next.t('field.packing_type'),
        width: 140
      },
      {
        type: 'string',
        name: 'packingSize',
        header: i18next.t('field.packing_size'),
        width: 140
      },
      {
        type: 'string',
        name: 'batchId',
        header: i18next.t('field.batch_id'),
        width: 140
      },
      {
        type: 'string',
        name: 'batchIdRef',
        header: i18next.t('field.batch_no_ref'),
        width: 140
      },
      {
        type: 'string',
        name: 'releaseUomValue',
        header: i18next.t('field.release_uom_value'),
        width: 100
      },
      {
        type: 'string',
        name: 'uom',
        header: i18next.t('field.uom'),
        width: 80
      }
    )

    if (this._hasVas) {
      configColumns.push({
        type: 'float',
        name: 'releaseQty',
        header: i18next.t('field.release_qty'),
        width: 100
      })
    }
    configColumns.push(
      {
        type: 'float',
        name: 'pickedQty',
        header: i18next.t('field.picked_qty'),
        width: 100
      },
      {
        type: 'float',
        name: 'loadedQty',
        header: i18next.t('field.loaded_qty'),
        record: { editable: true },
        width: 100
      }
    )

    this.pickedProductConfig = {
      rows: {
        appendable: false,
        selectable: { multiple: true },
        handlers: {
          click: (columns, data, column, record, rowIndex) => {
            if (data.records.length && record) {
              if (this._selectedOrderInventory && this._selectedOrderInventory.name === record.name) {
                return
              }
              this._selectedTaskStatus = null
              this._selectedTaskStatus = record.status
              this.updateContext()
            }
          }
        }
      },
      pagination: { infinite: true },
      list: {
        fields: [
          'hasVas',
          'toteName',
          'palletId',
          'productSku',
          'product',
          'packingType',
          'packingSize',
          'batchId',
          'batchIdRef',
          'releaseQty',
          'pickedQty',
          'loadedQty'
        ]
      },
      columns: configColumns
    }

    this.deliveryOrderConfig = {
      rows: {
        appendable: false,
        handlers: {
          click: (columns, data, column, record, rowIndex) => {
            if (data.records.length && record) {
              if (this._selectedDeliveryOrder && this._selectedDeliveryOrder.id === record.id) {
                return
              }
              this._selectedDeliveryOrder = record
              this._fetchLoadedProducts()
              this.updateContext()
            }
          }
        }
      },
      list: { fields: ['name', 'truck'] },
      pagination: { infinite: true },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'name',
          header: i18next.t('field.name'),
          width: 200
        },
        {
          type: 'string',
          name: 'truck',
          header: i18next.t('field.truck_no'),
          width: 140
        }
      ]
    }

    this.loadedProductConfig = {
      rows: { appendable: false, selectable: { multiple: true } },
      list: { fields: ['palletId', 'batchId', 'batchIdRef', 'releaseQty'] },
      pagination: { infinite: true },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'palletId',
          header: i18next.t('field.lot_id'),
          width: 140
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 140
        },
        {
          type: 'string',
          name: 'batchIdRef',
          header: i18next.t('field.batch_no_ref'),
          width: 140
        },
        {
          type: 'object',
          name: 'product',
          header: i18next.t('field.product'),
          width: 140
        },
        {
          type: 'number',
          name: 'pickedQty',
          header: i18next.t('field.qty'),
          width: 80
        },
        {
          type: 'number',
          name: 'releaseUomValue',
          header: i18next.t('field.uom_value'),
          width: 80
        },
        {
          type: 'string',
          name: 'uom',
          header: i18next.t('field.uom'),
          width: 80
        }
      ]
    }
  }

  pageUpdated() {
    if (this.active) {
      this._focusOnReleaseGoodField()
    }
  }

  _focusOnReleaseGoodField() {
    setTimeout(() => this.releaseGoodNoInput.focus(), 100)
  }

  async _fetchLoadingWorksheet(releaseGoodNo) {
    const response = await client.query({
      query: gql`
        query loadingWorksheet($releaseGoodNo: String!) {
          loadingWorksheet(releaseGoodNo: $releaseGoodNo) {
            worksheetInfo {
              releaseGood {
                name
              }
              bizplaceName
              refNo
              startedAt
              ownCollection
            }
            worksheetDetailInfos {
              name
              toteName
              palletId
              batchId
              batchIdRef
              packingType
              packingSize
              status
              product {
                id
                sku
                name
                description
              }
              qty
              pickedQty
              releaseQty
              releaseUomValue
              targetVas {
                qty
                outputQty
                product {
                  id
                }
                newProduct {
                  id
                  sku
                  description
                  packingType
                  name
                  uom
                }
                newProductDetail {
                  id
                  name
                  description
                  packingSize
                }
              }
              inventory {
                uom
              }
            }
          }
        }
      `,
      variables: { releaseGoodNo }
    })

    if (!response.errors) {
      this._releaseGoodNo = response.data.loadingWorksheet.worksheetInfo.releaseGood.name
      this._fillUpForm(this.infoForm, response.data.loadingWorksheet.worksheetInfo)
      this._ownCollection = response.data.loadingWorksheet.worksheetInfo.ownCollection

      this.pickedProductData = {
        records: response.data.loadingWorksheet.worksheetDetailInfos.map(record => {
          return {
            ...record,
            // product: record.product,
            productSku: record.product.sku,
            loadedQty: record.releaseQty,
            hasVas: record.targetVas || (record.releaseQty && record.pickedQty == 0) ? true : false,
            ...record.inventory
          }
        })
      }

      this._hasVas = this.pickedProductData.records.find(data => data.hasVas == true) ? true : false

      // causes grist unable to display data
      await this.pageInitialized()
      this.pickedProductData = { records: this.sortByNameField(this.pickedProductData) }
    } else {
      throw new Error(response.errors[0])
    }
  }

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

  async _loading() {
    try {
      this._validateLoading()
      const toteList = this.pickedProductGrist.selected.filter(itm => itm.toteName)

      let loadedWorksheetDetails = []

      if (toteList[0]?.toteName) {
        loadedWorksheetDetails = this.pickedProductGrist.selected
          .map(record => {
            return { name: record.name, loadedQty: record.loadedQty, toteName: record.toteName }
          })
          .filter(itm => !itm.toteName)

        let toteRecords = this.pickedProductGrist.data.records
          .filter(record => {
            return toteList.some(list => {
              return list.toteName == record.toteName
            })
          })
          .map(itm => {
            return { name: itm.name, loadedQty: itm.loadedQty, toteName: itm.toteName }
          })

        loadedWorksheetDetails = loadedWorksheetDetails.concat(toteRecords)
      } else {
        loadedWorksheetDetails = this.pickedProductGrist.selected.map(record => {
          return {
            name: record.name,
            loadedQty: record.loadedQty,
            toteName: record.toteName
          }
        })
      }

      let truckNo = null
      if (!this._ownCollection) {
        truckNo = this.warehouseTruckInput.value
      } else {
        truckNo = this.truckInput.value.toUpperCase().replace(/\s+/g, '')
      }

      const palletQty = this.palletQty.value
      const ownCollection = this._ownCollection
      const response = await client.mutate({
        mutation: gql`
          mutation loading(
            $loadedWorksheetDetails: [LoadedWorksheetDetail]!
            $releaseGoodNo: String!
            $orderInfo: WorksheetPatch
          ) {
            loading(
              loadedWorksheetDetails: $loadedWorksheetDetails
              releaseGoodNo: $releaseGoodNo
              orderInfo: $orderInfo
            )
          }
        `,
        variables: {
          loadedWorksheetDetails,
          releaseGoodNo: this._releaseGoodNo,
          orderInfo: {
            truckNo,
            palletQty,
            ownCollection
          }
        }
      })

      if (!response.errors) {
        this._clearView()
        await this._fetchLoadingWorksheet(this._releaseGoodNo)
        await this._fetchDeliveryOrders(this._releaseGoodNo)
        this._selectedTaskStatus = null
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _undoLoading() {
    try {
      this._validateUndoLoading()

      const response = await client.mutate({
        mutation: gql`
          mutation undoLoading($deliveryOrder: ObjectRef!, $palletIds: [String]!, $productIds: [String]!) {
            undoLoading(deliveryOrder: $deliveryOrder, palletIds: $palletIds, productIds: $productIds)
          }
        `,
        variables: {
          deliveryOrder: { id: this._selectedDeliveryOrder.id },
          palletIds: this.loadedProductData.records.map(item => item.palletId),
          productIds: this.loadedProductData.records.map(item => item.product.id)
        }
      })

      if (!response.errors) {
        this._clearView()
        await this._fetchLoadingWorksheet(this.releaseGoodNoInput.value)
        await this._fetchDeliveryOrders(this._releaseGoodNo)
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _fetchDeliveryOrders(releaseGoodNo) {
    const response = await client.query({
      query: gql`
        query deliveryOrderByReleaseGood($releaseGoodNo: String!) {
          deliveryOrderByReleaseGood(releaseGoodNo: $releaseGoodNo) {
            items {
              id
              name
              truck
              targetInventories {
                name
              }
            }
          }
        }
      `,
      variables: { releaseGoodNo }
    })

    if (!response.errors) {
      this.deliveryOrderData = {
        records: response.data.deliveryOrderByReleaseGood.items.map(item => {
          return {
            id: item.id,
            name: item.name,
            truck: item.truck
          }
        })
      }

      this.updateContext()
    } else {
      throw new Error(response.errors[0])
    }
  }

  async _fetchTransportVehicle() {
    const response = await client.query({
      query: gql`
        query transportVehicles($filters: [Filter!]) {
          transportVehicles(filters: $filters) {
            items {
              id
              name
              regNumber
              description
              size
              status
              updatedAt
              updater {
                id
                name
                description
              }
            }
            total
          }
        }
      `,
      variables: { filters: [] }
    })

    if (!response.errors) {
      this.transportVehicles = response.data.transportVehicles.items
    } else {
      throw new Error(response.errors[0])
    }
  }

  async _fetchLoadedProducts() {
    if (!this._selectedDeliveryOrder || !this._selectedDeliveryOrder.id) return

    const response = await client.query({
      query: gql`
        query orderInventories($filters: [Filter!]) {
          orderInventories(filters: $filters) {
            items {
              releaseQty
              type
              pickedQty
              releaseUomValue
              product {
                name
                description
              }
              inventory {
                palletId
                batchId
                batchIdRef
                uom
              }
            }
          }
        }
      `,
      variables: {
        filters: [
          {
            name: 'deliveryOrderId',
            operator: 'eq',
            value: this._selectedDeliveryOrder.id
          }
        ]
      }
    })

    if (!response.errors) {
      this.loadedProductData = {
        records: response.data.orderInventories.items.map(orderInventory => {
          return {
            ...orderInventory.inventory,
            ...orderInventory,
            pickedQty:
              this._hasVas &&
              (orderInventory.type === 'VAS_ORDER' ||
                orderInventory.pickedQty === 0 ||
                orderInventory.pickedQty > orderInventory.releaseQty)
                ? orderInventory.releaseQty
                : orderInventory.pickedQty,
            product: {
              name: orderInventory.product.name,
              description: orderInventory.product.inventory
            }
          }
        })
      }
    }
  }

  _validateLoading() {
    // 1. validate whethere there's selected product or not
    if (!this.pickedProductGrist.selected || !this.pickedProductGrist.selected.length) {
      throw new Error(i18next.t('text.there_is_no_selected_items'))
    }
    //2. validate whether delivery order is empty or not. It should only validate if enable-loading-delivery-information is set to true
    if (this._requireDeliveryInformation) {
      if (this._ownCollection) {
        if (!this.palletQty.value || !this.truckInput.value) {
          throw new Error(i18next.t('text.empty_field_in_delivery_information'))
        }
      } else if (!this.palletQty.value || !this.warehouseTruckInput.value) {
        throw new Error(i18next.t('text.empty_field_in_delivery_information'))
      }
    }
  }

  _validateUndoLoading() {
    if (!this.loadedProductData?.records?.length) {
      throw new Error(i18next.t('text.there_is_no_selected_items'))
    }
  }

  async _completeHandler() {
    try {
      this._validateComplete()

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

      if (!result.value) {
        return
      }

      if (this.pickedProductData && this.pickedProductData.records && this.pickedProductData.records.length) {
        this._validateRemainPallets(this.pickedProductData)
        return
      }

      this._complete()
    } catch (e) {
      this._showToast(e)
    }
  }

  _selectAll(event) {
    this.pickedProductData = {
      ...this.pickedProductData,
      records: [
        ...this.pickedProductData.records.map(record => {
          return {
            ...record,
            __selected__: true
          }
        })
      ]
    }

    this.pickedProductGrist.refresh()

    this.updateContext()
  }

  _onProductChangeHandler(event) {
    const beforeChange = event.detail.before
    const changeRecord = event.detail.after
    const changedColumn = event.detail.column.name

    if (changedColumn === 'loadedQty') {
      try {
        this._validateReleaseQty(changeRecord.loadedQty, beforeChange.releaseQty)
      } catch (e) {
        this._showToast(e)
        delete event.detail.after.loadedQty
      }
    }
  }

  _validateReleaseQty(loadedQty, pickedQty) {
    if (loadedQty > pickedQty || loadedQty <= 0) {
      throw new Error(i18next.t('text.invalid_quantity_input'))
    } else {
      return
    }
  }

  async _validateRemainPallets(data) {
    await sleep(1010)
    openPopup(
      html`
        <return-pallet-check-popup
          .data="${data}"
          @complete="${() => {
            this._complete()
          }}"
        ></return-pallet-check-popup>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: i18next.t('title.check_return_pallet')
      }
    )
  }

  async _complete() {
    try {
      const response = await client.mutate({
        mutation: gql`
          mutation completeLoading($releaseGoodNo: String!) {
            completeLoading(releaseGoodNo: $releaseGoodNo) {
              name
            }
          }
        `,
        variables: { releaseGoodNo: this._releaseGoodNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.loading_completed') })
        this._releaseGoodNo = null
        this.releaseGoodNoInput.value = ''
        this._clearView()
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _validateComplete() {
    if (!this._releaseGoodNo) throw new Error(i18next.t('text.there_is_no_release_order_no'))
  }

  _clearView() {
    this.pickedProductData = { records: [] }
    this.deliveryOrderData = { records: [] }
    this.loadedProductData = { records: [] }
    this.infoForm.reset()
    this.inputForm.reset()
    this.warehouseTruckInput.value = ''
    this._selectedTaskStatus = null
    this._selectedDeliveryOrder = null
    this.updateContext()
  }

  sortByNameField(items) {
    const nameField = 'batchId'

    return items?.records?.sort((a, b) => (a[nameField] > b[nameField] ? 1 : a[nameField] < b[nameField] ? -1 : 0))
  }

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

window.customElements.define('loading-product', LoadingProduct)
