import '@things-factory/barcode-ui'
import { MultiColumnFormStyles } from '@things-factory/form-ui'
import '@things-factory/grist-ui'
import { i18next, localize } from '@things-factory/i18n-base'
import { client, CustomAlert, navigate, PageView } from '@things-factory/shell'
import { CommonButtonStyles } from '@things-factory/styles'
import { isMobileDevice } from '@things-factory/utils'
import gql from 'graphql-tag'
import { css, html } from 'lit-element'
import { WORKSHEET_STATUS } from '../constants'
import { fetchSettingRule } from '../../fetch-setting-value'

class WorksheetCycleCount extends localize(i18next)(PageView) {
  static get properties() {
    return {
      _worksheetNo: String,
      _worksheetStatus: String,
      _cycleCountNo: String,
      _enableCartonLabel: Boolean,
      config: Object,
      data: Object
    }
  }

  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: column;
          flex: 1;
          overflow-y: 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);
        }

        .grist h2 mwc-icon {
          vertical-align: middle;
          margin: var(--grist-title-icon-margin);
          font-size: var(--grist-title-icon-size);
          color: var(--grist-title-icon-color);
        }

        h2 + data-grist {
          padding-top: var(--grist-title-with-grid-padding);
        }
      `
    ]
  }

  get context() {
    var actions = [
      {
        title: i18next.t('button.back'),
        action: () => navigate('cycle_count_worksheet_list'),
        ...CommonButtonStyles.back
      }
    ]

    if (this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value) {
      actions.push({
        title: i18next.t('button.activate'),
        action: this._activateWorksheet.bind(this),
        ...CommonButtonStyles.activate
      })
    }

    return {
      title: i18next.t('title.cycle_count_worksheet_detail'),
      actions,
      printable: {
        accept: ['preview'],
        content: this
      },
      help: 'operato-wms/inventory-check/worksheet-cycle-count'
    }
  }

  get computedColumns() {
    if (this._enableCartonLabel) {
      return this.preConfig.columns.filter(column => column.name !== 'palletId')
    } else {
      return this.preConfig.columns.filter(column => column.name !== 'cartonId')
    }
  }

  render() {
    return html`
      <div class="form-container">
        <form class="multi-column-form">
          <fieldset>
            <legend>${i18next.t('title.cycle_count')}</legend>
            <label>${i18next.t('label.company')}</label>
            <input name="bizplace" readonly />

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

            <label>${i18next.t('label.execute_date')}</label>
            <input type="date" name="executionDate" readonly />

            <label>${i18next.t('label.status')}</label>
            <select name="status" disabled>
              ${Object.keys(WORKSHEET_STATUS).map(
                key => html` <option value="${WORKSHEET_STATUS[key].value}">${WORKSHEET_STATUS[key].name}</option> `
              )}
            </select>

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

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

      <div class="grist">
        <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.inventory')}</h2>

        <data-grist
          id="grist"
          .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
          .config=${{ ...this.preConfig, columns: this.computedColumns }}
          .fetchHandler="${this.fetchWorksheet.bind(this)}"
        ></data-grist>
      </div>
    `
  }

  constructor() {
    super()
    this._enableCartonLabel = false
  }

  pageUpdated(changes) {
    if (this.active && (changes.resourceId || this._worksheetNo)) {
      if (changes.resourceId) {
        this._worksheetNo = changes.resourceId
      }
      this.grist.fetch()
      this._updateGristConfig()
    }
  }

  updated(changedProps) {
    if (changedProps.has('_worksheetStatus')) {
      this.updateContext()
    }
  }

  pageInitialized() {
    this.preConfig = {
      rows: { appendable: false },
      list: {
        fields: ['batchId', 'cartonId', 'palletId', 'sku', 'product', 'location', 'status']
      },
      pagination: { limit: 100, pages: [20, 50, 100, 200, 500] },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'batchId',
          header: i18next.t('field.batch_id'),
          imex: { header: i18next.t('field.batch_id'), key: 'batchId', width: 100, type: 'string' },
          width: 100
        },
        {
          type: 'string',
          name: 'cartonId',
          header: i18next.t('field.carton_id'),
          imex: { header: i18next.t('field.carton_id'), key: 'cartonId', width: 150, type: 'string' },
          width: 150
        },
        {
          type: 'string',
          name: 'palletId',
          header: i18next.t('field.lot_id'),
          imex: { header: i18next.t('field.lot_id'), key: 'palletId', width: 150, type: 'string' },
          width: 150
        },
        {
          type: 'string',
          name: 'sku',
          header: i18next.t('field.sku'),
          imex: { header: i18next.t('field.sku'), key: 'sku', width: 150, type: 'string' },
          width: 150
        },
        {
          type: 'object',
          name: 'product',
          header: i18next.t('field.product'),
          imex: {
            header: i18next.t('field.product'),
            key: 'product.name',
            width: 50,
            type: 'string'
          },
          width: 350
        },
        {
          type: 'string',
          name: 'brand',
          header: i18next.t('field.brand'),
          imex: {
            header: i18next.t('field.brand'),
            key: 'brand',
            width: 15,
            type: 'string'
          },
          width: 100
        },
        {
          type: 'object',
          name: 'location',
          header: i18next.t('field.location'),
          imex: {
            header: i18next.t('field.location'),
            key: 'location.name',
            width: 15,
            type: 'string'
          },
          width: 100
        },
        {
          type: 'string',
          name: 'packingType',
          header: i18next.t('field.packing_type'),
          imex: { header: i18next.t('field.packing_type'), key: 'packingType', width: 100, type: 'string' },
          width: 100
        },
        {
          type: 'string',
          name: 'uom',
          header: i18next.t('field.uom'),
          imex: {
            header: i18next.t('field.uom'),
            key: 'uom',
            width: 80,
            type: 'string'
          },
          width: 80
        }
      ]
    }
  }

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

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

  async fetchWorksheet({page, limit}) {
    if (!this._worksheetNo) return
    const response = await client.query({
      query: gql`
        query worksheetWithPagination($name: String!, $pagination: Pagination) {
          worksheetWithPagination(name: $name, pagination: $pagination) {
            worksheet {
              status
              checkCount
              inventoryCheck {
                name
                executionDate
              }
              bizplace {
                id
                name
                domain {
                  id
                  name
                }
              }
            }
            worksheetDetails {
              name
              description
              status
              targetInventoryCheckItem {
                product {
                  sku
                  name
                  brand
                  description
                }
                productDetail {
                  id
                  packingType
                  uom
                }
                inventory {
                  batchId
                  cartonId
                  palletId
                  packingType
                  uom
                  location {
                    id
                    name
                    description
                  }
                  product {
                    name
                    brand
                    description
                  }
                }
              }
            }
            total
          }
        }
      `,
      variables: {
        name: this._worksheetNo,
        pagination: {page, limit}
      }
    })

    if (!response.errors) {
      const { worksheet, worksheetDetails, total } = response.data.worksheetWithPagination
      this._worksheetStatus = worksheet.status
      this._cycleCountNo = (worksheet.inventoryCheck && worksheet.inventoryCheck.name) || ''

      const partnerDomainId = worksheet.bizplace?.domain.id
      this._enableCartonLabel = await fetchSettingRule('enable-carton-label', partnerDomainId)
      await this.updateComplete

      if (this._enableCartonLabel) {
        this.preConfig.columns = this.preConfig.columns.filter(column => column.name !== 'palletId')
      } else {
        this.preConfig.columns = this.preConfig.columns.filter(column => column.name !== 'cartonId')
      }

      this._fillupForm({
        ...worksheet,
        cycleCountNo: worksheet.inventoryCheck.name,
        executionDate: worksheet.inventoryCheck.executionDate
      })

      const records = worksheetDetails.map(worksheetDetail => {
        const record = {
          ...worksheetDetail.targetInventoryCheckItem.inventory,
          sku: worksheetDetail.targetInventoryCheckItem.product.sku,
          productDetailId: worksheetDetail.targetInventoryCheckItem.productDetail.id,
          locationId: worksheetDetail.targetInventoryCheckItem.inventory.location.id,
          brand: worksheetDetail.targetInventoryCheckItem.inventory.product.brand,
          description: worksheetDetail.description,
          status: worksheetDetail.status,
          uom: worksheetDetail.targetInventoryCheckItem.inventory.uom,
          packingType: worksheetDetail.targetInventoryCheckItem.inventory.packingType
        }

        if (!this._enableCartonLabel) {
          record.name = worksheetDetail.name
        }

        return record
      })

      if (this._enableCartonLabel) {
        const groupedRecords = {}
        let groupedTotal = 0

        records.forEach(record => {
          const groupKey = `${record.cartonId || ''}-${record.productDetailId || ''}-${record.batchId || ''}-${
            record.locationId || ''
          }`

          if (!groupedRecords[groupKey]) {
            groupedRecords[groupKey] = { ...record, count: 1 }
            groupedTotal++
          } else {
            groupedRecords[groupKey].count += 1
          }
        })

        const groupedResults = Object.values(groupedRecords)

        return { records: groupedResults, total: groupedTotal }
      } else {
        return { records, total }
      }
    }
  }

  _updateGristConfig() {
    const statusColumnConfig = {
      type: 'string',
      name: 'status',
      header: i18next.t('field.status'),
      width: 100
    }

    const updatedColumns = [...this.preConfig.columns]
    for (let column of updatedColumns) {
      if (column.name === 'description') {
        column.record = { ...column.record, editable: this._worksheetStatus === WORKSHEET_STATUS.DEACTIVATED.value }
      }
    }

    if (
      !updatedColumns.some(e => e.name === 'status') &&
      this._worksheetStatus !== WORKSHEET_STATUS.DEACTIVATED.value
    ) {
      updatedColumns.push(statusColumnConfig)
    } else {
      const indexToRemove = updatedColumns.findIndex(e => e.name === 'status')
      if (indexToRemove !== -1) {
        updatedColumns.splice(indexToRemove, 1)
      }
    }

    this.preConfig.columns = updatedColumns
    this.config = { ...this.preConfig }
  }

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

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

      if (!result.value) {
        return
      }

      CustomAlert({
        title: i18next.t('text.please_wait'),
        text: i18next.t('text.activate_cycle_count_worksheet'),
        allowOutsideClick: false,
        allowEscapeKey: false
      })

      const response = await client.query({
        query: gql`
          mutation activateCycleCount($worksheetNo: String!, $cycleCountWorksheetDetails: [WorksheetDetailPatch]) {
            activateCycleCount(worksheetNo: $worksheetNo, cycleCountWorksheetDetails: $cycleCountWorksheetDetails) {
              name
            }
          }
        `,
        variables: {
          worksheetNo: this._worksheetNo,
          cycleCountWorksheetDetails: this._getCycleCountWSD()
        }
      })

      if (!response.errors) {
        await CustomAlert({
          title: i18next.t('label.activated'),
          text: i18next.t('text.completed_x', { state: { x: i18next.t('text.activate_cycle_count_worksheet') } }),
          confirmButton: { text: i18next.t('button.confirm') }
        })
        await this.grist.fetch()
        this.updateContext()
        navigate(`cycle_count_worksheet_list`)
      } else {
        CustomAlert({
          title: i18next.t('title.error'),
          text: i18next.t('text.x_error', { state: { x: i18next.t('text.activate') } }),
          confirmButton: { text: i18next.t('button.confirm') }
        })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _getCycleCountWSD() {
    return this.grist.dirtyData.records.map(worksheetDetail => {
      return {
        name: worksheetDetail.name,
        description: worksheetDetail.description
      }
    })
  }

  // async _exportableData() {
  //   try {
  //     let records = []
  //     let data = []

  //     var headerSetting = [
  //       ...this.dataGrist._config.columns
  //         .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
  //         .map(column => {
  //           return column.imex
  //         })
  //     ]

  //     const bizplaceFilters = (await this.searchForm.getQueryFilters()).filter(x => x.name === 'bizplaceId')

  //     if (this.dataGrist.selected && this.dataGrist.selected.length > 0) {
  //       records = this.dataGrist.selected
  //       data = records
  //     } else {
  //       data = await this.fetchWorksheetDetailForExport()
  //     }

  //     let bizplace = await this.fetchBizplaces(bizplaceFilters)

  //     let product = await this.fetchProduct(bizplaceFilters)

  //     headerSetting = headerSetting.map(column => {
  //       switch (column.key) {
  //         case 'bizplace.name':
  //           column.arrData = bizplace
  //           break
  //         case 'product.name':
  //           column.arrData = product
  //           break
  //         default:
  //           break
  //       }
  //       return column
  //     })

  //     data = data.map(item => {
  //       return {
  //         id: item.id,
  //         ...this._columns
  //           .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
  //           .reduce((record, column) => {
  //             record[column.imex.key] = column.imex.key
  //               .split('.')
  //               .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
  //             return record
  //           }, {})
  //       }
  //     })

  //     return { header: headerSetting, data: data }
  //   } catch (e) {
  //     this._showToast(e)
  //   }
  // }

  // async fetchWorksheetDetailForExport() {
  //   const filters = await this.searchForm.getQueryFilters()
  //   const response = await client.query({
  //     query: gql`
  //       query {
  //         inventories(${gqlBuilder.buildArgs({
  //           filters: [...filters],
  //           pagination: { page: 1, limit: 9999999 },
  //           sortings: []
  //         })}) {
  //           items {
  //             id
  //             palletId
  //             batchId
  //             packingType
  //             uomValue
  //             bizplace {
  //               id
  //               name
  //               description
  //             }
  //             product {
  //               id
  //               name
  //             }
  //             qty
  //             warehouse {
  //               id
  //               name
  //               description
  //             }
  //             zone
  //             location {
  //               id
  //               name
  //               description
  //             }
  //             updatedAt
  //             updater {
  //               name
  //               description
  //             }
  //           }
  //           total
  //         }
  //       }
  //     `
  //   })

  //   return response.data.inventories.items || []
  // }

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

window.customElements.define('worksheet-cycle-count', WorksheetCycleCount)
