import '@things-factory/grist-ui'
import { MultiColumnFormStyles } from '@things-factory/form-ui'
import { openPopup } from '@things-factory/layout-base'
import { client, CustomAlert } from '@things-factory/shell'
import { i18next, localize } from '@things-factory/i18n-base'
import { isMobileDevice } from '@things-factory/utils'
import { css, html, LitElement } from 'lit-element'
import gql from 'graphql-tag'
import { ScrollbarStyles } from '@things-factory/styles'
import { ORDER_STATUS, RO_TYPES } from '../../constants'
import { fetchSettingRule } from '../../../fetch-setting-value'
import '@things-factory/biz-ui'

class BatchPickingPopup extends localize(i18next)(LitElement) {
  static get properties() {
    return {
      roConfig: Object,
      _roName: String,
      orderInventoryConfig: Object,
      mergedData: Object,
      _searchFields: Array,
      partnerBizplace: Object
    }
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      ScrollbarStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow: hidden;
          background-color: white;
        }
        search-form {
          overflow: visible;
        }
        .grist {
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        .grist-container {
          overflow-y: hidden;
          display: flex;
          flex: 1;
        }
        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 {
          font: var(--grist-title-font);
        }
        .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);
        }
      `
    ]
  }

  submit() {
    this.dispatchEvent(new CustomEvent('submit'))
  }

  render() {
    return html`
      <!-- <form class="multi-column-form">
        <fieldset>
          <label>${i18next.t('label.customer')}</label>
          <input
            readonly
            name="partnerDomain"
            value="${this.partnerDomain?.name ? this.partnerDomain.name : ''}"
            @click="${this.openPartnerSelector.bind(this)}"
            placeholder="${i18next.t('text.please_choose_partner')}"
          />
        </fieldset>
      </form> -->
      <search-form .fields=${this._searchFields} @submit=${() => this.releaseOrderGrist.fetch()}></search-form>

      <div class="grist-container">
        <div class="grist">
          <h2>${i18next.t('title.release_order')}</h2>
          <data-grist
            id="releaseOrder"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.roConfig}
            .fetchHandler="${this.fetchReadyToPickOrders.bind(this)}"
          ></data-grist>
        </div>

        <div class="grist">
          <h2>${i18next.t('title.merged_picking_list')}</h2>
          <data-grist
            id="orderInventory"
            .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
            .config=${this.orderInventoryConfig}
            .data="${this.mergedData}"
          ></data-grist>
        </div>
      </div>

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

  async firstUpdated() {
    this._searchFields = [
      {
        label: i18next.t('field.company'),
        name: 'partnerBizplace',
        type: 'text',
        value: '',
        handlers: {
          click: this.openPartnerSelector.bind(this)
        },
        props: { searchOper: 'eq', readonly: true },
        placeholder: `${i18next.t('text.please_choose_partner')}`
      },
      {
        label: i18next.t('field.release_date'),
        name: 'releaseDate',
        type: 'date',
        props: { searchOper: 'lte' }
      },
      {
        label: i18next.t('field.type'),
        name: 'type',
        type: 'select',
        options: Object.keys(RO_TYPES).map(map => {
          return { name: RO_TYPES[map].name, value: RO_TYPES[map].value }
        }),
        props: { searchOper: 'eq' }
      }
    ]

    this.roConfig = {
      pagination: { infinite: true },
      rows: {
        selectable: { multiple: true },
        appendable: false
      },
      list: { fields: ['name', 'refNo', 'bizplace', 'releaseDate'] },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        { type: 'gutter', gutterName: 'row-selector', multiple: true },
        {
          type: 'string',
          name: 'name',
          header: i18next.t('field.release_good_no'),
          width: 150
        },
        {
          type: 'string',
          name: 'type',
          header: i18next.t('field.type'),
          width: 100
        },
        {
          type: 'string',
          name: 'refNo',
          header: i18next.t('field.ref_no'),
          width: 130
        },
        {
          type: 'object',
          name: 'bizplace',
          header: i18next.t('field.company'),
          width: 200
        },
        {
          type: 'date',
          name: 'releaseDate',
          header: i18next.t('field.release_date'),
          sortable: true,
          width: 150
        }
      ]
    }

    this.orderInventoryConfig = {
      pagination: { infinite: true },
      rows: { appendable: false },
      list: { fields: ['batchId', 'productName', 'packingType', 'releaseQty', 'releaseUomValue'] },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 150
        },
        {
          type: 'string',
          name: 'productName',
          header: i18next.t('field.product'),
          width: 240
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 150
        },
        {
          type: 'integer',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          width: 100
        },
        {
          type: 'integer',
          name: 'releaseUomValue',
          header: i18next.t('field.release_uom_value'),
          width: 100
        },
        {
          type: 'string',
          name: 'batchIdRef',
          header: i18next.t('field.batch_no_ref'),
          width: 150
        }
      ]
    }
  }

  get searchForm() {
    return this.renderRoot.querySelector('search-form')
  }

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

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

  openPartnerSelector() {
    openPopup(
      html`
        <popup-partner-bizplaces-selector
          @selected="${e => {
            this.partnerBizplace = e.detail
            this._searchFields.find(x => x.name == 'partnerBizplace').value = e.detail.name
            this._searchFields = [...this._searchFields]

            this.releaseOrderGrist.fetch()
          }}"
        ></popup-partner-bizplaces-selector>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.partner')
      }
    )
  }

  async fetchReadyToPickOrders({ page, limit, sorters = [{ name: 'releaseDate' }] }) {
    if (!this.partnerBizplace) return { total: 0, records: [] }

    const filters = [
      ...(await this.searchForm.getQueryFilters()).filter(x => x.name != 'partnerBizplace'),
      { name: 'status', operator: 'eq', value: ORDER_STATUS.PENDING_WORKSHEET.value },
      { name: 'crossDocking', operator: 'eq', value: false },
      { name: 'bizplaceId', operator: 'eq', value: this.partnerBizplace.id }
    ]

    let batchLimit = await fetchSettingRule('batch-picking-limit')
    const pagination = { page, limit: batchLimit && !!parseInt(batchLimit) ? parseInt(batchLimit) : 20 }
    const sortings = sorters

    const response = await client.query({
      query: gql`
        query releaseGoodRequests($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
          releaseGoodRequests(filters: $filters, pagination: $pagination, sortings: $sortings) {
            items {
              id
              name
              refNo
              releaseDate
              type
              routeId
              bizplace {
                id
                name
                description
              }
              recall
            }
            total
          }
        }
      `,
      variables: { filters, pagination, sortings }
    })
    if (!response.errors) {
      return {
        total: response.data.releaseGoodRequests.total || 0,
        records: response.data.releaseGoodRequests.items || []
      }
    }
  }

  async generateItemList({ page, limit, sorters = [{ name: 'product' }] }) {
    if (this.releaseOrderGrist.selected.length < 2) return
    let roIds = this.releaseOrderGrist.selected.map(record => record.id) || []
    const filters = [
      {
        name: 'releaseGood',
        operator: 'in',
        value: roIds
      }
    ]
    const pagination = { page, limit }
    const sortings = sorters

    const response = await client.query({
      query: gql`
        query mergedProductOrderInventories($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
          mergedProductOrderInventories(filters: $filters, pagination: $pagination, sortings: $sortings) {
            items {
              productName
              packingType
              batchId
              batchIdRef
              releaseQty
              releaseUomValue
            }
            total
          }
        }
      `,
      variables: { filters, pagination, sortings }
    })

    if (!response.errors) {
      this.mergedData = {
        total: response.data.mergedProductOrderInventories.total || 0,
        records: response.data.mergedProductOrderInventories.items || []
      }
    }
  }

  async generateBatchPicking() {
    try {
      const data = this.releaseOrderGrist
      if (this.releaseOrderGrist.selected.length < 2) throw new Error('Minimum of 2 orders required for batch picking')

      let uniqueWS = this.releaseOrderGrist.selected.filter(
        res => res.recall !== this.releaseOrderGrist.selected[0].recall
      )

      if (uniqueWS.length > 0) {
        throw new Error("Recall Release Order can't be generated together with Normal Release Order")
      }

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

      if (!result.value) return

      let withRouteLabel = this.releaseOrderGrist.selected.find(itm => itm.routeId)
      let withoutRouteLabel = this.releaseOrderGrist.selected.find(itm => itm.routeId == null)

      if (withRouteLabel && withoutRouteLabel) {
        throw new Error(`RO without route labelling is included in the batch picking`)
      }

      let releaseGoodNos = []
      releaseGoodNos = this.releaseOrderGrist.selected.map(record => record.name)

      const response = await client.mutate({
        mutation: gql`
          mutation generateBatchPickingWorksheet($releaseGoodNos: [String!], $partnerBizplaceId: String!) {
            generateBatchPickingWorksheet(releaseGoodNos: $releaseGoodNos, partnerBizplaceId: $partnerBizplaceId) {
              name
            }
          }
        `,
        variables: {
          releaseGoodNos,
          partnerBizplaceId: this.partnerBizplace.id
        }
      })

      if (!response.errors) {
        this.dispatchEvent(new CustomEvent('generated'))
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _showToast({ type, message }) {
    document.dispatchEvent(
      new CustomEvent('notify', {
        detail: {
          type,
          message
        }
      })
    )
  }
}
window.customElements.define('batch-picking-popup', BatchPickingPopup)
