import '@things-factory/barcode-ui'
import '../../vas/reverse-kitting/popup-combination-sets'

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

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

class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView)) {
  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          overflow: auto;
          display: flex;
          flex-direction: column;
        }
        .container {
          flex: 1;
          display: flex;
        }
        .grist {
          background-color: var(--main-section-background-color);
          display: flex;
          overflow: hidden;
          flex: 1;
        }

        data-grist {
          flex: 1;
        }
      `
    ]
  }

  static get properties() {
    return {
      _orderNo: String,
      orderGristConfig: Object,
      orderData: Object,
      selectedParentInventory: Object
    }
  }

  constructor() {
    super()
    this._orderNo = ''
    this.orderData = { records: [] }
  }

  render() {
    return html`
      <form class="multi-column-form" id="info-form">
        <fieldset>
          <legend>${`${i18next.t('title.scan_area')}`}</legend>
          <barcode-scanable-input
            name="orderNo"
            custom-input
            @keypress="${this.orderNoKeypressHandler.bind(this)}"
          ></barcode-scanable-input>
        </fieldset>
      </form>

      ${this._orderNo
        ? html`<form class="multi-column-form" id="info-form">
              <fieldset>
                <legend>${`${i18next.t('title.order_no')}: ${this._orderNo}`}</legend>
              </fieldset>
            </form>

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

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

    return { title: i18next.t('title.reverse_kitting'), help: 'operato-wms/vas/execute-reverse-kitting', actions }
  }

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

  get completable() {
    let completable = false
    const orderDataWithIssues = this.orderData.records.filter(reverseKittingOI => !reverseKittingOI.completed)
    if (!orderDataWithIssues?.length) {
      completable = this.orderData.records.every(record => record.completed)
    } else {
      completable = orderDataWithIssues.every(record => record.issue)
    }

    return completable
  }

  updated(changedProps) {
    if (changedProps.has('_orderNo') || changedProps.has('orderData')) {
      this.updateContext()
    }
  }

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

  pageInitialized() {
    this.orderGristConfig = {
      pagination: { infinite: true },
      list: { fields: ['completed', 'batchId', 'palletId', 'product', 'qty', 'issue'] },
      rows: {
        appendable: false,
        handlers: {
          click: (columns, data, column, record, rowIndex) => {
            this.selectedParentInventory = record
            this._openPopupCombinationSets(record)
          }
        }
      },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'boolean',
          name: 'completed',
          header: i18next.t('field.completed'),
          label: true,
          width: 40
        },
        { type: 'object', name: 'location', label: true, hidden: true },
        { type: 'object', name: 'product', label: true, hidden: true },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          label: true,
          width: 150
        },
        {
          type: 'string',
          name: 'palletId',
          header: i18next.t('field.lot_id'),
          label: true,
          width: 200
        },
        {
          type: 'integer',
          name: 'qty',
          header: i18next.t('field.qty'),
          label: true,
          width: 60
        },
        {
          type: 'float',
          name: 'uomValue',
          header: i18next.t('field.uom_value'),
          label: true,
          width: 60
        },
        {
          type: 'string',
          name: 'issue',
          header: i18next.t('field.issue'),
          label: true,
          width: 200
        }
      ]
    }
  }

  async fetchReverseKittingOrder() {
    if (!this._orderNo) return
    const response = await client.mutate({
      mutation: gql`
        mutation executingReverseKittingOrder($name: String!) {
          executingReverseKittingOrder(name: $name) {
            id
            name
            status
            bizplace {
              id
              name
              description
            }
            reverseKittingOrderInventories {
              id
              name
              set
              targetType
              targetBatchId
              targetProduct {
                id
                name
                description
              }
              inventory {
                id
                name
                batchId
                batchIdRef
                palletId
                product {
                  id
                  sku
                  name
                  description
                }
                productName
                packingType
                packingSize
                uom
                location {
                  id
                  name
                }
                status
              }
              qty
              uomValue
              otherTarget
              operationGuide
              status
              issue
              description
              remark
            }
          }
        }
      `,
      variables: { name: this._orderNo }
    })

    if (!response.errors) {
      const reverseKittingOrder = response.data.executingReverseKittingOrder
      const reverseKittingOIs = reverseKittingOrder.reverseKittingOrderInventories
      this._orderStatus = reverseKittingOrder.status

      this.orderData = {
        records: reverseKittingOIs.map(reverseKittingOI => {
          const inventory = reverseKittingOI.inventory
          return {
            ...reverseKittingOI,
            completed: this.checkComplete(reverseKittingOI),
            batchId: inventory.batchId,
            palletId: inventory.palletId,
            location: inventory.location,
            product: inventory.product
          }
        })
      }
    }
  }

  checkComplete(record) {
    let completed = false
    let operationGuide = JSON.parse(record.operationGuide)
    completed = operationGuide.data.productCombinationSets.every(item => item.qty === item.actualQty)

    return completed
  }

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

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

      if (!result.value) {
        return
      }

      const response = await client.mutate({
        mutation: gql`
          mutation completeReverseKittingOrder($name: String!) {
            completeReverseKittingOrder(name: $name)
          }
        `,
        variables: {
          name: this._orderNo
        }
      })
      if (!response.errors) {
        await CustomAlert({
          title: i18next.t('title.completed'),
          text: i18next.t('text.reverse_kitting_completed'),
          confirmButton: { text: i18next.t('button.confirm') }
        })

        this._orderNo = null
        this._clearView()
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  async orderNoKeypressHandler(e) {
    if (e.keyCode === 13) {
      e.preventDefault()
      this._orderNo = this.orderNoInput.value
      this.orderNoInput.value = ''
      await this.fetchReverseKittingOrder()
    }
  }

  _validateComplete() {
    if (!this._orderNo) {
      throw new Error(i18next.t('text.there_is_no_reverse_kitting_no'))
    }
  }

  _clearView() {
    this.orderData = { records: [] }
    this._selectedParentInventory = null
    this.updateContext()
  }

  _focusOnOrderNoField() {
    setTimeout(() => this.orderNoInput.focus(), 100)
  }

  async _openPopupCombinationSets(record) {
    await sleep(1010)
    openPopup(
      html`
        <popup-combination-sets
          .orderNo="${this._orderNo}"
          .data="${record}"
          @order-reverse-kitting-data="${e => {
            this.fetchReverseKittingOrder(this._orderNo)
          }}"
        ></popup-combination-sets>
      `,
      {
        backdrop: true,
        escapable: false,
        closable: false,
        size: 'large',
        title: record.palletId
      }
    )
  }

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

window.customElements.define('execute-reverse-kitting', ExecuteReverseKitting)
