import '@things-factory/barcode-ui'
import '@things-factory/grist-ui'

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

import { MultiColumnFormStyles } from '@things-factory/form-ui'
import { i18next, localize } from '@things-factory/i18n-base'
import { client, CustomAlert } from '@things-factory/shell'
import { isMobileDevice } from '@things-factory/utils'

import { WORKSHEET_TYPE } from '../constants'

class InventoryAutoAssignPopup extends localize(i18next)(LitElement) {
  static get properties() {
    return {
      worksheetId: String,
      worksheetNo: String,
      selectedItems: Array,
      worksheetType: String,
      config: Object,
      data: Object
    }
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          padding: 10px;
          display: flex;
          flex-direction: column;
          overflow-x: overlay;
          background-color: var(--main-section-background-color);
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
        }
        .button-container {
          padding: var(--button-container-padding);
          margin: var(--button-container-margin);
          text-align: var(--button-container-align);
          background-color: var(--button-container-background);
          height: var(--button-container-height);
        }
      `
    ]
  }

  render() {
    return html`
      <div class="grist">
        <data-grist
          id="grist"
          .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
          .config=${this.config}
          .data="${this.data}"
        ></data-grist>
      </div>

      <div class="button-container">
        <mwc-button
          raised
          @click="${this.autoAssign.bind(this)}"
          label="${i18next.t('button.auto_assign')}"
        ></mwc-button>
      </div>
    `
  }

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

  firstUpdated() {
    this.data.records = [...this.data.records.filter(itm => itm.completed == false)]

    this.config = {
      list: { fields: [] },
      pagination: { infinite: true },
      rows: { appendable: false, selectable: { multiple: true } },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        { type: 'gutter', gutterName: 'row-selector', multiple: true },
        {
          type: 'boolean',
          name: 'completed',
          header: i18next.t('field.done'),
          width: 60
        },
        {
          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: 150
        },
        {
          type: 'string',
          name: 'productBrand',
          header: i18next.t('field.brand'),
          width: 100
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 100
        },
        {
          type: 'number',
          name: 'packingSize',
          header: i18next.t('field.packing_size'),
          width: 140
        },
        {
          type: 'float',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          width: 120
        },
        {
          type: 'float',
          name: 'releaseUomValue',
          header: i18next.t('field.release_uom_value'),
          width: 140
        }
      ]
    }
  }

  async autoAssign() {
    try {
      this.validateCheckedItems()
      const selectedItems = this.grist.selected

      let filterBizplace = []
      if (this.worksheetType === WORKSHEET_TYPE.BATCH_PICKING.value)
        filterBizplace = this.data.records.map(record => record.bizplace?.id)
      else if (this.worksheetType === WORKSHEET_TYPE.PICKING.value)
        filterBizplace = this.data.records.map(record => record.bizplaceId)

      let bizplaceId = [...new Set(filterBizplace)]

      if (selectedItems.some(record => record.completed)) {
        const result = await CustomAlert({
          title: i18next.t('title.are_you_sure'),
          text: i18next.t('text.there_is_completed_item_already'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) {
          return
        }
      }

      CustomAlert({
        title: i18next.t('title.inventory_auto_assign'),
        text: i18next.t('text.please_wait'),
        allowOutsideClick: true,
        allowEscapeKey: true
      })
      //// Note: Picking and Batch picking has been moved to server side processing.
      switch (this.worksheetType) {
        case WORKSHEET_TYPE.PICKING.value:
          await this._pickingAssignItem(this.worksheetNo, bizplaceId[0], selectedItems)
          break

        case WORKSHEET_TYPE.BATCH_PICKING.value:
          await this._batchPickingAssignItem(this.worksheetId, bizplaceId[0], selectedItems)
          break
      }

      await CustomAlert({
        title: i18next.t('title.completed'),
        text: i18next.t('text.inventory_auto_assign_completed'),
        confirmButton: { text: i18next.t('button.confirm') }
      })

      this.dispatchEvent(new CustomEvent('completed'))
      history.back()
    } catch (e) {
      this._showToast(e)
    }
  }

  async _pickingAssignItem(worksheetNo, bizplaceId, selectedItems) {
    await client.mutate({
      mutation: gql`
        mutation generatePickingWorksheetDetails(
          $bizplaceId: String!
          $selectedItems: [OrderInventoryPatch]!
          $worksheetNo: String!
        ) {
          generatePickingWorksheetDetails(
            bizplaceId: $bizplaceId
            selectedItems: $selectedItems
            worksheetNo: $worksheetNo
          )
        }
      `,
      variables: {
        worksheetNo,
        bizplaceId,
        selectedItems: selectedItems.map(item => {
          return {
            batchId: item.batchId,
            packingType: item.packingType,
            packingSize: item.packingSize,
            productId: item.product.id,
            uom: item.uom,
            releaseQty: item.releaseQty,
            releaseUomValue: item.releaseUomValue,
            pickingStrategy: item.product.pickingStrategy,
            orderProductId: item.orderProduct.id
          }
        })
      }
    })
  }

  async _batchPickingAssignItem(worksheetId, bizplaceId, selectedItems) {
    try {
      await client.mutate({
        mutation: gql`
          mutation generateBatchPickingWorksheetDetailsByBulk(
            $worksheetId: String!
            $bizplaceId: String!
            $selectedItems: [OrderInventoryPatch]!
          ) {
            generateBatchPickingWorksheetDetailsByBulk(
              worksheetId: $worksheetId
              bizplaceId: $bizplaceId
              selectedItems: $selectedItems
            )
          }
        `,
        variables: {
          worksheetId,
          bizplaceId,
          selectedItems: selectedItems.map(itm => {
            return {
              batchId: itm.batchId,
              productId: itm.product.id,
              packingType: itm.packingType,
              packingSize: itm.packingSize,
              uom: itm.uom,
              pickingStrategy: itm.product.pickingStrategy,
              releaseQty: itm.releaseQty,
              releaseUomValue: itm.releaseUomValue,
              extraJsonData: JSON.stringify(itm.extraJsonData)
            }
          })
        }
      })
    } catch (e) {
      this._showToast(e)
    }
  }

  validateCheckedItems() {
    if (!this.grist.selected || !this.grist.selected.length)
      throw new Error(i18next.t('text.there_is_no_selected_items'))
  }

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

window.customElements.define('inventory-auto-assign-popup', InventoryAutoAssignPopup)
