import '@things-factory/barcode-ui'
import '@things-factory/grist-ui'
import './inventory-assign-popup'
import './inventory-auto-assign-popup'
import './select-operator-popup'
import './item-label-popup'
import './inventory-reassign-popup'

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

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_INVENTORY_STATUS,
  VAS_BATCH_AND_PRODUCT_TYPE,
  VAS_BATCH_NO_TYPE,
  VAS_ETC_TYPE,
  VAS_PRODUCT_TYPE,
  WORKSHEET_STATUS,
  WORKSHEET_TYPE
} from '../constants'

class WorksheetPicking extends localize(i18next)(PageView) {
  static get properties() {
    return {
      isPalletPickingOrder: Boolean,
      _worksheetNo: String,
      _worksheetStatus: String,
      _roNo: String,
      _roId: String,
      _statusList: Array,
      ganNo: String,
      assignee: Object,
      productGristConfig: Object,
      wsdGristConfig: Object,
      productGristData: Object,
      worksheetDetailData: Object,
      vasData: Object,
      vasGristConfig: Object,
      worksheetType: String,
      crossDocking: Boolean,
      courierOption: Boolean,
      packingOption: Boolean,
      exportOption: Boolean,
      targetBizplace: Object,
      worksheetId: String,
      orderNo: String,
      isRecall: Boolean,
      isAssignedInventory: Boolean,
      _worksheetPickingAssignment: Boolean
    }
  }

  //vas
  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow-x: auto;
        }
        .form-container {
          display: flex;
        }
        .form-container > form {
          flex: 1;
        }
        barcode-tag {
          width: 100px;
          height: 100px;
          margin: 10px;
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          flex-direction: row;
          flex: 1;
          overflow-y: auto;
        }
        .grist-column {
          flex: 1;
          display: flex;
          flex-direction: column;
          overflow: auto;
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
        }
        h2 {
          padding: var(--subtitle-padding);
          font: var(--subtitle-font);
          color: var(--subtitle-text-color);
          border-bottom: var(--subtitle-border-bottom);
        }
        .grist h2 {
          margin: var(--grist-title-margin);
          border: var(--grist-title-border);
          font: var(--grist-title-font);
          color: var(--secondary-color);
        }

        .grist h2 mwc-icon {
          vertical-align: middle;
          margin: var(--grist-title-icon-margin);
          font-size: var(--grist-title-icon-size);
          color: var(--grist-title-icon-color);
        }

        h2 + data-grist {
          padding-top: var(--grist-title-with-grid-padding);
        }
      `
    ]
  }

  constructor() {
    super()
    this.isPalletPickingOrder = false
    this.worksheetDetailData = { records: [] }
    this._statusList = Object.keys(WORKSHEET_STATUS).map(key => {
      return { value: WORKSHEET_STATUS[key].value, display: WORKSHEET_STATUS[key].name }
    })
  }

  get context() {
    var actions = [
      {
        title: i18next.t('button.back'),
        action: () => history.back(),
        ...CommonButtonStyles.back
      },
      {
        title: i18next.t('button.select_operator'),
        action: this._selectOperator.bind(this),
        ...CommonButtonStyles.add
      }
    ]
    if (this.crossDocking) {
      actions = this._updateCrossDockingContext()
    }
    if (this._printItemLabel) {
      actions.push({
        title: i18next.t('button.print_label'),
        action: this._openItemLabelPrintPopup.bind(this),
        ...CommonButtonStyles.label
      })
    }

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

    if (this.activatable) {
      if (this.isAssignedInventory) {
        actions.push({
          title: i18next.t('button.reassign'),
          action: this._openReassignInventoryPopup.bind(this),
          ...CommonButtonStyles.assignment
        })
      }
      actions.push({
        title: i18next.t('button.activate'),
        action: this._activateWorksheet.bind(this),
        ...CommonButtonStyles.activate
      })
    }

    if (
      !this.activatable &&
      (this.worksheetDetailData?.records.find(itm => itm.obsolete == true) ||
        (this._worksheetPickingAssignment && this.worksheetDetailData?.records.find(itm => itm?.status == 'EXECUTING')))
    ) {
      actions.push({
        title: i18next.t('button.reassign'),
        action: this._openReassignInventoryPopup.bind(this),
        ...CommonButtonStyles.assignment
      })
    }

    if (this.assignable && !this._worksheetPickingAssignment) {
      actions.push({
        title: i18next.t('button.auto_assign'),
        action: this._showAutoAssignPopup.bind(this),
        ...CommonButtonStyles.assignment
      })
    }

    return {
      title: i18next.t('title.worksheet_picking'),
      actions,
      printable: {
        accept: ['preview'],
        content: this
      },
      help: 'operato-wms/outbound/worksheet-picking'
    }
  }

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

            <label>${i18next.t('label.options')}</label>
            <div options-wrap>
              <input id="ownCollection" type="checkbox" name="ownCollection" disabled />
              <label for="ownCollection">${i18next.t('label.own_collection')}</label>

              <input name="crossDocking" type="checkbox" .checked="${this.crossDocking}" disabled />
              <label>${i18next.t('field.cross_docking')}</label>

              <input name="courierOption" type="checkbox" .checked="${this.courierOption}" disabled />
              <label>${i18next.t('field.transporter')}</label>

              <input name="packingOption" type="checkbox" .checked="${this.packingOption}" disabled />
              <label>${i18next.t('field.packing')}</label>

              <input name="exportOption" type="checkbox" .checked="${this.exportOption}" disabled />
              <label>${i18next.t('field.export')}</label>

              <input name="vas" type="checkbox" .checked="${this.vasData?.records}" disabled />
              <label>${i18next.t('field.vas')}</label>
            </div>

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

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

            <label>${i18next.t('label.release_date')}</label>
            <input name="releaseDate" type="date" readonly />

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

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

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

            ${this.exportOption
              ? html`
                  <label>${i18next.t('label.container_no')}</label>
                  <input name="containerNo" readonly />

                  <label>${i18next.t('label.container_leaving_date')}</label>
                  <input name="containerLeavingDate" type="date" readonly />
                `
              : ''}

            <label>${i18next.t('label.status')}</label>
            <input
              name="status"
              value="${this._statusList.find(x => x.value == this._worksheetStatus)?.display || ''}"
              readonly
              disabled
            />

            <label>${i18next.t('label.picker')}</label>
            <input name="assignee" readonly />
          </fieldset>
        </form>

        <barcode-tag bcid="qrcode" .value=${this._roNo} showLogo="true"></barcode-tag>
      </div>

      <div class="grist">
        ${this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value && !this.isPalletPickingOrder
          ? html`
              <div class="grist-column">
                <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.productGristData}"
                ></data-grist>
              </div>
            `
          : ''}
        ${this._worksheetStatus == WORKSHEET_STATUS.DEACTIVATED.value &&
        this._worksheetPickingAssignment &&
        this.worksheetDetailData.records.length == 0
          ? ''
          : html`
        <div class="grist-column">
          <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.worksheet_detail')}</h2>
          <data-grist
            id="wsd-grist"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.wsdGristConfig}
            .data="${this.worksheetDetailData}"
          ></data-grist>

          <!-- vas data -->
          <!-- ${
            this.vasData?.records
              ? html`
                  <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.vas')}</h2>
                  <data-grist
                    id="vas-grist"
                    .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
                    .config=${this.vasGristConfig}
                    .data="${this.vasData}"
                  ></data-grist>
                `
              : ''
          } -->
        </div>
      </div>
      `}
      </div>
    `
  }

  async updated(changeProps) {
    if (changeProps.has('crossDocking') || changeProps.has('ganNo')) {
      if (this.crossDocking && this.ganNo) {
        const { name, status } = await this.fetchUnloadingWorksheet()
        this.unloadingWorksheetNo = name
        this.unloadingWorksheetStatus = status
        this.updateContext()
      }
    }
  }

  async pageUpdated(changes, lifecycle) {
    this.productGristConfig = {
      pagination: { infinite: true },
      rows: {
        appendable: false,
        classifier: record => {
          return {
            emphasized: record.completed
          }
        },
        handlers: {
          click: async (columns, data, column, record, rowIndex) => {
            if (record.batchId && record.product?.name && record.packingType && record.packingSize != undefined) {
              await this.fetchWorksheetDetailsByProductGroup(
                this._worksheetNo,
                record.batchId,
                record.product.name,
                record.product.sku,
                record.packingType,
                record.packingSize
              )
              this._selectedProduct = {
                batchId: record.batchId,
                batchIdRef: record.batchIdRef,
                product: record.product,
                packingType: record.packingType,
                packingSize: record.packingSize,
                uom: record.uom,
                releaseQty: record.releaseQty,
                releaseUomValue: record.releaseUomValue,
                availableQty: record.availableQty,
                completed: record.completed,
                orderProductId: record.orderProduct.id
              }

              this.updateContext()
            }
          }
        }
      },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'boolean',
          name: 'completed',
          header: i18next.t('field.done'),
          width: 40
        },
        {
          type: 'gutter',
          gutterName: 'button',
          icon: 'assignment',
          handlers: {
            click: (columns, data, column, record, rowIndex) => {
              if (record.completed) return
              if (this._worksheetPickingAssignment) return
              this._selectedProduct = {
                batchId: record.batchId,
                product: record.product,
                bizplaceId: record.bizplaceId,
                packingType: record.packingType,
                packingSize: record.packingSize,
                releaseQty: record.releaseQty,
                releaseUomValue: record.releaseUomValue,
                uom: record.uom,
                orderProductId: record.orderProduct.id
              }
              this._showInventoryAssignPopup()
            }
          }
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 100
        },
        {
          type: 'string',
          name: 'productSku',
          header: i18next.t('field.sku'),
          width: 100
        },
        {
          type: 'object',
          name: 'product',
          header: i18next.t('field.product'),
          width: 250
        },
        {
          type: 'string',
          name: 'productBrand',
          header: i18next.t('field.brand'),
          width: 100
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 150
        },
        {
          type: 'float',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          width: 60
        },
        {
          type: 'float',
          name: 'releaseUomValue',
          header: i18next.t('field.release_uom_value'),
          width: 60
        }
      ]
    }

    this.preWsdGristConfig = {
      list: {
        fields: [
          'palletId',
          'cartonId',
          'batchId',
          'product',
          'packingType',
          'location',
          'releaseQty',
          'pickedQty',
          'batchIdRef',
          'status'
        ]
      },
      pagination: { infinite: true },
      rows: { appendable: false },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 100
        },
        {
          type: 'string',
          name: 'palletId',
          header: i18next.t('field.lot_id'),
          width: 120
        },
        {
          type: 'string',
          name: 'productSku',
          header: i18next.t('field.sku'),
          width: 100
        },
        {
          type: 'object',
          name: 'product',
          header: i18next.t('field.product'),
          width: 250
        },
        {
          type: 'string',
          name: 'productBrand',
          header: i18next.t('field.brand'),
          width: 100
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 150
        },
        {
          type: 'object',
          name: 'location',
          header: i18next.t('field.location'),
          width: 120
        },
        {
          type: 'float',
          name: 'availableQty',
          header: i18next.t('field.available_qty'),
          width: 80
        },
        {
          type: 'float',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          width: 60
        },
        {
          type: 'float',
          name: 'pickedQty',
          header: i18next.t('field.picked_qty'),
          width: 60
        },
        {
          type: 'string',
          name: 'releaseUomValueWithUom',
          header: i18next.t('field.release_uom_value'),
          width: 60
        },
        {
          type: 'boolean',
          name: 'obsolete',
          header: i18next.t('field.obsolete'),
          width: 60
        },
        {
          type: 'date',
          name: 'expirationDate',
          header: i18next.t('field.expiry_date'),
          width: 150
        },
        {
          type: 'date',
          name: 'manufactureDate',
          header: i18next.t('field.manufacture_date'),
          width: 150
        }
      ]
    }

    this.vasGristConfig = {
      list: { fields: ['targetType', 'targetDisplay', 'packingType'] },
      pagination: { infinite: true },
      rows: { appendable: false },
      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: 'float',
          name: 'qty',
          header: i18next.t('field.qty'),
          width: 80
        },
        {
          type: 'float',
          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
        }
      ]
    }

    if (this.active && (changes.resourceId || this._worksheetNo)) {
      if (changes.resourceId) {
        this._worksheetNo = changes.resourceId
        this.vasData = {} // reset vas data from the page transition
      }
      await this.fetchOrderInventories()
      this.updateContext()
      this._updateGristConfig()
    }
    if (this.active) {
      this.orderNo = lifecycle.params.orderNo || null
    }
  }

  async pageInitialized() {
    this._worksheetPickingAssignment = await fetchSettingRule('enable-worksheet-picking-activation-assignment')
    this._printItemLabel = await fetchSettingRule('enable-item-label')
  }

  get form() {
    return this.shadowRoot.querySelector('form')
  }

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

  get wsdGrist() {
    return this.shadowRoot.querySelector('data-grist#wsd-grist')
  }

  get operatorInput() {
    return this.renderRoot.querySelector('input[name=assignee]')
  }

  async fetchOrderInventories() {
    // ** duplicated
    // const cartonIdColumnConfig = {
    //   type: 'string',
    //   name: 'cartonId',
    //   header: i18next.t('field.carton_id'),
    //   width: 120
    // }

    if (!this._worksheetNo) return
    const response = await client.query({
      query: gql`
        query worksheet($name: String!) {
          worksheet(name: $name) {
            name
            id
            status
            type
            assignee {
              id
              name
            }
            releaseGood {
              id
              name
              description
              refNo
              refNo2
              refNo3
              attentionTo
              attentionCompany
              city
              ownTransport
              crossDocking
              courierOption
              exportOption
              packingOption
              releaseDate
              recall
              assignedInventory
              arrivalNotice {
                name
              }
              shippingOrder {
                containerNo
                containerArrivalDate
                containerLeavingDate
              }
              orderProducts {
                id
                product {
                  id
                  sku
                  name
                }
                packingType
                packingSize
                releaseQty
                releaseUomValue
                uom
                batchId
              }
            }
            orderInventories {
              status
              batchId
              batchIdRef
              product {
                id
                name
                description
                sku
                brand
                pickingStrategy
              }
              orderProduct {
                id
                name
              }
              packingType
              packingSize
              uom
              releaseQty
              pickedQty
              releaseUomValue
              inventory {
                qty
                lockedQty
                palletId
                cartonId
                uom
                obsolete
                location {
                  name
                  description
                }
              }
            }
            bizplace {
              id
              name
              description
            }
            worksheetDetails {
              name
              status
              description
              targetInventory {
                batchId
                type
                batchIdRef
                releaseGood {
                  id
                  name
                }
                product {
                  id
                  name
                  description
                  sku
                }
                packingType
                packingSize
                pickedQty
                releaseQty
                releaseUomValue
                status
                inventory {
                  qty
                  lockedQty
                  palletId
                  cartonId
                  batchId
                  batchIdRef
                  packingType
                  obsolete
                  warehouse {
                    name
                    description
                  }
                  location {
                    name
                    description
                  }
                  product {
                    sku
                    name
                    brand
                    description
                  }
                  zone
                  uom
                  qty
                  expirationDate
                  manufactureDate
                }
              }
            }
            orderVass {
              vas {
                name
                operationGuide
                operationGuideType
              }
              set
              targetType
              targetBatchId
              targetProduct {
                id
                name
                description
              }
              packingType

              qty
              uomValue
              otherTarget
              description
              remark
              status
              operationGuide
            }
          }
        }
      `,
      variables: { name: this._worksheetNo }
    })

    if (!response.errors) {
      let worksheet = response.data.worksheet
      const orderVass = worksheet?.orderVass
      const releaseGood = worksheet?.releaseGood

      this.releaseGood = worksheet?.releaseGood
      this.worksheetDetails = worksheet.worksheetDetails
      this._worksheetStatus = worksheet.status
      this.worksheetType = worksheet?.type

      this._roId = releaseGood?.id || ''
      this._roNo = releaseGood?.name || ''
      this.isRecall = releaseGood?.recall
      this.crossDocking = releaseGood?.crossDocking
      this.courierOption = releaseGood?.courierOption
      this.packingOption = releaseGood?.packingOption
      this.ganNo = releaseGood?.arrivalNotice?.name
      this.exportOption = releaseGood?.exportOption
      this.isAssignedInventory = releaseGood?.assignedInventory

      if (this.exportOption) {
        worksheet = {
          ...worksheet,
          containerNo: worksheet.releaseGood.shippingOrder?.containerNo,
          containerLeavingDate: worksheet.releaseGood?.shippingOrder?.containerLeavingDate
        }
      }

      this.targetBizpace = worksheet?.bizplace || {}
      this.worksheetId = worksheet.id
      this.assignee = worksheet.assignee || {}

      this._fillupForm({
        ...worksheet,
        releaseGood: worksheet.releaseGood.name,
        bizplace: worksheet.bizplace.name,
        assignee: worksheet.assignee?.name || '',
        refNo: worksheet.releaseGood.refNo,
        refNo2: worksheet.releaseGood.refNo2,
        refNo3: worksheet.releaseGood.refNo3,
        ownCollection: worksheet.releaseGood.ownTransport,
        releaseDate: worksheet.releaseGood.releaseDate,
        containerNo: worksheet.containerNo,
        containerLeavingDate: worksheet.containerLeavingDate
      })

      if (releaseGood.assignedInventory) {
        const { tempOrderInvs, completedOrderInvs } = worksheet.orderInventories.reduce(
          (result, ordInv) => {
            if (ordInv.status === ORDER_INVENTORY_STATUS.PENDING_SPLIT.value) {
              ordInv.productSku = ordInv.product.sku
              ordInv.productBrand = ordInv.product.brand
              result.tempOrderInvs.push(ordInv)
            } else {
              ordInv.productSku = ordInv.product.sku
              ordInv.productBrand = ordInv.product.brand
              ordInv.releaseUomValueWithUom = ordInv.releaseUomValue.toFixed(3) + ' ' + ordInv.inventory.uom
              ordInv.availableQty = parseFloat(
                (ordInv.inventory.qty - ordInv.inventory.lockedQty + ordInv.releaseQty).toFixed(3)
              )
              result.completedOrderInvs.push(ordInv)
            }

            return result
          },
          {
            tempOrderInvs: [],
            completedOrderInvs: []
          }
        )

        this.isPalletPickingOrder = Boolean(!tempOrderInvs || !tempOrderInvs.length)

        this.productGristData = {
          records: tempOrderInvs.map(ordInv => {
            const { compQty, compUomValue } = completedOrderInvs.reduce(
              (result, compOrdInv) => {
                if (this._checkSameOrderInv(ordInv, compOrdInv)) {
                  result.compQty += compOrdInv.releaseQty
                  result.compUomValue += compOrdInv.releaseUomValue
                }

                // need to round off the completed uomValue to bypass the validation
                result.compUomValue = Math.round(result.compUomValue * 100) / 100

                return result
              },
              { compQty: 0, compUomValue: 0 }
            )

            return {
              ...ordInv,
              bizplaceId: worksheet.bizplace.id,
              completed: compQty === ordInv.releaseQty && compUomValue === ordInv.releaseUomValue
            }
          })
        }

        this.worksheetDetailData = {
          records: worksheet.worksheetDetails.map(wsd => {
            let record = {
              name: wsd.name,
              description: wsd.description,
              status: wsd.status,
              productSku: wsd.targetInventory.inventory.product.sku,
              productBrand: wsd.targetInventory.inventory.product.brand,
              releaseQty:
                orderVass.length == 0 || (orderVass.length > 0 && worksheet.status !== 'DONE')
                  ? wsd.targetInventory.releaseQty
                  : wsd.targetInventory.pickedQty,
              releaseUomValue: wsd.targetInventory.releaseUomValue,
              releaseUomValueWithUom:
                orderVass.length === 0 || (orderVass.length > 0 && worksheet.status !== 'DONE')
                  ? `${wsd.targetInventory.releaseUomValue.toFixed(3)} ${wsd.targetInventory.inventory.uom}`
                  : releaseGood.orderProducts.find(op => op.product.id === wsd.targetInventory.product.id)
                  ? `${releaseGood.orderProducts
                      .find(op => op.product.id === wsd.targetInventory.product.id)
                      .releaseUomValue.toFixed(3)} 
                      ${wsd.targetInventory.inventory.uom}`
                  : 'Unable To Find Matching Product Id',
              availableQty:
                orderVass.length == 0 || (orderVass.length > 0 && worksheet.status !== 'DONE')
                  ? parseFloat((wsd.targetInventory.inventory.qty -
                    wsd.targetInventory.inventory.lockedQty+
                    wsd.targetInventory.releaseQty).toFixed(3))
                  : parseFloat((wsd.targetInventory.inventory.qty -
                    wsd.targetInventory.inventory.lockedQty+
                    wsd.targetInventory.pickedQty).toFixed(3)),
                    
              pickedQty: wsd.targetInventory.pickedQty,
              expirationDate: wsd.targetInventory.inventory.expirationDate,
              manufactureDate: wsd.targetInventory.inventory.manufactureDate
            }

            if (wsd.targetInventory?.inventory) {
              record = Object.assign(record, wsd.targetInventory.inventory)
            } else {
              record = Object.assign(record, wsd.targetInventory)
            }

            return record
          })
        }
      } else {
        this.productGristData = {
          records: releaseGood.orderProducts.map(itm => {
            return {
              ...itm,
              productSku: itm.product.sku
            }
          })
        }
        this.isPalletPickingOrder = false
      }

      if (orderVass?.length) {
        this.vasData = {
          records: orderVass
            .sort((a, b) => a.set - b.set)
            .map(orderVas => {
              return {
                ...orderVas,
                set: orderVas.set ? `Set ${orderVas.set}` : ''
              }
            })
        }
      }

      this._updateGristConfig()
      this.updateContext()
    }
  }

  async fetchUnloadingWorksheet() {
    const response = await client.query({
      query: gql`
        query worksheetByOrderNo($orderType: String!, $orderNo: String!) {
          worksheetByOrderNo(orderType: $orderType, orderNo: $orderNo) {
            name
            status
          }
        }
      `,
      variables: { orderType: WORKSHEET_TYPE.UNLOADING.value, orderNo: this.ganNo }
    })

    if (!response.errors) {
      return response.data.worksheetByOrderNo
    }
  }

  _checkSameOrderInv(a, b) {
    return a.batchId === b.batchId && a.product?.sku === b.product?.sku && a.packingType === b.packingType
  }

  async fetchWorksheetDetailsByProductGroup(worksheetNo, batchId, productName, productSku, packingType, packingSize) {
    const response = await client.query({
      query: gql`
        query worksheetDetailsByProductGroup(
          $worksheetNo: String!
          $batchId: String!
          $productName: String!
          $productSku: String!
          $packingType: String!
          $packingSize: Float!
        ) {
          worksheetDetailsByProductGroup(
            worksheetNo: $worksheetNo
            batchId: $batchId
            productName: $productName
            productSku: $productSku
            packingType: $packingType
            packingSize: $packingSize
          ) {
            items {
              id
              name
              description
              targetInventory {
                releaseQty
                releaseUomValue
                inventory {
                  qty
                  lockedQty
                  batchId
                  batchIdRef
                  palletId
                  cartonId
                  packingType
                  packingSize
                  uom
                  obsolete
                  product {
                    sku
                    name
                    brand
                    description
                  }
                  location {
                    name
                    description
                    zone
                  }
                }
              }
              status
            }
            total
          }
        }
      `,
      variables: { worksheetNo, batchId, productName, productSku, packingType, packingSize }
    })

    if (!response.errors) {
      this.worksheetDetailData = {
        records: response.data.worksheetDetailsByProductGroup.items.map(item => {
          return {
            ...item,
            ...item.targetInventory,
            ...item.targetInventory.inventory,
            ...item.targetInventory.inventory.location,
            productSku: item.targetInventory.inventory.product.sku,
            productBrand: item.targetInventory.inventory.product.brand,
            description: item.description,
            releaseUomValueWithUom:
              item.targetInventory.releaseUomValue.toFixed(3) + ' ' + item.targetInventory.inventory.uom,
            availableQty:
              item.targetInventory.inventory.qty -
              item.targetInventory.inventory.lockedQty +
              item.targetInventory.releaseQty
          }
        }),
        total: response.data.worksheetDetailsByProductGroup.total
      }
    }
  }

  // async fetchWholeWorksheetDetails() {
  //   if (!this._worksheetNo) return
  //   const response = await client.query({
  //     query: gql`
  //       query worksheet($name: String!) {
  //         worksheet(name: $name) {
  //           worksheetDetails {
  //             name
  //             status
  //             description
  //             targetInventory {
  //               batchId
  //               batchIdRef
  //               releaseQty
  //               releaseUomValue
  //               product {
  //                 sku
  //                 name
  //                 description
  //               }
  //               packingType
  //               inventory {
  //                 qty
  //                 lockedQty
  //                 palletId
  //                 cartonId
  //                 batchId
  //                 batchIdRef
  //                 packingType
  //                 obsolete
  //                 warehouse {
  //                   name
  //                   description
  //                 }
  //                 location {
  //                   name
  //                   description
  //                 }
  //                 product {
  //                   sku
  //                   name
  //                   brand
  //                   description
  //                 }
  //                 zone
  //                 uom
  //                 qty
  //               }
  //             }
  //           }
  //           orderVass {
  //             vas {
  //               name
  //               operationGuide
  //               operationGuideType
  //             }
  //             set
  //             targetType
  //             targetBatchId
  //             targetProduct {
  //               id
  //               name
  //               description
  //             }
  //             packingType

  //             qty
  //             uomValue
  //             otherTarget
  //             description
  //             remark
  //             status
  //             operationGuide
  //           }
  //         }
  //       }
  //     `,
  //     variables: { name: this._worksheetNo }
  //   })

  //   if (!response.errors) {
  //     const worksheetDetails = response.data.worksheet.worksheetDetails
  //     const orderVass = response.data.worksheet.orderVass

  //     this.worksheetDetailData = {
  //       records: worksheetDetails.map(wsd => {
  //         let record = {
  //           name: wsd.name,
  //           description: wsd.description,
  //           status: wsd.status,
  //           productSku: wsd.targetInventory.inventory.product.sku,
  //           productBrand: wsd.targetInventory.inventory.product.brand,
  //           releaseQty: wsd.targetInventory.releaseQty,
  //           releaseUomValue: wsd.targetInventory.releaseUomValue,
  //           releaseUomValueWithUom:
  //             wsd.targetInventory.releaseUomValue.toFixed(3) + ' ' + wsd.targetInventory.inventory.uom,
  //           availableQty:
  //             wsd.targetInventory.inventory.qty -
  //             wsd.targetInventory.inventory.lockedQty +
  //             wsd.targetInventory.releaseQty
  //         }

  //         if (wsd.targetInventory?.inventory) {
  //           record = Object.assign(record, wsd.targetInventory.inventory)
  //         } else {
  //           record = Object.assign(record, wsd.targetInventory)
  //         }

  //         return record
  //       })
  //     }

  //     if (orderVass?.length) {
  //       this.vasData = {
  //         records: orderVass
  //           .sort((a, b) => a.set - b.set)
  //           .map(orderVas => {
  //             return {
  //               ...orderVas,
  //               set: orderVas.set ? `Set ${orderVas.set}` : ''
  //             }
  //           })
  //       }
  //     }
  //   }
  // }

  get undoable() {
    return this.productGristData.records.some(record => record.completed) && this._selectedProduct?.completed
  }

  get activatable() {
    if (this.productGristData.records.every(record => record.completed)) {
      if (this.crossDocking) {
        return (
          this.unloadingWorksheetStatus === WORKSHEET_STATUS.EXECUTING.value &&
          this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value
        )
      } else {
        let foundObsoleteItems = this.worksheetDetailData?.records.find(itm => itm.obsolete == true)
        return this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value && (!foundObsoleteItems || this.isRecall)
      }
    } else {
      return this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value && this._worksheetPickingAssignment
    }
  }

  get assignable() {
    return !this.productGristData.records.every(record => record.completed)
  }

  _updateCrossDockingContext() {
    let actions = []

    const isWorksheetDeactive = this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value
    const isUnloadingWorksheetExecuted = this.unloadingWorksheetStatus === WORKSHEET_STATUS.EXECUTING.value

    if (isWorksheetDeactive) {
      if (!isUnloadingWorksheetExecuted) {
        actions.push({
          title: i18next.t('button.move_to_x', { state: { x: i18next.t('title.worksheet_unloading') } }),
          action: () => navigate(`worksheet_unloading/${this.unloadingWorksheetNo}`)
        })
      }
    }

    return actions
  }

  _updateGristConfig() {
    const statusColumnConfig = {
      type: 'string',
      name: 'status',
      header: i18next.t('field.status'),
      width: 100
    }

    const cartonIdColumnConfig = {
      type: 'string',
      name: 'cartonId',
      header: i18next.t('field.carton_id'),
      width: 120
    }

    const batchIdRefColumnConfig = {
      type: 'string',
      name: 'batchIdRef',
      header: i18next.t('field.batch_no_ref'),
      width: 120
    }

    if (
      this.worksheetDetailData.records.some(e => e.cartonId) &&
      !this.preWsdGristConfig.columns.find(column => column.name === 'cartonId')
    ) {
      const palletIdColumnIdx = this.preWsdGristConfig.columns.map(c => c.name).indexOf('palletId')
      this.preWsdGristConfig.columns.splice(palletIdColumnIdx, 1, cartonIdColumnConfig)
    }

    if (
      this.worksheetDetailData.records.some(e => e.batchIdRef) &&
      !this.preWsdGristConfig.columns.find(column => column.name === 'batchIdRef')
    ) {
      this.preWsdGristConfig.columns = [...this.preWsdGristConfig.columns, batchIdRefColumnConfig]
    }

    if (
      !this.preWsdGristConfig.columns.some(e => e.name === 'status') &&
      this._worksheetStatus !== WORKSHEET_STATUS.DEACTIVATED.value
    ) {
      this.preWsdGristConfig.columns = [...this.preWsdGristConfig.columns, statusColumnConfig]
    } else if (
      this.preWsdGristConfig.columns.some(e => e.name === 'status') &&
      this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value
    ) {
      this.preWsdGristConfig.columns.splice(this.preWsdGristConfig.columns.map(e => e.name).indexOf('status'))
    }

    this.wsdGristConfig = { ...this.preWsdGristConfig }
  }

  _fillupForm(data) {
    for (let key in data) {
      Array.from(this.form.querySelectorAll('input, select')).forEach(field => {
        if (field.name === key && field.type === 'checkbox') {
          field.checked = data[key]
        } 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]
          }
        }
      })
    }
  }

  _showInventoryAssignPopup() {
    try {
      if (!this._selectedProduct) throw new Error(i18next.t('text.there_is_no_selected_product'))
      openPopup(
        html`
          <inventory-assign-popup
            .worksheetId="${this.worksheetId}"
            .worksheetNo="${this._worksheetNo}"
            .batchId="${this._selectedProduct.batchId}"
            .productId="${this._selectedProduct.product.id}"
            .productName="${this._selectedProduct.product.name}"
            .productSku="${this._selectedProduct.product.sku}"
            .productPickingStrategy="${this._selectedProduct.product.pickingStrategy}"
            .worksheetType="${this.worksheetType}"
            .bizplaceId="${this._selectedProduct.bizplaceId}"
            .packingType="${this._selectedProduct.packingType}"
            .packingSize="${this._selectedProduct.packingSize}"
            .uom="${this._selectedProduct.uom}"
            .releaseQty="${this._selectedProduct.releaseQty}"
            .releaseUomValue="${this._selectedProduct.releaseUomValue}"
            .orderProductId="${this._selectedProduct.orderProductId}"
            @completed="${async () => {
              await this.fetchOrderInventories()
              await this.fetchWorksheetDetailsByProductGroup(
                this._worksheetNo,
                this._selectedProduct.batchId,
                this._selectedProduct.product.name,
                this._selectedProduct.product.sku,
                this._selectedProduct.packingType,
                this._selectedProduct.packingSize
              )

              this._selectedProduct.completed = true
              this.updateContext()
            }}"
          ></inventory-assign-popup>
        `,
        {
          backdrop: true,
          size: 'large',
          title: i18next.t('title.inventory_assign')
        }
      )
    } catch (e) {
      this._showToast(e)
    }
  }

  _showAutoAssignPopup() {
    openPopup(
      html`
        <inventory-auto-assign-popup
          .worksheetId="${this.worksheetId}"
          .worksheetNo="${this._worksheetNo}"
          .worksheetType="${this.worksheetType}"
          .data="${this.productGrist.data}"
          @completed="${async () => {
            await this.fetchOrderInventories()
            await this.fetchWorksheetDetailsByProductGroup(
              this._worksheetNo,
              this._selectedProduct?.batchId,
              this._selectedProduct?.product?.name,
              this._selectedProduct?.product?.sku,
              this._selectedProduct?.packingType,
              this._selectedProduct?.packingSize
            )

            this.updateContext()
          }}"
        ></inventory-auto-assign-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.inventory_auto_assign')
      }
    )
  }

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

      if (!result.value) {
        return
      }

      await client.mutate({
        mutation: gql`
          mutation undoPickingAssigment(
            $worksheetNo: String!
            $batchId: String!
            $productId: String!
            $packingType: String!
            $packingSize: Float!
          ) {
            undoPickingAssigment(
              worksheetNo: $worksheetNo
              batchId: $batchId
              productId: $productId
              packingType: $packingType
              packingSize: $packingSize
            )
          }
        `,
        variables: {
          worksheetNo: this._worksheetNo,
          batchId: this._selectedProduct.batchId,
          productId: this._selectedProduct.product.id,
          packingType: this._selectedProduct.packingType,
          packingSize: this._selectedProduct.packingSize
        }
      })

      await this.fetchOrderInventories()
      await this.fetchWorksheetDetailsByProductGroup(
        this._worksheetNo,
        this._selectedProduct.batchId,
        this._selectedProduct.product.name,
        this._selectedProduct.product.sku,
        this._selectedProduct.packingType,
        this._selectedProduct.packingSize
      )

      this._selectedProduct.completed = false
      this.updateContext()
    } catch (e) {
      this._showToast(e)
    }
  }

  async _activateWorksheet() {
    try {
      console.time('worksheet')
      const result = await CustomAlert({
        title: i18next.t('title.are_you_sure'),
        text: i18next.t('text.activate_picking_worksheet'),
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') }
      })

      if (!result.value) {
        return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation activatePicking($worksheetNo: String!) {
            activatePicking(worksheetNo: $worksheetNo) {
              name
            }
          }
        `,
        variables: { worksheetNo: this._worksheetNo }
      })
      if (!response.errors) {
        this._showToast({ message: i18next.t('text.worksheet_activated') })
        await this.fetchOrderInventories()
        this.updateContext()
      }
    } catch (e) {
      this._showToast(e)
    }
    console.time('worksheet')
  }

  _getPickingWorksheetDetails() {
    return this.productGrist.dirtyData.records.map(worksheetDetail => {
      return {
        name: worksheetDetail.name,
        description: worksheetDetail.description
      }
    })
  }

  _openReassignInventoryPopup() {
    openPopup(
      html`
        <inventory-reassign-popup
          .bizplaceId=${this.targetBizpace?.id}
          .roId=${this._roId}
          .worksheetNo=${this._worksheetNo}
          .worksheetPickingAssignment=${this._worksheetPickingAssignment}
          @reassignment-completed="${async () => {
            await this.fetchOrderInventories()

            this.updateContext()
          }}"
        ></inventory-reassign-popup>
      `,
      {
        escapable: false,
        closable: false,
        backdrop: true,
        size: 'large',
        title: i18next.t('title.reassign_inventory')
      }
    )
  }

  _selectOperator() {
    openPopup(
      html`
        <select-operator-popup
          .bizplace=${this.targetBizpace}
          @updateOperator="${async e => {
            this.assignee = e.detail
            this.operatorInput.value = this.assignee.name || ''
            await this.assignWorker()

            if (this.activatable) {
              if (this.orderNo) {
                history.back()
              }
            }
          }}"
        ></select-operator-popup>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: 'select operator'
      }
    )
  }

  async _openItemLabelPrintPopup() {
    const _items = {
      records: this.worksheetDetails.map(itm => {
        return {
          batchId: itm.targetInventory.batchId,
          location: itm.targetInventory.inventory.location.name,
          roNo: itm.targetInventory.releaseGood.name,
          sku: itm.targetInventory.product.sku,
          product: itm.targetInventory.product,
          printQty: itm.targetInventory.releaseQty,
          releaseQty: itm.targetInventory.releaseQty,
          attentionTo: this.releaseGood.attentionTo?.toUpperCase() || '-',
          attentionCompany: this.releaseGood.attentionCompany?.toUpperCase() || '-',
          refNo: this.releaseGood.refNo || '-',
          city: this.releaseGood.city?.toUpperCase() || '-',
          releaseDate: this.releaseGood.releaseDate
        }
      })
    }

    openPopup(html` <item-label-popup .items="${_items}"></item-label-popup> `, {
      backdrop: true,
      size: 'large',
      title: i18next.t('title.select_item_label')
    })
  }

  async assignWorker() {
    const response = await client.mutate({
      mutation: gql`
        mutation assignPickingWorker($worksheetId: [String]!, $userId: String!) {
          assignPickingWorker(worksheetId: $worksheetId, userId: $userId)
        }
      `,
      variables: { worksheetId: [this.worksheetId], userId: this.assignee.id }
    })

    if (!response.errors) {
      return this._showToast({ message: i18next.t('text.updated_successfully') })
    }
  }

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

window.customElements.define('worksheet-picking', WorksheetPicking)
