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 gql from 'graphql-tag'
import { css, html, LitElement } from 'lit-element'

class CycleCountRecheckPopup extends localize(i18next)(LitElement) {
  static get properties() {
    return {
      enableCartonLabel: Boolean,
      cycleCountNo: String,
      inventories: Array,
      customerId: 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);
        }
        .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-container-button-font);
          text-transform: var(--button-text-transform);
        }
        .button-container button:hover,
        .button-container button:active {
          background-color: var(--button-background-focus-color);
        }
      `
    ]
  }

  render() {
    return html`
      <form id="input-form" class="multi-column-form">
        <fieldset>
          <legend>${i18next.t('title.cycle_count')}</legend>
          <label>${i18next.t('field.execution_date')}</label>
          <input name="executionDate" type="date" min="${this._getStdDate()}" required />
        </fieldset>
      </form>

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

      <div class="button-container">
        <mwc-button raised @click="${this.createCycleCountRecheck.bind(this)}"
          >${i18next.t('button.create')}</mwc-button
        >
        <mwc-button raised danger @click="${() => history.back()}">${i18next.t('button.cancel')}</mwc-button>
      </div>
    `
  }

  get form() {
    return this.renderRoot.querySelector('form#input-form')
  }

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

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

  constructor() {
    super()
    this.data = { records: [] }
  }

  async firstUpdated() {
    this.config = {
      rows: { appendable: false },
      list: {
        fields: [
          'palletId',
          'product',
          'batchId',
          'inspectedBatchNo',
          'packingType',
          'inspectedLocation',
          'inspectedQty',
          'inspectedUomValue',
          'uom',
          'status'
        ]
      },
      pagination: { infinite: true },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        { type: 'gutter', gutterName: 'row-selector', multiple: true },
        {
          type: 'string',
          name: 'cartonId',
          header: i18next.t('field.carton_id'),
          width: 120
        },
        {
          type: 'string',
          name: 'palletId',
          header: i18next.t('field.lot_id'),
          width: 120
        },
        {
          type: 'object',
          name: 'product',
          header: i18next.t('field.product'),
          width: 320
        },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          width: 100
        },
        {
          type: 'string',
          name: 'inspectedBatchNo',
          header: i18next.t('field.inspected_batch_no'),
          width: 100
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          width: 100
        },
        {
          type: 'object',
          name: 'location',
          header: i18next.t('field.system_location'),
          width: 120
        },
        {
          type: 'object',
          name: 'inspectedLocation',
          header: i18next.t('field.inspected_location'),
          width: 120
        },
        {
          type: 'string',
          name: 'originExpirationDate',
          header: i18next.t('field.system_expiration_date'),
          width: 120
        },
        {
          type: 'string',
          name: 'inspectedExpirationDate',
          header: i18next.t('field.inspected_expiration_date'),
          width: 120
        },
        {
          type: 'float',
          name: 'qty',
          header: i18next.t('field.system_qty'),
          width: 100
        },
        {
          type: 'float',
          name: 'inspectedQty',
          header: i18next.t('field.inspected_qty'),
          width: 100
        },
        {
          type: 'float',
          name: 'uomValue',
          header: i18next.t('field.system_uom_value'),
          width: 100
        },
        {
          type: 'float',
          name: 'inspectedUomValue',
          header: i18next.t('field.inspected_uom_value'),
          width: 100
        },
        {
          type: 'string',
          name: 'uom',
          header: i18next.t('field.uom'),
          width: 80
        },
        {
          type: 'string',
          name: 'status',
          header: i18next.t('field.status'),
          width: 150
        }
      ]
    }
    this._updateConfig()
  }

  _updateConfig() {
    this.config.columns = this.config.columns.filter(column => {
      if (this.enableCartonLabel) {
        return column.name !== 'palletId'
      } else {
        return column.name !== 'cartonId'
      }
    })
  }

  updated(changedProps) {
    if (changedProps.has('cycleCountNo')) {
      this.fetchNotTallyInventories()
    }
  }

  async fetchNotTallyInventories() {
    const response = await client.query({
      query: gql`
        query notTallyTargetInventories($cycleCountNo: String!) {
          notTallyTargetInventories(cycleCountNo: $cycleCountNo) {
            id
            inventory {
              cartonId
              palletId
              uom
              product {
                name
                description
              }
              packingType
            }
            originBatchNo
            inspectedBatchNo
            originLocation {
              name
              description
            }
            inspectedLocation {
              name
              description
            }
            originQty
            inspectedQty
            originUomValue
            inspectedUomValue
            systemExpiryDate
            inspectedExpiryDate
            status
            countNo
            product {
              sku
              name
              description
            }
            productDetail {
              id
              packingType
              uom
            }
          }
        }
      `,
      variables: {
        cycleCountNo: this.cycleCountNo
      }
    })

    if (!response.errors) {
      let records = response.data.notTallyTargetInventories.map(targetInv => {
        return {
          id: targetInv.id,
          batchId: targetInv.originBatchNo,
          inspectedBatchNo: targetInv?.inspectedBatchNo,
          cartonId: targetInv.inventory?.cartonId,
          palletId: targetInv.inventory?.palletId,
          product: targetInv.inventory?.product ? targetInv.inventory.product : targetInv.product,
          productDetail: targetInv.productDetail,
          packingType: targetInv.inventory?.packingType
            ? targetInv.inventory.packingType
            : targetInv.productDetail.packingType,
          location: targetInv.originLocation || '',
          inspectedLocation: targetInv.inspectedLocation || '',
          qty: targetInv?.originQty,
          inspectedQty: targetInv?.inspectedQty,
          originExpirationDate: targetInv?.systemExpiryDate,
          inspectedExpirationDate: targetInv?.inspectedExpiryDate,
          uomValue: targetInv.originUomValue,
          uom: targetInv?.inventory && targetInv.inventory?.uom,
          inspectedUomValue: targetInv.inspectedUomValue,
          status: targetInv.status,
          countNo: targetInv.countNo
        }
      })

      let groupedTotal = 0

      if (this.enableCartonLabel) {
        const groupedRecords = {}

        records.forEach(record => {
          const groupKey = `${record.cartonId || ''}-${record.batchId || ''}-${record.productDetail.id || ''}-${
            record.location.name || ''
          }`

          if (!groupedRecords[groupKey]) {
            groupedRecords[groupKey] = { ...record, count: 1 }
            groupedTotal++
          } else {
            groupedRecords[groupKey].qty += record.qty || 0
            groupedRecords[groupKey].inspectedQty += Number(record.inspectedQty) || 0
            groupedRecords[groupKey].uomValue += record.uomValue || 0
            groupedRecords[groupKey].inspectedUomValue += record.inspectedUomValue || 0
            groupedRecords[groupKey].count += 1
          }
        })

        records = Object.values(groupedRecords)
      }
      this.data = { records, total: groupedTotal || records.length }
    }
  }

  async createCycleCountRecheck() {
    try {
      this.checkValidity()

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

      if (!result.value) {
        return
      }

      // Variables for the mutation, structured based on the condition
      let variables = {
        executionDate: this.executionDateInput.value,
        customerId: this.customerId,
        cycleCountNo: this.cycleCountNo
      }

      let mutation
      if (this.enableCartonLabel) {
        variables.inventoryCheckItemIds = this.grist.selected.map(record => record.id)

        mutation = gql`
          mutation generateCycleCountWorksheetCarton(
            $executionDate: String!
            $customerId: String!
            $cycleCountNo: String
            $inventoryCheckItemIds: [String]
          ) {
            generateCycleCountWorksheetCarton(
              executionDate: $executionDate
              customerId: $customerId
              cycleCountNo: $cycleCountNo
              inventoryCheckItemIds: $inventoryCheckItemIds
            ) {
              name
            }
          }
        `
      } else {
        variables.inventoryCheckItemIds = this.grist.selected.map(record => record.id)

        mutation = gql`
          mutation generateCycleCountWorksheet(
            $executionDate: String!
            $customerId: String!
            $inventoryCheckItemIds: [String]
            $cycleCountNo: String
          ) {
            generateCycleCountWorksheet(
              executionDate: $executionDate
              customerId: $customerId
              inventoryCheckItemIds: $inventoryCheckItemIds
              cycleCountNo: $cycleCountNo
            ) {
              name
            }
          }
        `
      }

      const response = await client.mutate({
        mutation: mutation,
        variables: variables
      })

      if (!response.errors) {
        this.dispatchEvent(new CustomEvent('completed'))
        history.back()
        this.showToast({ message: i18next.t('text.cycle_count_worksheet_created') })
      }
    } catch (e) {
      this.showToast(e)
    }
  }

  checkValidity() {
    // Execution date
    if (!this.form.checkValidity()) {
      throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('field.execution_date') } }))
    }

    // Is there selected inventories
    if (!this.grist.selected?.length) {
      throw new Error(i18next.t('text.there_is_no_selected_items'))
    }
  }

  _getStdDate() {
    let date = new Date()
    date.setDate(date.getDate())
    return date.toISOString().split('T')[0]
  }

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

window.customElements.define('cycle-count-recheck-popup', CycleCountRecheckPopup)
