import '@things-factory/barcode-ui'
import '@things-factory/grist-ui'
import './select-operator-popup'

import gql from 'graphql-tag'
import { MultiColumnFormStyles } from '@things-factory/form-ui'
import { css, html } from 'lit-element'
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, ScrollbarStyles } from '@things-factory/styles'
import { isMobileDevice } from '@things-factory/utils'
import { WORKSHEET_STATUS } from '../constants'

class WorksheetZonePicking extends localize(i18next)(PageView) {
  static get properties() {
    return {
      _worksheetNo: String,
      _worksheet: Object,
      config: Object,
      _bizplace: String,
      _assignee: Object,
      _loading: Boolean
    }
  }

  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);
        }
        h2 + data-grist {
          padding-top: var(---grist-title-with-grid-padding);
        }
      `
    ]
  }

  constructor() {
    super()
    this._loading = false
    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._worksheet?.status == WORKSHEET_STATUS.DEACTIVATED.value) {
      actions.push({
        title: i18next.t('button.activate'),
        action: this._activateWorksheet.bind(this),
        ...CommonButtonStyles.activate
      })
    }

    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.worksheet_no')}</label>
            <input name="worksheetNo" readonly />

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

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

            <label>${i18next.t('label.release_good_no')}</label>
            <textarea name="releaseGoodNo" rows="5" readonly></textarea>

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

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

      <div class="grist-column">
        <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.worksheet_detail')}</h2>
        <data-grist
          id="grist"
          .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
          .config=${this.config}
          .fetchHandler=${this.fetchHandler.bind(this)}
        ></data-grist>
      </div>
    `
  }

  async pageUpdated(changes) {
    if (this.active && (changes.resourceId || this._worksheetNo)) {
      this._spinner(true)
      if (changes.resourceId) {
        this._worksheetNo = changes.resourceId
        this.form.reset()
        this.grist.fetch()
      }
      this._spinner(false)
    }
  }

  async pageInitialized() {
    this.config = {
      pagination: { infinite: true },
      rows: { appendable: false },
      list: {
        fields: [
          'palletId',
          'cartonId',
          'batchId',
          'product',
          'packingType',
          'location',
          'releaseQty',
          'pickedQty',
          'batchIdRef',
          'status'
        ]
      },
      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: 'string',
          name: 'productName',
          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
        }
      ]
    }
  }

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

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

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

  async fetchHandler() {
    try {
      this._loading = true
      if (!this._worksheetNo) return

      const response = await client.query({
        query: gql`
          query zonePickingWorksheet($name: String!) {
            zonePickingWorksheet(name: $name) {
              worksheet {
                bizplace {
                  id
                  name
                }
                assignee {
                  id
                  name
                }
                id
                name
                status
              }
              worksheetDetail {
                name
              }
              groupedOrderInventories {
                inventory {
                  batchId
                  packingType
                  palletId
                  obsolete
                  qty
                  lockedQty
                  uom
                  location {
                    name
                  }
                }
                product {
                  sku
                  name
                  brand
                }
                releaseQty
                pickedQty
                releaseUomValue
                conversion
              }
              releaseGood {
                name
              }
            }
          }
        `,
        variables: { name: this._worksheetNo }
      })

      if (!response.errors) {
        const zoneWorksheet = response.data.zonePickingWorksheet
        const worksheet = zoneWorksheet.worksheet
        this._worksheet = worksheet
        this._bizplace = worksheet.bizplace
        this._assignee = worksheet.assignee || {}

        //map data to grist
        let records = zoneWorksheet.groupedOrderInventories.map(item => {
          const inventory = item.inventory
          const availableQty = inventory.qty - inventory.lockedQty
          const releaseUomValueWithUom = `${item.releaseUomValue} ${inventory.uom}`
          return {
            batchId: inventory.batchId,
            palletId: inventory.palletId,
            productSku: item.product.sku,
            productName: item.product.name,
            productBrand: item.product.brand,
            packingType: inventory.packingType,
            location: inventory.location,
            availableQty: availableQty,
            releaseQty: item.releaseQty,
            pickedQty: item.pickedQty,
            releaseUomValueWithUom: releaseUomValueWithUom,
            obsolete: inventory.obsolete
          }
        })

        //fill in data in form
        let releaseGoodNo = [...new Set(zoneWorksheet.releaseGood.map(releaseGood => releaseGood.name))].join(',\n')

        this._fillupForm({
          worksheetNo: worksheet.name,
          bizplace: worksheet.bizplace.name,
          status: worksheet.status,
          releaseGoodNo: releaseGoodNo,
          assignee: worksheet.assignee?.name || ''
        })
        this.updateContext()

        return { records }
      }
    } catch (e) {
      this._showToast(e)
    } finally {
      this._loading = false
    }
  }

  async _activateWorksheet() {
    if (!this._loading) {
      try {
        const result = await CustomAlert({
          title: i18next.t('title.are_you_sure'),
          text: i18next.t('text.activate_zone_picking_worksheet'),
          confirmButton: { text: i18next.t('button.confirm') },
          cancelButton: { text: i18next.t('button.cancel') }
        })

        if (!result.value) {
          this._spinner(false)
          return
        }

        this._spinner(true)

        const response = await client.mutate({
          mutation: gql`
            mutation activateWorksheetZonePicking($name: String!) {
              activateWorksheetZonePicking(name: $name) {
                name
              }
            }
          `,
          variables: { name: this._worksheetNo }
        })
        if (!response.errors) {
          this._showToast({ message: i18next.t('text.worksheet_activated') })
          this.updateContext()
          navigate(`zone_worksheets`)
        }
      } catch (e) {
        this._showToast(e)
      } finally {
        this._spinner(false)
      }
    }
  }

  _selectOperator() {
    openPopup(
      html`
        <select-operator-popup
          .bizplace=${this._bizplace?.id}
          @updateOperator="${async e => {
            this._assignee = e.detail
            this.assigneeField.value = this._assignee.name || ''
            await this.assignWorker()
          }}"
        ></select-operator-popup>
      `,
      {
        backdrop: true,
        size: 'medium',
        title: 'select operator'
      }
    )
  }

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

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

  _fillupForm(data) {
    for (let key in data) {
      Array.from(this.form.querySelectorAll('input, select, textarea')).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]
          }
        }
      })
    }
  }

  _spinner(show) {
    if (show) {
      this._loading = true
      this.grist.showSpinner()
    } else {
      this._loading = false
      this.grist.hideSpinner()
    }
  }

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

window.customElements.define('worksheet-zone-picking', WorksheetZonePicking)
