import '@things-factory/grist-ui'
import '@things-factory/biz-ui'
import '@things-factory/warehouse-ui'
import '@things-factory/import-ui'
import './draft-release-good-card'

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

import { i18next, localize } from '@things-factory/i18n-base'
import { client, CustomAlert } from '@things-factory/shell'

class DraftReleaseGoodPopup extends localize(i18next)(LitElement) {
  connectedCallback() {
    super.connectedCallback()
    this.addEventListener('value-change', this.handleInputChangeFromChild, true)
    this.addEventListener('remove-card', this.handleCloseCardPopup.bind(this), true)
    this.addEventListener('checkbox-change', this.handleInputChangeFromChild, true)
  }
  selectedOrders = []

  handleCloseCardPopup() {
    if (--this.draftOrderCount <= 0) {
      history.go(-1)
    }
  }

  handleInputChangeFromChild(event) {
    const values = event.detail

    const index = this.selectedOrders.findIndex(itm => itm.valueInfo === values.valueInfo)

    if (index !== -1) {
      // Update the existing item with the matching valueInfo
      this.selectedOrders[index] = values

      this.selectedOrders = this.selectedOrders.filter(item => item.valueCheckBox === true)
    } else if (values.valueCheckBox) {
      // If no matching valueInfo is found and valueCheckBox is true, add the new item
      this.selectedOrders.push(values)
    }
  }

  handleSelectAllChange() {
    this.selectedAll = !this.selectedAll

    // Update the selected property of each card based on selectedAll
    this.draftOrder = this.draftOrder.map(orderItem => ({
      ...orderItem,
      selected: this.selectedAll
    }))

    if (!this.selectedAll) {
      this.selectedOrders = [] // when SelectAll checkbox is unchecked, clear the selectedOrders array
    }

    // Manually request an update to trigger a re-render
    this.requestUpdate()
  }

  static get properties() {
    return {
      draftOrder: Object,
      draftOrderCount: Number,
      draftInfo: Object,
      config: Object,
      data: Object,
      selectedAll: Boolean,
      draftOrderStatus: Object
    }
  }

  constructor() {
    super()

    this.draftOrder = {}
    this.draftInfo = {}
    this.config = {}
    this.data = {}
    this.selectedAll = false
  }

  static get styles() {
    return [
      css`
        .container {
          background-color: white;
          height: 438px;
          overflow-y: scroll;
        }

        draft-release-good-card {
          margin: 10px 0;
        }

        .button-container {
          position: absolute;
          left: 50%;
          transform: translateX(-50%);
          display: flex;
          justify-content: center;
          align-items: center;
        }

        footer {
          position: sticky;
          bottom: 0;
          background-color: white;
          text-align: center;
          padding: 10px 0;
          display: flex;
          justify-content: space-between;
          align-items: center;
        }

        .button-container input[class='cancel'] {
          background-color: white;
          color: red;
          padding: 10px 20px;
          border: 2px solid red;
          border-radius: 5px;
          cursor: pointer;
          font-weight: bold;
          padding: 8px 15px;
          margin-right: 10px;
        }

        .button-container input[class='confirm'] {
          background-color: #117e7f;
          color: white;
          padding: 10px 20px;
          border: 1px solid white;
          border-radius: 5px;
          cursor: pointer;
          font-weight: bold;
          display: flex;
          justify-content: center;
          align-items: center;
        }

        .selectAll {
          margin-top: 10px;
        }

        .selectAll > label {
          color: gray;
        }

        .addNew input[class='addNew'] {
          background-color: white;
          color: #117e7f;
          border: 1px solid #117e7f;
          border-radius: 5px;
          cursor: pointer;
          font-weight: bold;
          padding: 8px 15px;
          margin-left: 15px;
        }

        [danger] {
          margin-left: -40px;
          float: left;
          margin: 0 var(--margin-narrow) 0 0;
          --mdc-theme-primary: var(--status-danger-color);
        }

        [outlined] {
          border-color: red;
        }
      `
    ]
  }

  render() {
    return html`
      <div class="container">
        <div class="selectAll">
          <input type="checkbox" .checked=${this.selectedAll} @change=${this.handleSelectAllChange} />
          <label> Select All </label>
        </div>
        ${this.draftOrder.map(orderItem => {
          const draftInfoWithLength = { ...orderItem, orderCount: orderItem.length }
          return html`
            <draft-release-good-card
              .draftInfo=${draftInfoWithLength}
              .draftOrder=${orderItem}
              .config=${this.config}
              .checkDisable=${this.checkDisable}
              .selected=${orderItem.selected || false}
              .checkReleaseType=${this.draftOrderStatus}
              @checkbox-change=${this.handleInputChangeFromChild}
            ></draft-release-good-card>
          `
        })}
      </div>
      <footer>
        <div class="addNew">
          <input type="button" class="addNew" value="+ ADD NEW" @click=${this.addNew} />
        </div>
        <div class="button-container">
          <input type="button" class="cancel" value="Cancel" @click=${this.closePopup} />
          <input type="button" class="confirm" value="Confirm" @click=${this._generateReleaseGood} />
        </div>
      </footer>
    `
  }

  async closePopup() {
    history.back()
  }

  async addNew() {
    this._showToast({ message: i18next.t('text.please_select_additional_checkboxes_to_add_new_draft_orders') })
    this.closePopup()
  }

  async firstUpdated() {
    this.draftOrderCount = this.draftOrder.length
    this.config = {
      list: { fields: ['name', 'status'] },
      pagination: { infinite: true },
      rows: { appendable: false },
      columns: [
        {
          type: 'string',
          name: 'bizplace',
          header: i18next.t('field.company'),
          imex: { header: i18next.t('field.company'), key: 'bizplace.name', width: 30, type: 'string' },
          sortable: false,
          width: 250
        },
        {
          type: 'string',
          name: 'sku',
          header: i18next.t('field.sku'),
          width: 250
        },
        {
          type: 'string',
          name: 'groupType',
          header: i18next.t('field.group_type'),
          width: 250
        },
        {
          type: 'number',
          name: 'availableQty',
          header: i18next.t('field.available_qty'),
          width: 130
        },
        {
          type: 'number',
          name: 'releaseQty',
          header: i18next.t('field.release_qty'),
          width: 130
        },
        {
          type: 'string',
          name: 'status',
          header: i18next.t('field.status'),
          imex: { header: i18next.t('field.status'), key: 'status', width: 30, type: 'string' },
          sortable: false,
          width: 150
        }
      ]
    }
  }

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

  async _generateReleaseGood() {
    try {
      let releaseResponse
      let selectedGristData = this.selectedOrders

      if (selectedGristData.length < 1) {
        this._showToast({ message: i18next.t('text.please_select_a_draft_order_to_proceed') })
        return
      }

      if (selectedGristData.some(item => item.valueRadio === '')) {
        this._showToast({ message: i18next.t('text.unable_to_create_partial_release_order_for_sku_as_miminum_required_quantity_to_release_is_1') })
        return
      }

      // Sort by createdAt ASC to ensure orders that came in first get converted first
      selectedGristData.sort((a, b) => {
        const orderA = this.draftOrder.find(order => order.id === a.valueInfo)
        const orderB = this.draftOrder.find(order => order.id === b.valueInfo)
        return new Date(orderA?.createdAt) - new Date(orderB?.createdAt)
      })

      const filterSelectedData = selectedGristData.map(item => {
        return {
          id: item.valueInfo ? item.valueInfo : '',
          releaseType: item.valueRadio ? item.valueRadio : null
        }
      })

      const checkReleaseType = filterSelectedData.every(item => item.releaseType === null)

      if (checkReleaseType) {
        throw new Error(i18next.t('text.please_select_a_valid_draft_order_to_generate_release_order'))
      }

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

      if (!result.value) return

      if (filterSelectedData.length > 0) {
        releaseResponse = await client.mutate({
          mutation: gql`
            mutation generateReleaseGoodsfromDraft($releaseInfo: [DraftReleaseGoodInfos!]!) {
              generateReleaseGoodsfromDraft(releaseInfo: $releaseInfo) {
                draftName
                isProductBundle
              }
            }
          `,
          variables: {
            releaseInfo: filterSelectedData
          }
        })
      } else {
        releaseResponse = null
      }

      let releasedDraftOrders
      const releaseDraft = releaseResponse?.data?.generateReleaseGoodsfromDraft || []

      let filterSuccessOrders = releaseDraft?.filter(itm => !itm.isProductBundle)
      let filterPbOrders = releaseDraft?.filter(itm => itm.isProductBundle)

      if (releaseDraft.length > 0) {
        const draftNames = filterSuccessOrders.map(order => order.draftName)
        releasedDraftOrders = draftNames.join(', ')
      }

      if (releasedDraftOrders) {
        throw new Error(`Due to insufficient available quantity, only ${releasedDraftOrders} is able to release`)
      }

      if (filterPbOrders.length > 0) {
        throw new Error('Partial release is not permitted for bundle SKU. Only single SKUs have been released.')
      }

      if (!releaseResponse?.errors) {
        this._showToast({ message: i18next.t('text.release_order(s)_has_been_generated') })
        this.dispatchEvent(new CustomEvent('reload-page', { detail: null, bubbles: true, composed: true }))
        history.back()
      }
    } catch (e) {
      this.dispatchEvent(new CustomEvent('reload-page', { detail: null, bubbles: true, composed: true }))
      this._showToast(e)
      history.back()
    }
  }

  _showToast({ type, message, delay = 1000 }) {
    setTimeout(() => {
      document.dispatchEvent(
        new CustomEvent('notify', {
          detail: {
            type,
            message
          }
        })
      )
    }, delay)
  }
}
window.customElements.define('draft-release-good-popup', DraftReleaseGoodPopup)
