import '@things-factory/biz-ui'
import '@things-factory/warehouse-ui'
import './validate-gan-popup'
import './validate-ro-popup'
import './validate-b2c-ro-popup'

import gql from 'graphql-tag'
import { css, html } from 'lit-element'
import XLSX from 'xlsx'

import { MultiColumnFormStyles } from '@things-factory/form-ui'
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 { sleep } from '@things-factory/utils'

import { fetchSettingRule } from '../../fetch-setting-value'

class BulkOperation extends localize(i18next)(PageView) {
  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        :host {
          display: block;
          --menu-cards-size: 300px;
        }
        ul {
          margin: var(--margin-wide) 0;
          padding: 0;
          overflow: hidden;
          list-style: none;
        }
        li {
          display: block;
          float: left;
          background-color: var(--main-section-background-color);
          border-radius: var(--border-radius);
          border: 1px solid var(--main-section-background-color);
          box-shadow: var(--box-shadow);
          margin: var(--margin-narrow) var(--margin-default) var(--margin-default) 0;
          padding: var(--padding-default) var(--padding-default) var(--padding-narrow) var(--padding-default);
          text-align: center;
        }
        li:hover {
          border: 1px solid var(--primary-color);
        }
        a {
          cursor: pointer;
          text-decoration: none;
          color: var(--secondary-color);
        }
        mwc-icon {
          font-size: 18px;
          color: var(--primary-color);
          border: 1px solid rgba(0, 0, 0, 0.2);
          border-radius: var(--border-radius);
          background-color: var(--theme-white-color);
        }
        a,
        span {
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
        [subtitle] {
          padding: var(--subtitle-padding);
          font: var(--subtitle-font);
          color: var(--subtitle-text-color);
          text-transform: capitalize;
          display: flex;
          justify-content: center;
          align-items: center;
        }
        form {
          display: block;
          width: var(--menu-cards-size);
        }
        .multi-column-form input {
          min-width: 85% !important;
        }
        [attachment-wrap] {
          display: flex;
          flex-direction: row;
          justify-content: center;
          grid-column: span 24;
        }
        [attachment-wrap] file-uploader {
          flex: 1;
          background-color: var(--theme-white-color);
        }
        .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);
        }
        @media screen and (max-width: 600px) {
          ul {
            display: grid;
            grid-template-columns: 50% 50%;
            grid-gap: var(--padding-narrow);
          }
          [field] {
            grid-column: span 2;
          }
        }
        @media screen and (max-width: 460px) {
          [attachment-wrap] {
            grid-column: span 12;
          }
        }
        @media screen and (min-width: 1201px) and (max-width: 2000px) {
          [attachment-wrap] {
            grid-column: span 36;
          }
        }
        @media screen and (min-width: 2001px) {
          [attachment-wrap] {
            grid-column: span 48;
          }
        }
      `
    ]
  }

  static get properties() {
    return {
      _ganBizplaceId: String,
      _ganBizplaceName: String,
      _ganPartnerDomainId: String,
      _ganDocument: Object,
      _roDocument: Object,
      _rawData: Array,
      _roBizplaceId: String,
      _roBizplaceName: String,
      _roB2cBizplaceId: String,
      _roB2cBizplaceName: String,
      ganProcessingSetting: String,
      _bufferLocationId: Object,
      _arrivalNotices: Array
    }
  }

  firstUpdated() {}

  get context() {
    return {
      title: i18next.t('title.bulk_operation'),
      help: 'operato-wms/bulk-operation/bulk-operation'
    }
  }

  get _ganDocument() {
    return this.shadowRoot.querySelector('#upload-gan-document')
  }

  get _roDocument() {
    return this.shadowRoot.querySelector('#upload-ro-document')
  }

  get _b2cRoDocument() {
    return this.shadowRoot.querySelector('#upload-b2c-ro-document')
  }

  get _ganData() {
    let date =
      new Date().getDate().toString().padStart(2, '0') +
      '/' +
      (new Date().getMonth() + 1).toString().padStart(2, '0') +
      '/' +
      new Date().getFullYear()
    return [
      {
        refNo: '',
        refNo2: '',
        refNo3: '',
        etaDate: date,
        truckNo: '',
        containerNo: '',
        containerSize: '',
        looseItem: false,
        importCargo: false,
        sku: '',
        batchId: '',
        batchIdRef: '',
        lotId: '',
        packingType: '',
        packingSize: 0,
        uom: '',
        packQty: 0,
        palletQty: 0,
        manufactureDate: '',
        unitPrice: ''
      }
    ]
  }

  get _roData() {
    return [
      {
        refNo: '',
        refNo2: '',
        refNo3: '',
        releaseDate:
          new Date().getDate().toString().padStart(2, '0') +
          '/' +
          (new Date().getMonth() + 1).toString().padStart(2, '0') +
          '/' +
          new Date().getFullYear(),
        attentionTo: '',
        attentionCompany: '',
        deliveryAddress1: '',
        deliveryAddress2: '',
        deliveryAddress3: '',
        deliveryAddress4: '',
        deliveryAddress5: '',
        postalCode: '',
        city: '',
        state: '',
        country: '',
        phone1: '',
        batchId: '',
        sku: '',
        packingType: '',
        packingSize: 0,
        uom: '',
        releaseQty: 0,
        billingAddress: '',
        billingAddress2: '',
        billingAddress3: '',
        billingAddress4: '',
        billingAddress5: '',
        billingPostalCode: '',
        billingCountry: '',
        billingState: '',
        billingCity: '',
        expirationDate:
          new Date().getDate().toString().padStart(2, '0') +
          '/' +
          (new Date().getMonth() + 1).toString().padStart(2, '0') +
          '/' +
          new Date().getFullYear()
      }
    ]
  }

  get _b2cRoData() {
    return [
      {
        refNo: '',
        refNo2: '',
        refNo3: '',
        releaseDate:
          new Date().getDate().toString().padStart(2, '0') +
          '/' +
          (new Date().getMonth() + 1).toString().padStart(2, '0') +
          '/' +
          new Date().getFullYear(),
        lmdOption: false,
        codOption: false,
        paidAmount: 0,
        invoice: '',
        airwayBill: '',
        attentionTo: '',
        deliveryAddress1: '',
        deliveryAddress2: '',
        deliveryAddress3: '',
        deliveryAddress4: '',
        deliveryAddress5: '',
        postalCode: '',
        city: '',
        state: '',
        country: '',
        phone1: '',
        billingAddress: '',
        billingAddress2: '',
        billingAddress3: '',
        billingAddress4: '',
        billingAddress5: '',
        billingPostalCode: '',
        billingCity: '',
        billingState: '',
        billingCountry: '',
        batchId: '',
        cartonId: '',
        sku: '',
        packingType: '',
        packingSize: 0,
        uom: '',
        releaseQty: 0,
        expirationDate:
          new Date().getDate().toString().padStart(2, '0') +
          '/' +
          (new Date().getMonth() + 1).toString().padStart(2, '0') +
          '/' +
          new Date().getFullYear()
      }
    ]
  }

  render() {
    return html`
      <ul export-form>
        <li>
          <div subtitle>
            Arrival Notice &nbsp;
            <a @click=${async () => await this._downloadOrderTemplate(this._ganData, 'Bulk Arrival Notices')} download>
              <mwc-icon>file_download</mwc-icon>
            </a>
          </div>
          <form name="input-form" class="multi-column-form" autocomplete="off">
            <fieldset>
              <div attachment-wrap>
                <input type="hidden" name="bizplaceId" value="${this._ganBizplaceId}" />
                <input
                  type="text"
                  name="ganBizplaceName"
                  placeholder="${i18next.t('label.company')}"
                  value="${this._ganBizplaceName}"
                  @click="${() => {
                    this._openBizplacesSelector('GAN')
                  }}"
                />
              </div>
              <div attachment-wrap>
                <file-uploader
                  name="attachments"
                  id="upload-gan-document"
                  label="${i18next.t('label.select_file')}"
                  accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                  custom-input
                ></file-uploader>
              </div>
            </fieldset>
          </form>
          <div class="button-container">
            <mwc-button raised @click=${async () => await this._extractRawDataFromExcel(this._ganDocument, 'GAN')}
              >${i18next.t('button.validate')}</mwc-button
            >
          </div>
        </li>
        <li>
          <div subtitle>
            B2B Release Order &nbsp;
            <a @click=${async () => await this._downloadOrderTemplate(this._roData, 'Bulk Release Orders')} download>
              <mwc-icon>file_download</mwc-icon>
            </a>
          </div>
          <form name="input-form" class="multi-column-form" autocomplete="off">
            <fieldset>
              <div attachment-wrap>
                <input type="hidden" name="bizplaceId" value="${this._roBizplaceId}" />
                <input
                  type="text"
                  name="roBizplaceName"
                  placeholder="${i18next.t('label.company')}"
                  value="${this._roBizplaceName}"
                  @click="${() => {
                    this._openBizplacesSelector('RO')
                  }}"
                />
              </div>
              <div attachment-wrap>
                <file-uploader
                  name="attachments"
                  id="upload-ro-document"
                  label="${i18next.t('label.select_file')}"
                  accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                  custom-input
                ></file-uploader>
              </div>
            </fieldset>
          </form>
          <div class="button-container">
            <mwc-button raised @click=${async () => await this._extractRawDataFromExcel(this._roDocument, 'RO')}
              >${i18next.t('button.validate')}</mwc-button
            >
          </div>
        </li>

        <!-- ubah dkt sini -->
        <li>
          <div subtitle>
            B2C Release Order &nbsp;
            <a
              @click=${async () => await this._downloadOrderTemplate(this._b2cRoData, 'Bulk B2C Release Orders')}
              download
            >
              <mwc-icon>file_download</mwc-icon>
            </a>
          </div>
          <form name="input-form" class="multi-column-form" autocomplete="off">
            <fieldset>
              <div attachment-wrap>
                <input type="hidden" name="bizplaceId" value="${this._roB2cBizplaceId}" />
                <input
                  type="text"
                  name="roBizplaceName"
                  placeholder="${i18next.t('label.company')}"
                  value="${this._roB2cBizplaceName}"
                  @click="${() => {
                    this._openBizplacesSelector('B2C_RO')
                  }}"
                />
              </div>
              <div attachment-wrap>
                <file-uploader
                  name="attachments"
                  id="upload-b2c-ro-document"
                  label="${i18next.t('label.select_file')}"
                  accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                  custom-input
                ></file-uploader>
              </div>
            </fieldset>
          </form>
          <div class="button-container">
            <mwc-button raised @click=${async () => await this._extractRawDataFromExcel(this._b2cRoDocument, 'B2C_RO')}
              >${i18next.t('button.validate')}</mwc-button
            >
          </div>
        </li>
      </ul>
    `
  }

  async _downloadOrderTemplate(data, fileName) {
    const ws = XLSX.utils.json_to_sheet(data)
    const wb = XLSX.utils.book_new()
    XLSX.utils.book_append_sheet(wb, ws)
    XLSX.writeFile(wb, `${fileName}.xlsx`)
  }

  async _extractRawDataFromExcel(_docs, sourceFn) {
    if (
      (sourceFn == 'GAN' && !this._ganBizplaceId) ||
      (sourceFn == 'RO' && !this._roBizplaceId) ||
      (sourceFn == 'B2C_RO' && !this._roB2cBizplaceId)
    ) {
      this._showToast({ level: 'error', message: `${i18next.t('text.please_select_the_company')}` })
      return
    }

    if (_docs && _docs.files) {
      if (_docs.files.length == 1) {
        const file = _docs.files[0]
        const fileReader = new FileReader()

        fileReader.readAsArrayBuffer(file)

        fileReader.onload = e => {
          /* extract rawData from .xlsx file */
          const bufferArray = e.target.result
          const workbook = XLSX.read(bufferArray, { type: 'buffer' })
          const firstWorksheetName = workbook.SheetNames[0]
          const worksheet = workbook.Sheets[firstWorksheetName]

          let rawData = XLSX.utils.sheet_to_json(worksheet)

          rawData = rawData.map(raw => {
            //return entries without empty strings
            return Object.fromEntries(Object.entries(raw).filter(([_, val]) => !/^\s*$/.test(val)))
          })

          if (sourceFn == 'GAN') this._validateArrivalNotice(rawData)
          else if (sourceFn == 'RO') this._validateReleaseOrder(rawData)
          else if (sourceFn == 'B2C_RO') this._validateB2cReleaseOrder(rawData)
        }
      } else if (_docs.files.length > 1)
        this._showToast({ level: 'error', message: i18next.t('text.you_can_only_upload_one_file_max') })
      else this._showToast({ level: 'error', message: i18next.t('text.please_attach_the_file') })
    } else this._showToast({ level: 'error', message: i18next.t('text.please_attach_the_file') })
  }

  async _assignBufferLocation() {
    try {
      this._validateBufferLocation()

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

      if (!result.value) return

      const response = await client.mutate({
        mutation: gql`
          mutation generateArrivalNoticeWorksheet($arrivalNoticeNos: [String!], $bufferLocation: ObjectRef!) {
            generateArrivalNoticeWorksheet(arrivalNoticeNos: $arrivalNoticeNos, bufferLocation: $bufferLocation) {
              unloadingWorksheet {
                name
              }
            }
          }
        `,
        variables: {
          arrivalNoticeNos: this._arrivalNotices,
          bufferLocation: { id: this._bufferLocationId }
        }
      })

      if (!response.errors) {
        navigate(`inbound_worksheets`)
        this._showToast({ message: i18next.t('text.warehouse_is_assigned') })
      }
    } catch (e) {
      this._showToast(e)
    }
  }

  _validateBufferLocation() {
    if (!this._bufferLocationId) throw new Error(i18next.t('text.warehouse_is_not_assigned'))
  }

  _validateArrivalNotice(records) {
    /* validate excel that user uploaded */
    openPopup(
      html`
        <validate-gan-popup
          .records=${records.map(raw => {
            return {
              refNo: String(raw.refNo || ''),
              refNo2: String(raw.refNo2 || ''),
              refNo3: String(raw.refNo3 || ''),
              truckNo: String(raw.truckNo || ''),
              ownTransport: !!raw.truckNo,
              looseItem: !!raw.looseItem,
              importCargo: !!raw.importCargo,
              containerNo: String(raw.containerNo || ''),
              containerSize: String(raw.containerSize || ''),
              sku: String(raw.sku || ''),
              batchId: String(raw.batchId || ''),
              batchIdRef: String(raw.batchIdRef || ''),
              packingType: raw.packingType && raw.packingType != '' ? String(raw.packingType) : null,
              packingSize: !isNaN(Number(raw.packingSize || 'x')) ? Number(raw.packingSize) : null,
              uom: raw.uom && raw.uom != '' ? String(raw.uom) : null,
              packQty: parseFloat(raw.packQty || 0),
              palletQty: parseInt(raw.palletQty || 0),
              palletId: String(raw.lotId || ''),
              unitPrice: raw.unitPrice,
              manufactureDate: Number.isInteger(raw.manufactureDate)
                ? raw.manufactureDate.toString()
                : raw.manufactureDate,
              etaDate: Number.isInteger(raw.etaDate) ? raw.etaDate.toString() : raw.etaDate
            }
          })}
          .ganProcessing=${this.ganProcessingSetting}
          .bizplaceId=${this._ganBizplaceId}
          @gan-processing-setting="${async e => {
            this._arrivalNotices = e.detail
            await sleep(10)
            this._openBufferSelector()
          }}"
        ></validate-gan-popup>
      `,
      {
        backdrop: true,
        escapable: false,
        size: 'large',
        title: i18next.t('title.bulk_arrival_notices')
      }
    )
  }

  _validateReleaseOrder(records) {
    /* validate excel that user uploaded */
    openPopup(
      html`
        <validate-ro-popup
          .records=${records.map(record => {
            return {
              refNo: String(record.refNo || ''),
              refNo2: String(record.refNo2 || ''),
              refNo3: String(record.refNo3 || ''),
              releaseDate: Number.isInteger(record.releaseDate) ? record.releaseDate.toString() : record.releaseDate,
              deliveryAddress1: String(record.deliveryAddress1 || ''),
              deliveryAddress2: String(record.deliveryAddress2 || ''),
              deliveryAddress3: String(record.deliveryAddress3 || ''),
              deliveryAddress4: String(record.deliveryAddress4 || ''),
              deliveryAddress5: String(record.deliveryAddress5 || ''),
              attentionTo: String(record.attentionTo || ''),
              attentionCompany: String(record.attentionCompany || ''),
              city: String(record.city || ''),
              state: String(record.state || ''),
              country: String(record.country || ''),
              batchId: String(record.batchId || ''),
              cartonId: String(record.cartonId || ''),
              sku: String(record.sku || ''),
              productId: String(record.productId || ''),
              productDetailId: String(record.productDetailId || ''),
              packingType: record.packingType && record.packingType != '' ? String(record.packingType) : null,
              packingSize: !isNaN(Number(record.packingSize || 'x')) ? Number(record.packingSize) : null,
              uom: record.uom && record.uom != '' ? String(record.uom) : null,
              releaseQty: parseFloat(record.releaseQty),
              postalCode: String(record.postalCode || ''),
              phone1: String(record.phone1 || ''),
              exportOption: false,
              billingAddress: String(record.billingAddress || ''),
              billingAddress2: String(record.billingAddress2 || ''),
              billingAddress3: String(record.billingAddress3 || ''),
              billingAddress4: String(record.billingAddress4 || ''),
              billingAddress5: String(record.billingAddress5 || ''),
              billingPostalCode: String(record.billingPostalCode || ''),
              billingCountry: String(record.billingCountry || ''),
              billingState: String(record.billingState || ''),
              billingCity: String(record.billingCity || ''),
              expirationDate: Number.isInteger(record.expirationDate)
                ? record.expirationDate.toString()
                : record.expirationDate
            }
          })}
          .bizplaceId=${this._roBizplaceId}
        ></validate-ro-popup>
      `,
      {
        backdrop: true,
        escapable: false,
        size: 'large',
        title: i18next.t('title.bulk_release_orders')
      }
    )
  }

  _validateB2cReleaseOrder(records) {
    /* validate excel that user uploaded */
    openPopup(
      html`
        <validate-b2c-ro-popup
          .records=${records.map(record => {
            let newPaidAmount = parseFloat(record?.paidAmount?.toFixed(2))
            return {
              refNo: String(record.refNo || ''),
              refNo2: String(record.refNo2 || ''),
              refNo3: String(record.refNo3 || ''),
              releaseDate: Number.isInteger(record.releaseDate) ? record.releaseDate.toString() : record.releaseDate,
              lmdOption: record.lmdOption || false,
              codOption: record.codOption || false,
              paidAmount: newPaidAmount,
              invoice: String(record.invoice || ''),
              airwayBill: String(record.airwayBill || ''),
              attentionTo: String(record.attentionTo || ''),
              deliveryAddress1: String(record.deliveryAddress1 || ''),
              deliveryAddress2: String(record.deliveryAddress2 || ''),
              deliveryAddress3: String(record.deliveryAddress3 || ''),
              deliveryAddress4: String(record.deliveryAddress4 || ''),
              deliveryAddress5: String(record.deliveryAddress5 || ''),
              postalCode: String(record.postalCode || ''),
              city: String(record.city || ''),
              state: String(record.state || ''),
              country: String(record.country || ''),
              phone1: String(record.phone1 || ''),
              billingAddress: String(record.billingAddress || ''),
              billingAddress2: String(record.billingAddress2 || ''),
              billingAddress3: String(record.billingAddress3 || ''),
              billingAddress4: String(record.billingAddress4 || ''),
              billingAddress5: String(record.billingAddress5 || ''),
              billingPostalCode: String(record.billingPostalCode || ''),
              billingCountry: String(record.billingCountry || ''),
              billingState: String(record.billingState || ''),
              billingCity: String(record.billingCity || ''),
              batchId: String(record.batchId || ''),
              cartonId: String(record.cartonId || ''),
              sku: String(record.sku || ''),
              packingType: record.packingType && record.packingType != '' ? String(record.packingType) : null,
              packingSize: !isNaN(Number(record.packingSize || 'x')) ? Number(record.packingSize) : null,
              uom: record.uom && record.uom != '' ? String(record.uom) : null,
              releaseQty: parseFloat(record.releaseQty),
              type: 'b2c',
              exportOption: false,
              packingOption: true,
              courierOption: true,
              expirationDate: Number.isInteger(record.expirationDate)
                ? record.expirationDate.toString()
                : record.expirationDate
            }
          })}
          .bizplaceId=${this._roB2cBizplaceId}
        ></validate-b2c-ro-popup>
      `,
      {
        backdrop: true,
        escapable: false,
        size: 'large',
        title: i18next.t('title.bulk_b2c_release_orders')
      }
    )
  }

  _openBizplacesSelector(source) {
    openPopup(
      html`
        <popup-partner-bizplaces-selector
          @selected="${async e => {
            let { id, name, domain } = e.detail
            if (source == 'GAN') {
              this._ganBizplaceId = id
              this._ganBizplaceName = name
              this._ganPartnerDomainId = domain.id
            } else if (source == 'RO') {
              this._roBizplaceId = id
              this._roBizplaceName = name
            } else if (source == 'B2C_RO') {
              this._roB2cBizplaceId = id
              this._roB2cBizplaceName = name
            }
            this.ganProcessingSetting =
              (await fetchSettingRule('gan-order-processing', this._ganPartnerDomainId)) || '-1'
          }}"
        ></popup-partner-bizplaces-selector>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_company')
      }
    )
  }

  _openBufferSelector() {
    openPopup(
      html`
        <buffer-location-selector
          @selected="${async e => {
            this._bufferLocationId = `${e.detail.id}`
            await this._assignBufferLocation()
          }}"
        ></buffer-location-selector>
      `,
      {
        backdrop: true,
        size: 'large',
        title: i18next.t('title.select_warehouse')
      }
    )
  }

  _getStdDateStr(date) {
    if (isNaN(date.getFullYear())) return ''
    else {
      date.setHours(date.getHours() + 8)
      return date.toISOString().split('T')[0]
    }
  }

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

window.customElements.define('bulk-operation', BulkOperation)
