import '@things-factory/barcode-ui'
import { SingleColumnFormStyles } from '@things-factory/form-ui'
import { client } from '@things-factory/shell'
import gql from 'graphql-tag'
import { i18next, localize } from '@things-factory/i18n-base'
import { css, html, LitElement } from 'lit-element'
import { openPopup } from '@things-factory/layout-base'
import '../components/select-cc-product-popup'

class AddExtraInventoryPopup extends localize(i18next)(LitElement) {
  static get properties() {
    return {
      bizplaceId: String,
      bizplaceName: String,
      cycleCountNo: String,
      countNo: Number,
      productDetailId: String,
      productId: String,
      config: Object,
      data: Object
    }
  }

  static get styles() {
    return [
      SingleColumnFormStyles,
      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;
        }
        .input-container {
          display: flex;
        }
        .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);
        }
        .button-container button {
          background-color: var(--button-container-button-background-color);
          border-radius: var(--button-container-button-border-radius);
          height: var(--button-container-button-height);
          border: var(--button-container-button-border);
          margin: var(--button-container-button-margin);
          padding: var(--button-padding);
          color: var(--theme-white-color);
          font: var(--button-font);
          text-transform: var(--button-text-transform);
        }
        .button-container button:hover,
        .button-container button:active {
          background-color: var(--button-background-focus-color);
        }
        .button-container > barcode-scanable-input {
          margin: auto;
        }
      `
    ]
  }

  async firstUpdated() {
    await this.updateComplete

    if (this.skuInput) this.skuInput.value = ''
    if (this.inspectedLocationInput) this.inspectedLocationInput.value = ''
    if (this.inspectedBatchNoInput) this.inspectedBatchNoInput.value = ''
    if (this.inspectedQtyInput) this.inspectedQtyInput.value = ''
    if (this.inspectedUomValueInput) this.inspectedUomValueInput.value = ''
    this.inspectedExpirationDate = ''
    this.productDetailId = ''
    this.productId = ''
  }

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

  get skuInput() {
    return this.shadowRoot.querySelector('input[name=sku]')
  }

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

  get inspectedBatchNoInput() {
    return this.shadowRoot.querySelector('input[name=inspectedBatchNo]')
  }

  get inspectedQtyInput() {
    return this.shadowRoot.querySelector('input[name=inspectedQty]')
  }

  get inspectedUomValueInput() {
    return this.shadowRoot.querySelector('input[name=inspectedUomValue]')
  }

  get inspectedExpirationDateInput() {
    return this.shadowRoot.querySelector('input[name=inspectedExpirationDate]')
  }

  render() {
    return html`
      <form
        id="input-form"
        class="single-column-form"
        @keypress="${async e => {
          if (e.keyCode === 13) {
            e.preventDefault()
            this._checkPalletId()
          }
        }}"
      >
        <fieldset>
          <label>${i18next.t('label.location')}</label>
          <barcode-scanable-input name="inspectedLocation" custom-input></barcode-scanable-input>
          <label>${i18next.t('label.sku')}</label>
          <input name="sku" type="text" .value=${this.sku} custom-input @click="${this._openProductSelection}" />
          <label>${i18next.t('label.uom')}</label>
          <input name="uom" type="text" .value=${this.uom || ''} readonly />
          <label>${i18next.t('label.inspected_batch_no')}</label>
          <input name="inspectedBatchNo" type="text" .value=${this.inspectedBatchNo} custom-input />
          <label>${i18next.t('label.inspected_qty')}</label>
          <input name="inspectedQty" type="text" .value=${this.inspectedQty} custom-input />
          <label>${i18next.t('label.inspected_expiration_date')}</label>
          <input name="inspectedExpirationDate" type="date" .value=${this.inspectedExpirationDate} custom-input />
          ${!this.enableCartonLabel
            ? html`
                <label>${i18next.t('label.inspected_uom_value')} </label>
                <input name="inspectedUomValue" type="text" .value=${this.inspectedUomValue} custom-input />
              `
            : ''}
        </fieldset>
      </form>
      <div class="button-container">
        <mwc-button raised @click="${this._submitInventory}" label="${i18next.t('button.confirm')}"></mwc-button>
      </div>
    `
  }

  focusOnPalletInput() {
    this.palletIdInput.focus()
  }

  focusOnInspectedLocationInput() {
    this.inspectedLocationInput.focus()
  }

  _openProductSelection() {
    openPopup(
      html`
        <select-cc-product-popup
          .bizplaceId="${this.bizplaceId}"
          @selected="${e => {
            // e.detail will contain the data about the selected product
            if (e.detail) {
              this.productDetailId = e.detail.productDetailId
              this.sku = e.detail.product.sku
              this.productId = e.detail.product.id
              this.uom = e.detail.uom
              this.requestUpdate()
            }
          }}"
        ></select-cc-product-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_item')
      }
    )
  }

  async _submitInventory() {
    try {
      await this._validateInput()
      let inspectedBatchNo = this.inspectedBatchNoInput.value
      let inspectedExpirationDate = this.inspectedExpirationDateInput.value
        ? new Date(this.inspectedExpirationDateInput.value)
        : null
      let inspectedQty = Number(this.inspectedQtyInput.value)
      let inspectedUomValue = this.enableCartonLabel ? inspectedQty : Number(this.inspectedUomValueInput.value)
      let inspectedLocation = this.inspectedLocationInput.value
      let productDetailId = this.productDetailId
      let productId = this.productId
      let countNo = this.countNo

      const response = await client.mutate({
        mutation: gql`
          mutation addExtraInventory(
            $cycleCountNo: String!
            $inspectedLocation: String!
            $productDetailId: String!
            $productId: String!
            $inspectedBatchNo: String!
            $inspectedQty: Float!
            $inspectedUomValue: Float!
            $countNo: Int!
            $inspectedExpirationDate: Date
          ) {
            addExtraInventory(
              cycleCountNo: $cycleCountNo
              inspectedLocation: $inspectedLocation
              productDetailId: $productDetailId
              productId: $productId
              inspectedBatchNo: $inspectedBatchNo
              inspectedQty: $inspectedQty
              inspectedUomValue: $inspectedUomValue
              countNo: $countNo
              inspectedExpirationDate: $inspectedExpirationDate
            )
          }
        `,
        variables: {
          cycleCountNo: this.cycleCountNo,
          inspectedLocation,
          productDetailId,
          productId,
          inspectedBatchNo,
          inspectedQty,
          inspectedUomValue,
          countNo,
          inspectedExpirationDate
        }
      })
      this.dispatchEvent(new CustomEvent('add-inventory', {}))
      this._showToast({ message: i18next.t('text.the_inventory_has_been_added') })
    } catch (e) {
      this._showToast({ type: 'error', message: e.message })
    }
  }

  async _validateInput() {
    const inspectedBatchNo = this.inspectedBatchNoInput.value
    if (!inspectedBatchNo) {
      this.selectOnInput(this.inspectedBatchNoInput)
      throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('field.inspected_batch_no') } }))
    }

    const inspectedQty = this.inspectedQtyInput.value
    if (!inspectedQty) {
      this.selectOnInput(this.inspectedQtyInput)
      throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('field.inspected_qty') } }))
    }

    // Check if inspectedQty has more than 3 decimal places
    const decimalPlaces = inspectedQty.toString().split('.')[1]?.length || 0
    if (decimalPlaces > 3) {
      throw new Error(i18next.t('text.maximum_3_decimal_places_allowed'))
    }

    if (inspectedQty <= 0) {
      throw new Error(i18next.t('text.x_should_be_positive', { state: { x: i18next.t('field.inspected_qty') } }))
    }

    const locationName = this.inspectedLocationInput.value
    if (!locationName) {
      this.selectOnInput(this.inspectedLocationInput)
      throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('label.location') } }))
    } else {
      const foundLocation = await this._fetchLocation(locationName)
      if (!foundLocation) {
        throw new Error(i18next.t('text.location_not_found'))
      }
    }
  }

  async _fetchLocation(locationName) {
    if (locationName) {
      const response = await client.query({
        query: gql`
          query location($name: String!) {
            location(name: $name) {
              id
              name
              zone
              row
              column
              shelf
              type
            }
          }
        `,
        variables: { name: locationName }
      })

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

  selectOnInput(input) {
    setTimeout(() => input.select(), 100)
  }

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

window.customElements.define('add-extra-inventory-popup', AddExtraInventoryPopup)
