import '@things-factory/grist-ui'
import '@things-factory/warehouse-ui'
import '../../components/attachment-viewer'
import '../../components/popup-note'
import '../../components/vas-templates'
import '../../inbound/carton-label-popup'
import '../../inbound/pallet-label-popup'
import './edit-product-popup'
import './proceed-edit-product-popup'
import './view-product-changes-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 { getRenderer } from '@things-factory/grist-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 {
  ORDER_PRODUCT_STATUS,
  ORDER_STATUS,
  VAS_BATCH_AND_PRODUCT_TYPE,
  VAS_BATCH_NO_TYPE,
  VAS_ETC_TYPE,
  VAS_PRODUCT_TYPE
} from '../../constants'

//vas --inbound
class ArrivalNoticeDetail extends localize(i18next)(PageView) {
  static get properties() {
    return {
      /**
       * @description
       * flag for whether use transportation from warehouse or not.
       * true =>
       */
      _ganNo: String,
      _ownTransport: Boolean,
      _crossDocking: Boolean,
      _releaseGood: Object,
      _importCargo: Boolean,
      _warehouseTransport: Boolean,
      _enableTransportationServiceSetting: Boolean,
      _importedOrder: Boolean,
      _hasContainer: Boolean,
      _looseItem: Boolean,
      _status: String,
      _bizplaceName: String,
      _attachments: Array,
      _template: Object,
      _showAssignWarehouse: Boolean,
      _vasExpanded: Boolean,
      _enableCartonLabel: Boolean,
      _strictProductSelection: Boolean,
      _ganProcessingSetting: String,
      containerSizes: Array,
      isUserBelongsDomain: Boolean,
      data: Object,
      productGristConfig: Object,
      vasGristConfig: Object,
      productData: Object,
      vasData: Object,
      arrivalNoticeId: String,
      _disableTransport: Boolean,
      userRole: Array,
      enableDirectInbound: Boolean,
      _enableLotIdInput: Boolean
    }
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow-x: auto;
        }
        .container {
          flex: 1;
          display: flex;
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        .guide-container {
          max-width: 30vw;
          display: flex;
          flex-direction: column;
        }
        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);
        }
        .vas[collapsable] {
          height: 40%;
        }
        .vas[collapsable][collapsed] {
          display: none;
        }
        data-grist#vas-grist {
          padding-top: 0px;
          height: 100%;
        }
        h2.vas-title {
          padding-bottom: 0px;
        }
        [options-wrap] *,
        [attachment-wrap] a * {
          vertical-align: middle;
        }
        [options-wrap] input[type='checkbox'] {
          left: 0;
        }
        [options-wrap] input[type='checkbox'] + label {
          margin-right: 20px;
          padding-left: 0;
        }
        [attachment-wrap] {
          grid-column: span 9 / auto;
        }
        [attachment-wrap] a {
          display: block;
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          color: var(--primary-color);
          font-size: var(--fontsize-default);
        }
        [attachment-wrap] {
          margin: 0;
          padding: 0;
          list-style: none;
        }
        [attachment-wrap] a mwc-icon {
          font-size: var(--fontsize-default);
        }
        barcode-tag {
          width: 100px;
          height: 100px;
          margin: 10px;
        }
        .form-container {
          display: flex;
        }
        .form-container > form {
          flex: 1;
        }
      `
    ]
  }

  get context() {
    var titleName = i18next.t('title.arrival_notice_detail')
    this._vasExpanded = false
    this._showAssignWarehouse = false
    const isNotAdmin = !this.userRoles?.some(itm => itm.name.toLowerCase().includes('admin'))

    var actions = [
      {
        title: i18next.t('button.back'),
        action: () => history.back(),
        ...CommonButtonStyles.back
      }
    ]

    if (
      this._status === ORDER_STATUS.PENDING.value &&
      this.userRoles?.find(itm => itm.name.toLowerCase().includes('admin'))
    ) {
      actions.push({
        title: i18next.t('button.edit_product'),
        action: this.openEditProductPopup.bind(this),
        ...CommonButtonStyles.add
      })
    }

    if (this.enableDirectInbound && this._status === ORDER_STATUS.PENDING.value && isNotAdmin) {
      actions.push({
        title: i18next.t('button.edit_product'),
        action: this.openEditProductPopup.bind(this),
        ...CommonButtonStyles.add
      })
    }

    if (this._status === ORDER_STATUS.PENDING.value) {
      actions.push({
        title: i18next.t('button.update_order_details'),
        action: this._updateArrivalNotice.bind(this),
        ...CommonButtonStyles.add
      })

      actions.push({
        title: i18next.t('button.delete'),
        action: this._deleteArrivalNotice.bind(this),
        ...CommonButtonStyles.delete
      })

      if (this._crossDocking && !this._releaseGood?.id) {
        actions.push({
          title: i18next.t('button.create_release_order'),
          action: () => navigate(`create_release_order/${this._ganNo}`)
        })
      } else {
        actions.push({
          title: i18next.t('button.confirm'),
          action: this._confirmArrivalNotice.bind(this),
          ...CommonButtonStyles.confirm
        })
      }
    }

    if (this.isUserBelongsDomain) {
      if (this._status === ORDER_STATUS.PROCESSING.value) {
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.edit_product'),
            action: this.openEditProductPopup.bind(this),
            ...CommonButtonStyles.add
          }
        )

        if (this._enableCartonLabel) {
          actions.push({
            title: i18next.t('button.carton_label_print'),
            action: this._openCartonLabelPrintPopup.bind(this),
            ...CommonButtonStyles.label
          })
        } else {
          actions.push({
            title: i18next.t('button.lot_label_print'),
            action: this._openLotLabelPrintPopup.bind(this),
            ...CommonButtonStyles.label
          })
        }
      } else if (this._status === ORDER_STATUS.PENDING_RECEIVE.value) {
        titleName = i18next.t('title.receive_arrival_notice')
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.reject'),
            action: this._rejectArrivalNotice.bind(this),
            ...CommonButtonStyles.reject
          },
          {
            title: i18next.t('button.receive'),
            action: this._receiveArrivalNotice.bind(this),
            ...CommonButtonStyles.receive
          }
        )
      } else if (this._status === ORDER_STATUS.INTRANSIT.value) {
        titleName = i18next.t('title.check_arrived_notice')
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.cancel'),
            action: this._cancelArrivalNotice.bind(this),
            ...CommonButtonStyles.cancel
          },
          {
            title: i18next.t('button.arrived'),
            action: this._checkArrivedNotice.bind(this),
            ...CommonButtonStyles.arrived
          }
        )
      } else if (this._status === ORDER_STATUS.ARRIVED.value) {
        titleName = i18next.t('title.assign_warehouse')
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.cancel'),
            action: this._cancelArrivalNotice.bind(this),
            ...CommonButtonStyles.cancel
          },
          {
            title: i18next.t('button.assign_warehouse'),
            action: this._assignBufferLocation.bind(this),
            ...CommonButtonStyles.warehouse
          }
        )
        this._showAssignWarehouse = true
      } else if (this._status === ORDER_STATUS.READY_TO_UNLOAD.value) {
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.cancel'),
            action: this._cancelArrivalNotice.bind(this),
            ...CommonButtonStyles.cancel
          },
          {
            title: i18next.t('button.edit_product'),
            action: this.openEditProductPopup.bind(this),
            ...CommonButtonStyles.add
          }
        )
      } else if (
        this._status === ORDER_STATUS.PENDING_APPROVAL.value &&
        this.productData.records.some(
          product =>
            product.status === ORDER_PRODUCT_STATUS.ADDED.value || product.status === ORDER_PRODUCT_STATUS.EDITED.value
        )
      ) {
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.product_changes'),
            action: this.openProductChangesPopup.bind(this),
            ...CommonButtonStyles.inspect
          }
        )
      } else if (this._status === ORDER_STATUS.PUTTING_AWAY.value) {
        actions.push({
          title: i18next.t('button.update_order_details'),
          action: this._updateArrivalNotice.bind(this),
          ...CommonButtonStyles.add
        })
      }
    } else {
      if (
        this._status === ORDER_STATUS.PENDING_APPROVAL.value &&
        this.productData.records.some(
          product =>
            product.status === ORDER_PRODUCT_STATUS.ADDED.value || product.status === ORDER_PRODUCT_STATUS.EDITED.value
        )
      ) {
        actions.push(
          {
            title: i18next.t('button.update_order_details'),
            action: this._updateArrivalNotice.bind(this),
            ...CommonButtonStyles.add
          },
          {
            title: i18next.t('button.inspect_changes'),
            action: this.openApproveProductPopup.bind(this),
            ...CommonButtonStyles.approve
          }
        )
      }

      if (this._status !== ORDER_STATUS.PENDING.value && this._status !== ORDER_STATUS.PENDING_APPROVAL.value) {
        actions.push({
          title: i18next.t('button.duplicate'),
          action: () => window.open(`duplicate_arrival_notice/${this._ganNo}`),
          ...CommonButtonStyles.copy
        })
      }

      if (
        this._status === ORDER_STATUS.INTRANSIT.value ||
        this._status === ORDER_STATUS.ARRIVED.value ||
        this._status === ORDER_STATUS.READY_TO_UNLOAD.value
      ) {
        actions.push({
          title: i18next.t('button.cancel'),
          action: this._cancelArrivalNotice.bind(this),
          ...CommonButtonStyles.cancel
        })
      }
    }
    if (this._status === ORDER_STATUS.REJECTED.value) {
      titleName = i18next.t('title.rejected_arrival_notice_detail')
    }

    if (this.enableDirectInbound && this._status === ORDER_STATUS.DONE.value) {
      actions.push({
        title: i18next.t('button.carton_label_print'),
        action: this._openCartonLabelPrintPopup.bind(this),
        ...CommonButtonStyles.label
      })
    }
    return {
      title: titleName,
      actions,
      help: 'operato-wms/arrival-notice/gan-detail'
    }
  }

  render() {
    return html`
      <div class="form-container">
        <form name="arrivalNotice" class="multi-column-form">
          <fieldset>
            <legend>${i18next.t('title.gan_no')}: ${this._ganNo}</legend>

            <label>${i18next.t('label.options')}</label>
            <div options-wrap>
              <input
                id="ownTransport"
                type="checkbox"
                name="ownTransport"
                ?checked="${this._ownTransport}"
                @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()
      }}"
                ?disabled=${this.determineStatus() || this._disableTransport}
              />
              <label for="ownTransport">${i18next.t('label.own_transport')}</label>

              <input
                id="warehouseTransport"
                type="checkbox"
                name="warehouseTransport"
                ?checked="${!this._ownTransport}"
                ?disabled=${this.determineStatus() || this._disableTransport}
                @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
      }}"
                ?disabled=${this.determineStatus()}
              />
              <label for="container">${i18next.t('label.container')}</label>

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

              <input
                id="importedOrder"
                type="checkbox"
                name="importCargo"
                ?checked="${this._importedOrder}"
                ?disabled=${this.determineStatus()}
              />
              <label for="importedOrder">${i18next.t('label.import_cargo')}</label>

              ${this._crossDocking
        ? html`
                    <input
                      id="crossDocking"
                      type="checkbox"
                      name="crossDocking"
                      ?checked="${this._crossDocking}"
                      disabled
                    />
                    <label for="crossDocking">${i18next.t('label.cross_docking')}</label>
                  `
        : ''}
            </div>

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

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

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

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

            <label>${i18next.t('label.eta_date')}</label>
            <input name="etaDate" type="date" disabled />

            <label ?hidden="${!this._warehouseTransport}">${i18next.t('label.transport_vehicle')}</label>
            <input name="transportVehicle" ?hidden="${!this._warehouseTransport}" ?readonly=${this.determineStatus()} />

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

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

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

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

            <label>${i18next.t('label.status')}</label>
            <select name="status" disabled>
              ${Object.keys(ORDER_STATUS).map(key => {
          const status = ORDER_STATUS[key]
          return html` <option value="${status.value}">${i18next.t(`label.${status.name}`)}</option> `
        })}
            </select>

            ${this._attachments?.length > 0
        ? html`
                  <label>${i18next.t('label.attachment')}</label>
                  <ul attachment-wrap>
                    ${(this._attachments || []).map(
          attachment =>
            html`
                          <li>
                            <a href="${location.origin}/attachment/${attachment.path}" download
                              ><mwc-icon>attach_file</mwc-icon> ${attachment.name}</a
                            >
                          </li>
                        `
        )}
                  </ul>
                `
        : ''}
          </fieldset>

          <fieldset style=${this._showAssignWarehouse ? '' : 'display: none'}>
            <legend>${i18next.t('title.assign_warehouse')}</legend>
            <label>${i18next.t('label.warehouse')}</label>
            <input
              id="buffer-location"
              name="buffer-location"
              readonly
              @click="${this._openBufferSelector.bind(this)}"
            />
          </fieldset>
        </form>
        <barcode-tag bcid="qrcode" .value=${this._ganNo} showLogo="true"></barcode-tag>
      </div>

      <div class="container">
        <div class="grist">
          <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.product')}</h2>
          <data-grist
            id="product-grist"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.productGristConfig}
            .data="${this.productData}"
          ></data-grist>

          <h2
            @click="${e => {
        this._vasExpanded = !this._vasExpanded
      }}"
          >
            <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 class="guide-container">${this._template}</div>
      </div>
    `
  }

  constructor() {
    super()
    this.productData = { records: [] }
    this.containerSizes = []
    this._downloadable = true
    this._attachments = []
    this.vasData = { records: [] }
    this._showAssignWarehouse = false
    this._vasExpanded = false
    this._strictProductSelection = false
    this._disableTransport = false
    this._importedOrder = false
    this._enableTransportationServiceSetting = false
    this.enableDirectInbound = false
    this._enableLotIdInput = false
  }

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

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

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

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

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

  get bufferLocationField() {
    return this.shadowRoot.querySelector('input#buffer-location')
  }

  async pageInitialized() {
    this.containerSizes = await getCodeByName('CONTAINER_SIZES')
    this._enableTransportationServiceSetting = await fetchSettingRule('enable-transportation-service')
    this.isUserBelongsDomain = await this._checkUserBelongsDomain()
    this.userRoles = await this.fetchUserRoleHandler()
    this._enableLotIdInput = await fetchSettingRule('enable-lot-id-input')
    this.enableDirectInbound = await fetchSettingRule('enable-direct-gan-order')
    this.vasGristConfig = {
      list: { fields: ['set', 'targetType', 'target', 'packingType', 'qty', 'vas', 'status', 'remark'] },
      pagination: { infinite: true },
      rows: {
        appendable: false,
        handlers: {
          click: (columns, data, column, record, rowIndex) => {
            if (record && record.vas && record.vas.operationGuideType === 'template') {
              this._template = document.createElement(record.vas.operationGuide)
              this._template.record = { ...record, operationGuide: JSON.parse(record.operationGuide) }
            } else {
              this._template = null
            }
          }
        }
      },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'set',
          header: i18next.t('field.set'),
          width: 80
        },
        {
          type: 'string',
          name: 'targetType',
          header: i18next.t('field.target_type'),
          width: 190
        },
        {
          type: 'string',
          name: 'target',
          header: i18next.t('field.target'),
          record: {
            renderer: (value, column, record, rowIndex, field) => {
              if (record.targetType === VAS_BATCH_NO_TYPE) {
                return getRenderer()(record.targetBatchId, column, record, rowIndex, field)
              } else if (record.targetType === VAS_PRODUCT_TYPE) {
                return getRenderer('object')(record.targetProduct, column, record, rowIndex, field)
              } else if (record.targetType === VAS_BATCH_AND_PRODUCT_TYPE) {
                return getRenderer()(
                  `${record.targetBatchId} / ${record.targetProduct.name}`,
                  column,
                  record,
                  rowIndex,
                  field
                )
              } else if (record.targetType === VAS_ETC_TYPE) {
                return getRenderer()(record.otherTarget, column, record, rowIndex, field)
              }
            }
          },

          width: 250
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 120
        },
        {
          type: 'integer',
          name: 'qty',
          header: i18next.t('field.qty'),
          width: 80
        },
        {
          type: 'integer',
          name: 'uomValue',
          header: i18next.t('field.uom_value'),
          width: 80
        },
        {
          type: 'object',
          name: 'vas',
          header: i18next.t('field.vas'),
          record: { options: { queryName: 'vass' } },
          width: 200
        },
        {
          type: 'string',
          name: 'status',
          header: i18next.t('field.status'),
          width: 150
        },
        {
          type: 'string',
          name: 'remark',
          header: i18next.t('field.remark'),
          width: 350
        },
        {
          type: 'string',
          name: 'description',
          header: i18next.t('field.comment'),
          width: 350
        }
      ]
    }
  }

  async pageUpdated(changes) {
    if (this.active) {
      this._ganNo = changes.resourceId || this._ganNo || ''
      this._template = null
      await this._fetchGAN()
    }
  }

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

    let productGristColumns = [
      { type: 'gutter', gutterName: 'sequence' },
      {
        type: 'string',
        name: 'batchId',
        header: i18next.t('field.batch_id'),
        width: 150
      },
      {
        type: 'string',
        name: 'productSku',
        header: i18next.t('field.sku'),
        width: 150
      },
      {
        type: 'object',
        name: 'product',
        header: i18next.t('field.product'),
        record: { options: { queryName: 'products' } },
        width: 350
      },
      {
        type: 'string',
        name: 'productBrand',
        header: i18next.t('field.brand'),
        width: 150
      },
      {
        type: 'string',
        name: 'packingType',
        header: i18next.t('field.packing_type'),
        width: 150
      },
      {
        type: 'float',
        name: 'uomValue',
        header: i18next.t('field.uom_value'),
        width: 100
      },
      {
        type: 'string',
        name: 'uom',
        header: i18next.t('field.uom'),
        width: 80
      },
      {
        type: 'float',
        name: 'packQty',
        header: i18next.t('field.pack_qty'),
        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'),
        width: 80
      },
      ...(this._enableLotIdInput
        ? [
          {
            type: 'string',
            name: 'palletId',
            header: i18next.t('field.lot_id'),
            imex: { header: i18next.t('field.lot_id'), key: 'palletId', width: 25, type: 'string' },
            record: { editable: true },
            width: 150
          }
        ]
        : []),
      {
        type: 'date',
        name: 'manufactureDate',
        header: i18next.t('field.manufacture_date'),
        width: 120
      },
      {
        type: 'string',
        name: 'batchIdRef',
        header: i18next.t('field.batch_no_ref'),
        width: 150
      },
      {
        type: 'float',
        name: 'unitPrice',
        header: i18next.t('field.unit_price'),
        width: 80
      },
      {
        type: 'string',
        name: 'remark',
        header: i18next.t('field.remark'),
        width: 300
      }
    ]

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

    const expDateColumn = {
      type: 'date',
      name: 'expDate',
      header: i18next.t('field.exp_date'),
      width: 120
    }

    const locationColumn = {
      type: 'object',
      name: 'location',
      header: i18next.t('field.location'),
      width: 150
    }

    const warehouseColumn = {
      type: 'object',
      name: 'warehouse',
      header: i18next.t('field.warehouse'),
      width: 150
    }

    function insertAfter(cols, anchorName, newCols) {
      const idx = cols.findIndex(c => c.name === anchorName)
      if (idx >= 0) cols.splice(idx + 1, 0, ...newCols)
    }

    if (this.enableDirectInbound) {
      const anchor = this._enableLotIdInput ? 'palletId' : 'palletQty'
      insertAfter(
        productGristColumns,
        anchor,
        [expDateColumn]
      )

      insertAfter(
        productGristColumns,
        'batchIdRef',
        [warehouseColumn, locationColumn]
      )
    }

    this.productGristConfig = {
      list: {
        fields: [
          'batchId',
          'productSku',
          'product',
          'packingType',
          'uomValue',
          'uom',
          'brand',
          'packQty',
          'totalUomValue',
          'palletQty',
          'palletId',
          'expDate',
          'manufactureDate',
          'batchIdRef',
          'warehouse',
          'location',
          'unitPrice',
          'remark'
        ]
      },
      pagination: { infinite: true },
      rows: {
        appendable: false,
        classifier: (record, rowIndex) => {
          return {
            emphasized:
              record.status === ORDER_PRODUCT_STATUS.ADDED.value || record.status === ORDER_PRODUCT_STATUS.EDITED.value
          }
        }
      },
      columns: productGristColumns
    }
  }

  async _fetchGAN() {
    if (!this._ganNo) return
    this._status = ''
    const response = await client.query({
      query: gql`
        query arrivalNotice($name: String!) {
          arrivalNotice(name: $name) {
            id
            bizplace {
              id
              name
              domain {
                id
              }
            }
            container
            containerNo
            containerSize
            ownTransport
            crossDocking
            releaseGood {
              id
            }
            etaDate
            looseItem
            deliveryOrderNo
            status
            truckNo
            transportVehicle
            refNo
            refNo2
            refNo3
            importCargo
            attachment {
              id
              name
              refBy
              path
              mimetype
            }
            orderProducts {
              id
              batchId
              batchIdRef
              adjustedBatchId
              adjustedBatchIdRef
              product {
                id
                name
                description
                sku
                brand
                isInventoryDecimal
                isRequiredCheckExpiry
              }
              productDetail {
                id
              }
              remark
              adjustedUnitPrice
              status
              packingType
              adjustedPackingType
              packingSize
              unitPrice
              uomValue
              adjustedUomValue
              uom
              adjustedUom
              packQty
              adjustedPackQty
              totalUomValue
              adjustedTotalUomValue
              palletQty
              palletId
              adjustedPalletQty
              expDate
              adjustedExpDate
              manufactureDate
              releaseQty
              releaseUomValue
              warehouse{
                name
                id
              }
              location {
                name
                id
              }
              adjustedLocation {
                name
                id
              }
              adjustedWarehouse {
                name
                id
              }
            }
            orderVass {
              vas {
                name
                operationGuide
                operationGuideType
              }
              set
              targetType
              targetBatchId
              targetProduct {
                id
                name
                description
              }
              packingType
              qty
              uomValue
              otherTarget
              description
              remark
              status
              operationGuide
            }
            purchaseOrder {
              id
              name
              bufferLocation {
                id
                name
                description
              }
            }
          }
        }
      `,
      variables: { name: this._ganNo }
    })

    if (!response.errors) {
      const { arrivalNotice } = response.data
      const { orderProducts, orderVass } = arrivalNotice
      const partnerDomainId = arrivalNotice.bizplace.domain.id

      this.arrivalNoticeId = arrivalNotice.id
      this.orderBizplace = arrivalNotice.bizplace
      this._hasContainer = arrivalNotice.container
      this._looseItem = arrivalNotice.looseItem
      this._ownTransport = arrivalNotice.ownTransport
      this._crossDocking = arrivalNotice.crossDocking
      this._releaseGood = arrivalNotice.releaseGood
      this._bizplaceName = arrivalNotice.bizplace.name
      this._importCargo = arrivalNotice.importCargo
      this._status = arrivalNotice.status

      this._fillupANForm({ ...arrivalNotice })

      if (arrivalNotice && arrivalNotice?.attachment) {
        this._attachments = arrivalNotice && arrivalNotice.attachment
      }

      this.setProductGristConfig()
      this.productData = {
        records: orderProducts
          .map(record => {
            return {
              ...record,
              productSku: record.product.sku,
              productBrand: record.product.brand,
            }
          })
          .sort((a, b) => a.product.sku.localeCompare(b.product.sku))
      }
      this.vasData = {
        records: orderVass
          .sort((a, b) => a.set - b.set)
          .map(orderVas => {
            return {
              ...orderVas,
              set: orderVas.set ? `Set ${orderVas.set}` : ''
            }
          })
      }

      this._enableCartonLabel = await fetchSettingRule('enable-carton-label', partnerDomainId)
      this._strictProductSelection = await fetchSettingRule('strict-product-selection', partnerDomainId)
      this._ganProcessingSetting = (await fetchSettingRule('gan-order-processing', partnerDomainId)) || '-1'
      this.updateContext()
    }
  }

  async _checkUserBelongsDomain() {
    try {
      const response = await client.query({
        query: gql`
          query {
            checkUserBelongsDomain
          }
        `
      })

      if (!response.errors) {
        return response.data.checkUserBelongsDomain
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _fillupANForm(data) {
    this._fillupForm(this.arrivalNoticeForm, data)

    if (data?.purchaseOrder?.bufferLocation) {
      this.bufferLocationField.value = `${data.purchaseOrder.bufferLocation.name} ${data.purchaseOrder.bufferLocation.description ? `(${data.purchaseOrder.bufferLocation.description})` : ''
        }`
      this.bufferLocationField.setAttribute('location-id', data.purchaseOrder.bufferLocation.id)
    }
  }

  _fillupForm(form, data) {
    for (let key in data) {
      Array.from(form.querySelectorAll('input, textarea, select')).forEach(field => {
        if (field.name === key && field.type === 'checkbox') {
          field.checked = data[key]

          if (field.name === 'ownTransport') {
            this._ownTransport = data[key]
            if (data[key] === true) {
              // If ownTransp ort is true, set warehouseTransport to false
              this._ownTransport = true
              this._ownTransportInput.checked = true
              this._warehouseTransport = false
              this._warehouseTransportInput.checked = false
            }

            // If ownTransport is true, warehouseTransport must be false
            if (!this._ownTransport) {
              this._warehouseTransport = true
              this._warehouseTransportInput.checked = true
              // If ownTransport is true, set warehouseTransport to false
              this._ownTransport = false
              this._ownTransportInput.checked = false
            }
          }
        } else if (field.name === key) {
          field.value = data[key]
        }
      })
    }
  }

  async _updateArrivalNotice() {
    try {
      const arrivalNoticeInfo = this._getFormInfo()

      if (arrivalNoticeInfo.container) {
        if (!arrivalNoticeInfo.containerNo || arrivalNoticeInfo?.containerNo == '')
          throw new Error(i18next.t('text.container_no_is_empty'))

        if (!arrivalNoticeInfo.containerSize || this.arrivalNoticeForm?.containerSize == '')
          throw new Error(i18next.t('text.please_select_container_size'))
      }

      arrivalNoticeInfo.name = this._ganNo
      delete arrivalNoticeInfo.bizplaceName

      if (!arrivalNoticeInfo.container) {
        arrivalNoticeInfo.containerNo = ''
        arrivalNoticeInfo.containerSize = ''
      } else if (arrivalNoticeInfo.warehouseTransport) {
        arrivalNoticeInfo.deliveryOrderNo = ''
        arrivalNoticeInfo.truckNo = ''
      }

      delete arrivalNoticeInfo.warehouseTransport
      delete arrivalNoticeInfo['buffer-location']

      if (this._warehouseTransport) {
        arrivalNoticeInfo.truckNo = ''
        arrivalNoticeInfo.deliveryOrderNo = ''
      }

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

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation updateArrivalNoticeDetails($arrivalNotice: ArrivalNoticePatch!) {
            updateArrivalNoticeDetails(arrivalNotice: $arrivalNotice) {
              id
            }
          }
        `,
        variables: {
          arrivalNotice: {
            ...arrivalNoticeInfo
          }
        }
      })
      if (!response.errors) {
        this._showToast({ message: i18next.t('text.arrival_notice_details_updated') })
        await this._fetchGAN()
      }
    } catch (error) {
      this._showToast(error)
    }
  }

  async _deleteArrivalNotice() {
    try {
      let result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.you_wont_be_able_to_revert_this'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      if (this._crossDocking) {
        result = await CustomAlert({
          title: i18next.t('label.cross_docking'),
          text: i18next.t('text.release_order_will_be_deleted'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) return
      }

      this._executeRevertTransactions()
      const response = await client.mutate({
        mutation: gql`
          mutation deleteArrivalNotice($name: String!) {
            deleteArrivalNotice(name: $name)
          }
        `,
        variables: { name: this._ganNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.gan_has_been_deleted') })
        navigate(`arrival_notices`)
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _executeRevertTransactions() {
    try {
      for (let i = 0; i < this.vasData.records.length; i++) {
        const record = this.vasData.records[i]
        if (record.vas.operationGuideType && record.vas.operationGuideType === 'template') {
          const template = document.createElement(record.vas.operationGuide)

          for (let j = 0; j < template.revertTransactions.length; j++) {
            const trx = template.revertTransactions[j]
            await trx(record)
          }
        }
      }
    } catch (e) {
      throw e
    }
  }

  async _rejectArrivalNotice() {
    const popup = openPopup(
      html`
        <popup-note
          .title="${i18next.t('title.remark')}"
          @submit="${async e => {
          try {
            if (!e.detail.value) throw new Error(i18next.t('text.remark_is_empty'))
            const result = await CustomAlert({
              title: i18next.t('title.are_you_sure'),
              text: i18next.t('text.reject_arrival_notice'),
              confirmButton: { text: i18next.t('button.confirm') },
              cancelButton: { text: i18next.t('button.cancel') }
            })

            if (!result.value) return

            if (this._crossDocking) {
              const result = await CustomAlert({
                title: i18next.t('title.cross_docking'),
                text: i18next.t('text.related_release_order_will_be_rejected'),
                confirmButton: { text: i18next.t('button.confirm') },
                cancelButton: { text: i18next.t('button.cancel') }
              })

              if (!result.value) return
            }

            const response = await client.mutate({
              mutation: gql`
                  mutation rejectArrivalNotice($name: String!, $patch: ArrivalNoticePatch!) {
                    rejectArrivalNotice(name: $name, patch: $patch) {
                      name
                    }
                  }
                `,
              variables: { name: this._ganNo, patch: { remark: e.detail.value } }
            })

            if (!response.errors) {
              navigate('arrival_notices')
              this._showToast({ message: i18next.t('text.arrival_notice_rejected') })
            }
          } catch (e) {
            this._showToast(e)
          }
        }}"
        ></popup-note>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: i18next.t('title.reject_arrival_notice')
      }
    )
  }

  async _receiveArrivalNotice() {
    try {
      let result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.receive_arrival_notice'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      if (this._crossDocking) {
        result = await CustomAlert({
          title: i18next.t('title.are_you_sure'),
          text: i18next.t('text.this_is_cross_docking'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation receiveArrivalNotice($name: String!) {
            receiveArrivalNotice(name: $name) {
              name
            }
          }
        `,
        variables: { name: this._ganNo }
      })

      if (!response.errors) {
        if (this._ganProcessingSetting == '2') {
          this.pageReset()
          this._showToast({ message: i18next.t('text.arrival_notice_received') })
          this._openBufferSelector()
        } else {
          this.pageReset()
          this._showToast({ message: i18next.t('text.arrival_notice_received') })
        }
      }
    } catch (e) {
      this._showToast(e)
    }
  }

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

      if (!result.value) {
        return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation checkArrivedNotice($name: String!) {
            checkArrivedNotice(name: $name) {
              name
            }
          }
        `,
        variables: { name: this._ganNo }
      })

      if (!response.errors) {
        this._showToast({ message: i18next.t('text.arrival_notice_is_arrived') })
        this.pageReset()
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _assignBufferLocation() {
    try {
      this._validateBufferLocation()

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

      if (!result.value) return

      if (this._crossDocking) {
        result = await CustomAlert({
          title: i18next.t('title.cross_docking'),
          text: i18next.t('text.picking_worksheet_will_be_generated'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation generateArrivalNoticeWorksheet($arrivalNoticeNo: [String!], $bufferLocation: ObjectRef!) {
            generateArrivalNoticeWorksheet(arrivalNoticeNos: $arrivalNoticeNo, bufferLocation: $bufferLocation) {
              unloadingWorksheet {
                name
              }
            }
          }
        `,
        variables: {
          arrivalNoticeNo: [this._ganNo],
          bufferLocation: { id: this.bufferLocationField.getAttribute('location-id') }
        }
      })

      if (!response.errors) {
        navigate(`inbound_worksheets`)
        this._showToast({ message: i18next.t('text.warehouse_is_assigned') })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _validateBufferLocation() {
    if (!this.bufferLocationField.getAttribute('location-id'))
      throw new Error(i18next.t('text.warehouse_is_not_assigned'))
  }

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

  async _confirmArrivalNotice() {
    // Check if ALL products have packQty = 0 AND palletQty = 0
    const isAllZero = this.productData.records.every(product => {
      // Products might not have packQty/palletQty properties directly if they are in a different format,
      // but usually grist data has them.
      // Need to handle null/undefined as 0
      const packQty = product.packQty || 0
      const palletQty = product.palletQty || 0
      return packQty === 0 && palletQty === 0
    })

    if (isAllZero) {
      const confirmZero = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.changing_all_product_quantities_to_0_will_cancel_order'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!confirmZero.value) return
    }

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

    if (!result.value) return

    if (this._crossDocking) {
      result = await CustomAlert({
        title: i18next.t('title.cross_docking'),
        text: i18next.t('text.release_order_will_be_confirmed'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return
    }

    try {
      const mutation = this.enableDirectInbound
        ? gql`
            mutation confirmDirectInboundArrivalNotice($name: String!) {
              confirmDirectInboundArrivalNotice(name: $name) {
                name
              }
            }
        `
        : gql`
            mutation confirmArrivalNotice($name: String!) {
              confirmArrivalNotice(name: $name) {
                name
              }
            }
        `
      const response = await client.mutate({
        mutation,
        variables: { name: this._ganNo }
      })

      if (!response.errors) {
        if (this._ganProcessingSetting == '1') {
          this._showToast({ message: i18next.t('text.gan_confirmed') })
          this.pageReset()
          this._openBufferSelector()
        } else {
          this._showToast({ message: i18next.t('text.gan_confirmed') })
          navigate('arrival_notices')
        }
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async _cancelArrivalNotice() {
    try {
      let result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.you_wont_be_able_to_revert_this'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation cancelArrivalNotice($name: String!) {
            cancelArrivalNotice(name: $name)
          }
        `,
        variables: { name: this._ganNo }
      })

      if (!response.errors) {
        navigate('arrival_notices')
        this._showToast({ message: i18next.t('text.arrival_notice_cancelled') })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _openBufferSelector() {
    openPopup(
      html`
        <buffer-location-selector
          @selected="${async e => {
          this.bufferLocationField.value = `${e.detail.name} ${e.detail.description ? `(${e.detail.description})` : ''
            }`
          this.bufferLocationField.setAttribute('location-id', e.detail.id)

          if (this._ganProcessingSetting == '1' || this._ganProcessingSetting == '2') {
            await this._assignBufferLocation()
          }
        }}"
        ></buffer-location-selector>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_warehouse')
      }
    )
  }

  async _fetchWorksheet() {
    const response = await client.query({
      query: gql`
        query worksheet($name: String!) {
          worksheet(name: $name) {
            id
            name
            worksheetDetails {
              id
              name
              targetProduct {
                product {
                  id
                  sku
                  brand
                  name
                  type
                  description
                }
                batchId
                packingType
                palletQty
                palletId
              }
            }
          }
        }
      `,
      variables: { name: this.arrivalNoticeId }
    })

    if (!response.errors) {
      this.data = {
        records: response.data.worksheet.worksheetDetails.map(worksheetDetail => {
          return {
            ...worksheetDetail.targetProduct,
            id: worksheetDetail.id,
            batchId: worksheetDetail.batchId,
            printQty: worksheetDetail.targetProduct.palletQty,
            packingType: worksheetDetail.targetProduct.packingType
          }
        })
      }
    }
  }

  determineStatus() {
    let status = false

    if (ORDER_STATUS.DONE.value == this._status || ORDER_STATUS.REJECTED.value == this._status) {
      status = true
    }

    return status
  }

  async _openLotLabelPrintPopup() {
    await this._fetchWorksheet()
    let a = this.data
    const _pallets = {
      records: this.data.records.map(record => {
        return {
          id: record.id,
          palletId: record.palletId,
          batchId: record.batchId,
          product: record.product,
          palletQty: record.palletQty,
          printQty: record.palletQty,
          packingType: record.packingType,
          bizplace: this._bizplaceName
        }
      })
    }
    openPopup(html` <pallet-label-popup .pallets="${_pallets}"></pallet-label-popup> `, {
      backdrop: true,
      size: 'large',
      title: i18next.t('title.lot_label')
    })
  }

  _openCartonLabelPrintPopup() {
    openPopup(
      html` 
      <carton-label-popup 
        .fixedType="${'default'}" 
        .bizplaceName="${this._bizplaceName}"
        .enableDirectInbound="${this.enableDirectInbound}"
        .productData="${this.productData}"
        .arrivalNoticeId="${this.arrivalNoticeId}"
      ></carton-label-popup> 
      `,
      {
        backdrop: true,
        title: i18next.t('title.carton_label')
      }
    )
  }

  openEditProductPopup() {
    this.productData.records = this.productData.records.filter(
      orderProduct => orderProduct.status !== ORDER_PRODUCT_STATUS.UNLOADED.value
    )

    openPopup(
      html`
        <edit-product-popup
          .ganNo="${this._ganNo}"
          .status="${this._status}"
          .productData="${this.productData}"
          .bizplace="${this.orderBizplace}"
          .strictEditable="${this._strictProductSelection}"
          .enableDirectInbound="${this.enableDirectInbound}"
          @completed="${this._fetchGAN.bind(this)}"
        ></edit-product-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.edit_add_order_product')
      }
    )
  }

  openApproveProductPopup() {
    openPopup(
      html`
        <proceed-edit-product-popup
          .ganNo="${this._ganNo}"
          .bizplace="${this.orderBizplace}"
          .data="${this.productData}"
          .enableDirectInbound="${this.enableDirectInbound}"
          @completed="${() => {
          this._fetchGAN()
          this.updateContext()
        }}"
        ></proceed-edit-product-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.proceed_edited_added_product')
      }
    )
  }

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

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

    return obj
  }

  openProductChangesPopup() {
    openPopup(
      html` 
        <view-product-changes-popup 
          .data="${this.productData}"
          .enableDirectInbound="${this.enableDirectInbound}"
        ></view-product-changes-popup> 
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.view_product_changes')
      }
    )
  }

  async fetchUserRoleHandler() {
    const response = await client.query({
      query: gql`
        query myRoles {
          myRoles {
            id
            name
            description
          }
        }
      `
    })

    if (!response.errors?.length) {
      return response.data.myRoles
    }

    return []
  }

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

window.customElements.define('arrival-notice-detail', ArrivalNoticeDetail)
