import '@things-factory/grist-ui'

import gql from 'graphql-tag'
import { css, html, LitElement } from 'lit-element'
import { connect } from 'pwa-helpers/connect-mixin'

import { MultiColumnFormStyles } from '@things-factory/form-ui'
import { i18next, localize } from '@things-factory/i18n-base'
import { client, store, CustomAlert } from '@things-factory/shell'
import { isMobileDevice } from '@things-factory/utils'
import { CONDITION_OF_GOODS } from '../constants'
import '../components/mobile-condition-of-goods-listing'
import { showToast } from '../../util'
class ConditionOfGoodsPopup extends connect(store)(localize(i18next)(LitElement)) {
  static get properties() {
    return {
      config: Object,
      mobileConfig: Object,
      unloadedInventories: Array,
      worksheetDetailNames: Array,
      _productInfoFilter: String,
      _conditionFilter: String,
      _isExecuting: Boolean
    }
  }

  constructor() {
    super()
    this._isExecuting = false
    this._productInfoFilter = ''
    this._conditionFilter = ''
    this.unloadedInventories = []
    this.worksheetDetailNames = []
    this.config = null
    this._closeTimeoutId = null
  }

  disconnectedCallback() {
    if (this._closeTimeoutId) {
      clearTimeout(this._closeTimeoutId)
      this._closeTimeoutId = null
    }
    super.disconnectedCallback()
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      css`
        .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);
          display: flex;
          gap: 10px;
          justify-content: flex-end;
        }
        
        @media (max-width: 767px) {
          mobile-condition-of-goods-listing {
            padding-bottom: 40px;
          }
          
          .button-container {
            background-color: var(--theme-white-color, white);
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            z-index: 1000;
            margin: 0;
            padding: 0;
            justify-content: flex-end;
            align-items: flex-end;
            height: 40px !important;
            gap: 0;
          }
          
          .button-container mwc-button {
            margin-bottom: 0 !important;
          }
        }
        
        .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);
          min-width: 100px;
        }
        .button-container button:hover,
        .button-container button:active {
          background-color: var(--button-background-focus-color);
        }
        .button-container button.secondary {
          background-color: var(--button-secondary-background-color, #757575);
        }
        .button-container button.secondary:hover,
        .button-container button.secondary:active {
          background-color: var(--button-secondary-background-focus-color, #616161);
        }
        data-grist {
          overflow-y: hidden;
          flex: 1;
          --grid-record-odd-background-color: var(--theme-white-color);
          --data-list-background-color: var(--theme-white-color);
        }
        .grist {
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow-y: auto;
        }
        data-listing {
          flex: 1;
          overflow: hidden;
        }
        :host {
          padding: 10px;
          display: flex;
          flex-direction: column;
          overflow: hidden;
          background-color: white;
          --data-list-label-text-transform: capitalize;
        }
        .filter-section {
          background-color: var(--form-section-background-color, #f5f5f5);
          padding: 15px;
          margin-bottom: 10px;
          border-radius: 4px;
        }
        .filter-section fieldset {
          margin-bottom: 10px;
        }
        .filter-section fieldset:last-child {
          margin-bottom: 0;
        }
        select {
          width: 100%;
          padding: 8px;
          border: 1px solid #ccc;
          border-radius: 4px;
          font-size: 14px;
          box-sizing: border-box;
        }
        input[type='text'] {
          width: 100%;
          padding: 8px;
          border: 1px solid #ccc;
          border-radius: 4px;
          font-size: 14px;
          box-sizing: border-box;
        }
        @media screen and (max-width: 460px) {
          .single-column-form {
            max-width: 100%;
            grid-gap: 5px;
            border-bottom: 1px solid #017E7F;
          }
          .single-column-form fieldset {
            display: contents;
            border: none;
            margin: 0;
            padding: 0;
          }
          .single-column-form label {
            font-weight: bold !important;
            text-transform: capitalize !important;
          }
          .single-column-form input[type='text'],
          .single-column-form select {
            width: 100%;
            box-sizing: border-box;
            max-width: 100%;
            margin-bottom: 10px;
          }
        }
      `
    ]
  }

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

  get dataListing() {
    return this.shadowRoot.querySelector('mobile-condition-of-goods-listing')
  }

  get currentDataComponent() {
    return isMobileDevice() ? this.dataListing : this.dataGrist
  }

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

  get conditionFilterSelect() {
    return this.shadowRoot.querySelector('select[name=conditionFilter]')
  }

  firstUpdated() {
    this._setupGristConfig()
    this.updateComplete.then(() => {
      const component = this.currentDataComponent
      if (component && this.worksheetDetailNames && this.worksheetDetailNames.length > 0) {
        if (isMobileDevice() && this.dataListing) {
          this.dataListing.fetch()
        } else if (!isMobileDevice() && this.dataGrist) {
          this.dataGrist.fetch()
        }
      }
    })
  }

  updated(changedProperties) {
    if (changedProperties.has('worksheetDetailNames')) {
      const component = this.currentDataComponent
      if (component && this.worksheetDetailNames && this.worksheetDetailNames.length > 0) {
        if (isMobileDevice() && this.dataListing) {
          this.dataListing.fetch()
        } else if (!isMobileDevice() && this.dataGrist) {
          this.dataGrist.fetch()
        }
      }
    }
  }

  _onFieldChange(e) {
    // Handle field changes from data-listing component
    // This is called when selection box values change
    // The data is already updated in the component, we just need to track changes
  }

  _setupGristConfig() {
    this.config = {
      pagination: { limit: 50, pages: [20, 50, 100, 200, 500] },
      rows: { selectable: { multiple: false }, appendable: false },
      list: {
        fields: ['palletId', 'cartonId', 'sku', 'productName', 'qty', 'conditionOfGoods']
      },
      columns: [
        { type: 'gutter', gutterName: 'sequence' },
        {
          type: 'string',
          name: 'palletId',
          label: true,
          header: i18next.t('field.lot_id'),
          width: 150
        },
        {
          type: 'string',
          name: 'cartonId',
          label: true,
          header: i18next.t('field.carton_id'),
          width: 150
        },
        {
          type: 'string',
          name: 'sku',
          label: true,
          header: i18next.t('field.sku'),
          width: 120
        },
        {
          type: 'string',
          name: 'productName',
          label: true,
          header: i18next.t('field.product_name'),
          width: 250
        },
        {
          type: 'float',
          name: 'qty',
          label: true,
          header: i18next.t('field.actual_pack_qty'),
          width: 120
        },
        {
          type: 'select',
          name: 'conditionOfGoods',
          label: true,
          header: i18next.t('field.condition'),
          width: 150,
          record: {
            editable: true,
            options: Object.keys(CONDITION_OF_GOODS).map(key => ({
              value: CONDITION_OF_GOODS[key].value,
              display: i18next.t(`label.${CONDITION_OF_GOODS[key].name}`)
            }))
          }
        }
      ]
    }

    this.mobileConfig = {
      columns: [
        {
          type: 'text',
          header: i18next.t('field.lot_id'),
          field: 'palletId',
          color: '#007E7F'
        },
        {
          type: 'text',
          header: i18next.t('field.carton_id'),
          field: 'cartonId',
          color: '#007E7F'
        },
        {
          type: 'text',
          header: i18next.t('field.sku'),
          field: 'sku',
          color: '#007E7F'
        },
        {
          type: 'text',
          header: i18next.t('field.product_name'),
          field: 'productName'
        },
        {
          type: 'text',
          header: i18next.t('field.actual_pack_qty'),
          field: 'qty'
        },
        {
          type: 'selectionBox',
          header: i18next.t('field.condition'),
          field: 'conditionOfGoods',
          options: Object.keys(CONDITION_OF_GOODS).map(key => ({
            value: CONDITION_OF_GOODS[key].value,
            label: i18next.t(`label.${CONDITION_OF_GOODS[key].name}`)
          }))
        }
      ]
    }
  }

  async fetchHandler({ page, limit }) {
    try {
      const worksheetDetailNames = this._getWorksheetDetailNames()
      
      if (!worksheetDetailNames || worksheetDetailNames.length === 0) {
        return {
          total: 0,
          records: []
        }
      }

      const response = await client.query({
        query: gql`
          query unloadedInventories($worksheetDetailNames: [String]!) {
            unloadedInventories(worksheetDetailNames: $worksheetDetailNames) {
              id
              batchId
              packingType
              packingSize
              batchIdRef
              palletId
              cartonId
              qty
              expirationDate
              manufactureDate
              status
              product {
                id
                name
                sku
              }
              conditionOfGoods
            }
          }
        `,
        variables: { 
          worksheetDetailNames
        },
      })

      if (response.errors) {
        throw new Error(response.errors[0]?.message || i18next.t('text.error_occurred'))
      }

      const allInventories = response.data?.unloadedInventories || []

      // Apply filters
      let filtered = this._applyFilters(allInventories)

      // Transform to records format
      const allRecords = filtered.map(inventory => ({
        id: inventory.id,
        palletId: inventory.palletId || '',
        cartonId: inventory.cartonId || '',
        sku: inventory.product?.sku || '',
        productName: inventory.product?.name || '',
        qty: inventory.qty || 0,
        conditionOfGoods: inventory.conditionOfGoods || CONDITION_OF_GOODS.GOOD.value
      }))

      // Apply pagination
      const startIndex = (page - 1) * limit
      const endIndex = startIndex + limit
      const records = allRecords.slice(startIndex, endIndex)

      return {
        total: allRecords.length,
        records
      }
    } catch (e) {
      showToast({ message: e.message || i18next.t('text.error_occurred'), type: 'error' })
      return {
        total: 0,
        records: []
      }
    }
  }

  _getWorksheetDetailNames() {
    return this.worksheetDetailNames || []
  }

  _onProductInfoFilterChange(e) {
    this._productInfoFilter = e.target.value
  }

  _onProductInfoFilterKeyPress(e) {
    if (e.keyCode === 13) {
      e.preventDefault()
      if (isMobileDevice() && this.dataListing) {
        this.dataListing.fetch()
      } else if (!isMobileDevice() && this.dataGrist) {
        this.dataGrist.fetch()
      }
    }
  }

  _onConditionFilterChange(e) {
    this._conditionFilter = e.target.value
    if (isMobileDevice() && this.dataListing) {
      this.dataListing.fetch()
    } else if (!isMobileDevice() && this.dataGrist) {
      this.dataGrist.fetch()
    }
  }

  _applyFilters(inventories) {
    let filtered = inventories || []

    // Apply product info filter (search by SKU or product name)
    if (this._productInfoFilter && this._productInfoFilter.trim() !== '') {
      const searchTerm = this._productInfoFilter.toLowerCase().trim()
      filtered = filtered.filter(
        inventory =>
          (inventory.product?.sku && inventory.product.sku.toLowerCase().includes(searchTerm)) ||
          (inventory.product?.name && inventory.product.name.toLowerCase().includes(searchTerm))
      )
    }

    // Apply condition filter
    if (this._conditionFilter && this._conditionFilter !== '') {
      filtered = filtered.filter(inventory => {
        const condition = inventory.conditionOfGoods || CONDITION_OF_GOODS.GOOD.value
        return condition === this._conditionFilter
      })
    }

    return filtered
  }

  _closePopup() {
    history.back()
  }

  async _confirmChanges() {
    try {
      if (this._isExecuting) return

      const result = await CustomAlert({
        type: 'info',
        title: 'Proceed with Goods Condition changes ?',
        confirmButton: { text: i18next.t('button.confirm') },
        cancelButton: { text: i18next.t('button.cancel') },
        invertButton: true
      })

      if (!result.value) {
        return
      }

      this._isExecuting = true

      const component = this.currentDataComponent
      if (!component) {
        this._isExecuting = false
        showToast({ message: i18next.t('text.error_occurred'), type: 'error' })
        return
      }

      // Show spinner for both mobile and web before processing
      component.showSpinner()

      // Get patches based on device type
      let rawPatches = []
      if (isMobileDevice()) {
        rawPatches = component.getChangedRecords() || []
      } else {
        rawPatches = component.exportPatchList({})
      }

      // Check if patches is empty - handle cleanup and return
      if (!rawPatches || rawPatches.length === 0) {
        component.hideSpinner()
        this._isExecuting = false
        showToast({ message: i18next.t('text.nothing_changed'), type: 'info' })
        return
      }

      // Normalize patches to inventoryPatches format (id + conditionOfGoods)
      const inventoryPatches = rawPatches.map(patch => ({
        id: patch.id,
        conditionOfGoods: patch.conditionOfGoods || CONDITION_OF_GOODS.GOOD.value
      }))

      const response = await client.mutate({
        mutation: gql`
          mutation updateInventoryCondition($patches: [InventoryPatch!]!) {
            updateInventoryCondition(patches: $patches) {
              id
              conditionOfGoods
            }
          }
        `,
        variables: { patches: inventoryPatches }
      })

      if (response.errors) {
        throw new Error(response.errors[0]?.message || i18next.t('text.error_occurred'))
      }

      this.dispatchEvent(
        new CustomEvent('condition-updated', {
          bubbles: true,
          composed: true,
          detail: { changes: inventoryPatches }
        })
      )

      if (component) {
        component.hideSpinner()
      }
      this._closeTimeoutId = setTimeout(() => {
        this._closeTimeoutId = null
        this._closePopup()
      }, 50)
    } catch (e) {
      showToast({ message: e.message || i18next.t('text.error_occurred'), type: 'error' })
      const component = this.currentDataComponent
      if (component) {
        component.hideSpinner()
      }
    } finally {
      this._isExecuting = false
    }
  }


  render() {
    const isMobileDeviceCheck = isMobileDevice()

    return html`
      <form id="info-form" class="${isMobileDeviceCheck ? 'single-column-form' : 'multi-column-form'}">
        <fieldset>
          <label>${i18next.t('label.product_info')}</label>
          <input
            type="text"
            name="productInfo"
            .value="${this._productInfoFilter}"
            @input="${this._onProductInfoFilterChange.bind(this)}"
            @keypress="${this._onProductInfoFilterKeyPress.bind(this)}"
          />
        </fieldset>
        <fieldset>
          <label>${i18next.t('label.condition')}</label>
          <select name="conditionFilter" .value="${this._conditionFilter}" @change="${this._onConditionFilterChange.bind(this)}">
            <option value="">All</option>
            ${Object.keys(CONDITION_OF_GOODS).map(
              key => html`
                <option value="${CONDITION_OF_GOODS[key].value}">${i18next.t(`label.${CONDITION_OF_GOODS[key].name}`)}</option>
              `
            )}
          </select>
        </fieldset>
      </form>

      ${!isMobileDeviceCheck
        ? html`
            <div class="grist">
              ${this.config
                ? html`
                    <data-grist
                      id="grist"
                      .mode=${'GRID'}
                      .config=${this.config}
                      .fetchHandler="${this.fetchHandler.bind(this)}"
                    ></data-grist>
                  `
                : html`<div>Loading...</div>`}
            </div>
          `
        : html`
            <mobile-condition-of-goods-listing
              .config="${this.mobileConfig}"
              .fetchHandler="${this.fetchHandler.bind(this)}"
              @field-change="${this._onFieldChange.bind(this)}"
            ></mobile-condition-of-goods-listing>
          `}

      <div class="button-container">
        <mwc-button
          outlined
          class="secondary"
          @click="${this._closePopup.bind(this)}"
          label="${i18next.t('button.close')}"
          icon="close"
          ?disabled=${this._isExecuting}
        ></mwc-button>
        <mwc-button
          raised
          @click="${this._confirmChanges.bind(this)}"
          label="${i18next.t('button.confirm')}"
          icon="check"
          ?disabled=${this._isExecuting}
        ></mwc-button>
      </div>
    `
  }
}

window.customElements.define('condition-of-goods-popup', ConditionOfGoodsPopup)

