import '@things-factory/barcode-ui'
import '@things-factory/grist-ui'
import { css, html } from 'lit-element'
import { gql } from 'graphql-tag'
import { MultiColumnFormStyles, SingleColumnFormStyles } from '@things-factory/form-ui'
import { WORKSHEET_STATUS } from '../../constants'
import { i18next } from '@things-factory/i18n-base'
import { isMobileDevice } from '@things-factory/utils'
import { LoadingExecutionBase } from './loading-execution-base'
import '../../components/list-view/product-list-view'
import { fetchPageSettings } from '../../../util'
import { CommonButtonStyles } from '@things-factory/styles'
import { client, CustomAlert, gqlContext } from '@things-factory/shell'
import { openPopup } from '@things-factory/layout-base'
import { showToast } from '../../../util'
import './loading-package-info-popup'

// Constants
const SETTINGS = {
  QC_SKU: 'qc-sku',
  DISABLE_QC: 'disable-QC-in-loading',
  ENABLE_TOTE_SCANNING: 'enable-tote-scanning',
  DISPLAY_CONVERSION: 'display-conversion'
}

const TAB_TYPES = {
  QC: 'QC',
  LOADING: 'LOADING',
  LOADED: 'LOADED'
}

const DEFAULT_TABS = [TAB_TYPES.QC, TAB_TYPES.LOADING, TAB_TYPES.LOADED]
const LOADING_TABS = [TAB_TYPES.LOADING, TAB_TYPES.LOADED]

const VALIDATE_QC_SEALS = gql`
  query validateQcSeals($releaseGoodNo: String!) {
    validateQcSeals(releaseGoodNo: $releaseGoodNo) {
      valid
      error
      minimumSealNumber
    }
  }
`

const GROUP_PACKING_TAB_TYPES = {
  SKU: 'SKU',
  PACKING_LIST: 'Packing Label'
}

const GROUP_PACKING_TABS = [GROUP_PACKING_TAB_TYPES.SKU, GROUP_PACKING_TAB_TYPES.PACKING_LIST]

const CREATE_GROUP_LOADING_PACKAGES = gql`
  mutation createGroupLoadingPackages($releaseGoodNo: String!, $groupedItems: [GroupLoadingPackageItem!]!) {
    createGroupLoadingPackages(releaseGoodNo: $releaseGoodNo, groupedItems: $groupedItems) {
      id
      name
      status
      loadingPackageItems {
        id
        name
        releaseQty
        orderProduct {
          id
        }
      }
    }
  }
`

const GET_LOADING_PACKAGES = gql`
  query loadingPackagesByReleaseGoodNo($releaseGoodNo: String!) {
    loadingPackagesByReleaseGoodNo(releaseGoodNo: $releaseGoodNo) {
      id
      name
      status
      createdAt
      loadingPackageItems {
        id
        name
        packedQty
        orderProduct {
          id
          name
          packingType
          product {
            id
            name
            sku
          }
        }
        productDetail {
          id
          packingType
        }
      }
    }
  }
`

// List View Configurations
const QC_LIST_CONFIG = {
  selectable: true,
  columnLeft: {
    size: 8,
    fields: [
      {
        type: 'row',
        content: [
          {
            header: 'Product Name',
            field: 'relatedOrderInv.product.name',
            type: 'string',
            style: '-webkit-line-clamp: 2;'
          }
        ]
      },
      { type: 'row', content: [{ header: 'SKU No.', field: 'relatedOrderInv.product.sku', type: 'string' }] },
      {
        type: 'row',
        content: [
          { header: 'Exp Date', field: 'expirationDate', type: 'string' },
          { header: 'Batch No', field: 'relatedOrderInv.batchId', type: 'string' }
        ]
      },
      {
        type: 'row',
        content: [
          { header: 'Packing Size', field: 'packingSize', type: 'string' },
          { header: 'Packing Type', field: 'relatedOrderInv.packingType', type: 'string' }
        ]
      }
    ]
  },
  columnRight: {
    size: 4,
    fields: [
      {
        type: 'row',
        content: [{ header: 'Bin No.', field: 'binLocation.name', type: 'string', style: 'font-weight: bold;' }]
      },
      {
        type: 'row',
        content: [{ header: 'Pack Conv.', field: 'conversion', type: 'string' }]
      },
      {
        type: 'valueBox',
        content: { header: 'QC Qty.', field: 'sortedQty', field2: 'pickedQty', type: 'string' }
      }
    ]
  }
}

const LOADING_LIST_CONFIG = {
  selectable: true,
  columnLeft: {
    size: 8,
    fields: [
      {
        type: 'row',
        content: [
          {
            header: 'Product Name',
            field: 'relatedOrderInv.product.name',
            type: 'string',
            style: '-webkit-line-clamp: 2;'
          }
        ]
      },
      { type: 'row', content: [{ header: 'SKU No.', field: 'relatedOrderInv.product.sku', type: 'string' }] },
      {
        type: 'row',
        content: [
          { header: 'Exp Date', field: 'expirationDate', type: 'string' },
          { header: 'Batch No', field: 'relatedOrderInv.batchId', type: 'string' }
        ]
      },
      {
        type: 'row',
        content: [
          { header: 'Packing Size', field: 'packingSize', type: 'string' },
          { header: 'Packing Type', field: 'relatedOrderInv.packingType', type: 'string' }
        ]
      }
    ]
  },
  columnRight: {
    size: 4,
    fields: [
      {
        type: 'row',
        content: [{ header: 'Bin No.', field: 'binLocation.name', type: 'string', style: 'font-weight: bold;' }]
      },
      {
        type: 'row',
        content: [{ header: 'Pack Conv.', field: 'conversion', type: 'string' }]
      },
      {
        type: 'valueBox',
        content: { header: 'Ready Qty.', field: 'sortedQty', field2: 'pickedQty', type: 'string' }
      }
    ]
  }
}

const SKU_LIST_CONFIG = {
  selectable: true,
  columnLeft: {
    size: 8,
    fields: [
      {
        type: 'row',
        content: [
          {
            header: 'SKU No.',
            field: 'relatedOrderInv.product.sku',
            type: 'string'
          }
        ]
      },
      {
        type: 'row',
        content: [
          {
            header: 'Product Name',
            field: 'relatedOrderInv.product.name',
            type: 'string',
            style: '-webkit-line-clamp: 2;'
          }
        ]
      },
      {
        type: 'row',
        content: [
          {
            header: 'Packing Type',
            field: 'relatedOrderInv.packingType',
            type: 'string'
          }
        ]
      }
    ]
  },
  columnRight: {
    size: 4,
    fields: [
      {
        type: 'row',
        content: [
          {
            header: 'Total Qty.',
            field: 'remainingQty',
            type: 'string'
          }
        ]
      },
      {
        type: 'editableValueBox',
        content: { header: 'Group Qty.', field: 'groupQty', type: 'number', placeholder: 'e.g. 10', defaultValue: '' }
      }
    ]
  }
}

export class LoadingExecution extends LoadingExecutionBase {
  static get properties() {
    return {
      ...super.properties,
      _useQcSku: { type: Boolean },
      _currentReleaseGood: { type: Object },
      _tabCounts: { type: Object },
      _qcBannerState: { type: Object },
      _isGroupPackingMode: { type: Boolean },
      _groupPackingActiveTab: { type: String },
      _loadingPackages: { type: Array },
      _combinedSkuData: { type: Array }
    }
  }

  static get styles() {
    return [
      MultiColumnFormStyles,
      SingleColumnFormStyles,
      css`
        :host {
          display: flex;
          flex-direction: column;
          overflow: hidden;
          padding: 0;
          flex: 1;
        }
        h2 {
          padding: var(--subtitle-padding);
          font: var(--subtitle-font);
          color: var(--subtitle-text-color);
          border-bottom: var(--subtitle-border-bottom);
        }
        legend mwc-icon {
          vertical-align: middle;
          margin: var(--grist-title-icon-margin);
          font-size: var(--grist-title-icon-size);
          color: var(--grist-title-icon-color);
          cursor: pointer;
        }
        .flex-col {
          display: flex;
          flex-direction: column;
        }
        .flex-row {
          display: flex;
          flex-direction: row;
        }
        .flex-50 {
          flex: 50%;
        }
        .mt-5px {
          margin-top: 5px;
        }
        .font-bold {
          font-weight: bold !important;
        }
        .text-14 {
          font-size: 14px !important;
          line-height: 1.5 !important;
        }
        .text-center {
          display: flex;
          align-items: center;
        }
        @media screen and (max-width: 460px) {
          .single-column-form {
            max-width: 100%;
            grid-gap: 5px;
          }
        }
        .side-padding-10 {
          padding: 0 10px 0px 10px;
        }
        /* Set icon size */
        mwc-icon {
          font-size: 24px;
        }
        .issue-btn,
        .back-btn {
          background-color: #3a8eab;
          color: #f3f2f7;
          border: none;
          padding: 5px 10px;
          border-radius: 3px;
          cursor: pointer;
        }
        .issue-btn:hover,
        .back-btn:hover {
          background-color: #357d92;
        }
        .tabs {
          display: flex;
          justify-content: space-between;
        }
        .tab-info {
          display: flex;
          justify-content: space-between;
          color: #f3f2f7;
          background-color: #007e7f;
          padding: 10px;
        }
        .tab-button {
          flex: 1;
          padding: 10px;
          background-color: #d2d1d6;
          color: #007e7f;
          border: none;
          cursor: pointer;
          text-align: center;
          border-radius: 10px 10px 0 0;
          font-weight: bold;
        }
        .tab-button.active {
          color: #f3f2f7;
          background-color: #007e7f;
        }
        .tab-content {
          display: none;
        }
        .tab-content.active {
          display: flex;
          flex-direction: column;
          flex: 1;
          overflow: hidden;
        }
        .tab-content.active product-list-view {
          flex: 1;
          overflow-y: auto;
          min-height: 0;
        }
        .order-no {
          display: -webkit-box;
          -webkit-line-clamp: 1;
          -webkit-box-orient: vertical;
          overflow: hidden;
        }
        .order-info {
          border: none;
          background: none;
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: 0 12px 8px;
        }
        .loading-banner {
          background-color: #fff3cd;
          border: 1px solid #ffc107;
          border-radius: 4px;
          padding: 12px 16px;
          margin: 10px;
          display: flex;
          justify-content: space-between;
          align-items: center;
          color: #856404;
        }
        .loading-banner button {
          background-color: #007e7f;
          color: white;
          border: none;
          padding: 6px 12px;
          border-radius: 4px;
          cursor: pointer;
          font-weight: bold;
        }
        .loading-banner button:hover {
          background-color: #005f60;
        }
        .qc-banner {
          background-color: #fff3cd;
          border: 1px solid #ffc107;
          border-radius: 4px;
          padding: 12px 16px;
          margin: 10px;
          display: flex;
          justify-content: space-between;
          align-items: center;
          color: #856404;
        }
        .qc-banner button {
          background-color: #007e7f;
          color: white;
          border: none;
          padding: 6px 12px;
          border-radius: 4px;
          cursor: pointer;
          font-weight: bold;
        }
        .qc-banner button:hover {
          background-color: #005f60;
        }
        #sku {
          --product-item-selected-bg: #d4edea;
        }
      `
    ]
  }

  constructor() {
    super()
    this._executionData = { ...this._executionData, ownCollection: false }
    this._useQcSku = false
    this._currentReleaseGood = null
    this._qcBannerState = { show: false, needsSealing: false, minimumSealNumber: 0 }
    this._isGroupPackingMode = false
    this._loadingPackages = []
    this._combinedSkuData = []
    this._deliveryOrderConfig = {
      columnLeft: {
        size: 8,
        fields: [
          {
            type: 'row',
            content: [{ header: 'Delivery Order No.', field: 'name', type: 'string' }]
          },
          {
            type: 'row',
            content: [{ header: 'Vehicle Number', field: 'truckNo', type: 'string' }]
          }
        ]
      },
      columnRight: {
        size: 4,
        fields: [
          {
            type: 'actionBox',
            content: [
              {
                header: 'View Info',
                btnClass: 'btn-common',
                callback: rowData => {
                  this.openDoInfoPopup(rowData.name)
                }
              }
            ]
          }
        ]
      }
    }
  }

  updated(changedProperties) {
    if (changedProperties.has('worksheet')) {
      this._currentReleaseGood = {
        releaseGood: this.worksheet?.releaseGood,
        bizplaceName: this.worksheet?.bizplaceName,
        startedAt: this.worksheet?.startedAt
      }
    }

    // Update banner state when QC or loading data changes
    if (changedProperties.has('qcData') || changedProperties.has('loadingData')) {
      if (this._updateQcBannerState) {
        this._updateQcBannerState()
      }
    }
  }

  get groupPackingListButton() {
    return {
      title: i18next.t('button.group_packing_label'),
      action: async () => {
        if (this.state?.activeTab !== TAB_TYPES.LOADING) {
          showToast({ message: i18next.t('text.only_available_on_loading_tab'), type: 'error' })
          return
        }

        await this._fetchLoadingPackages()
        this._calculateAndCombineSkuData()
        this._isGroupPackingMode = true
        this.getButton()
      },
      ...CommonButtonStyles.inspect
    }
  }

  //===== OVERWRITE PARENT CLASS, FOR GROUP PACKING MODE =====
  getButton() {
    if (this._isGroupPackingMode) {
      const actions = [
        {
          title: i18next.t('button.back'),
          action: () => {
            this._isGroupPackingMode = false
            this.getButton()
          },
          ...CommonButtonStyles.back
        },
        {
          title: i18next.t('button.group'),
          action: async () => {
            await this.handleGroupPackages()
          },
          ...CommonButtonStyles.submit
        }
      ]

      this.parent.configContext(actions)
    } else {
      super.getButton()
    }
  }

  get backButton() {
    const base = super.backButton
    return {
      ...base,
      action: () => {
        if (this._isGroupPackingMode) {
          this._groupPackingActiveTab = GROUP_PACKING_TAB_TYPES.SKU
          this._isGroupPackingMode = false
        } else {
          base.action()
        }
      }
    }
  }

  combineSameProducts(data) {
    const combinedMap = new Map()

    data.forEach(item => {
      const key = `${item.relatedOrderInv?.product?.sku}_${item.batchId}_${item.expirationDate}`

      if (combinedMap.has(key)) {
        const existing = combinedMap.get(key)
        existing.releaseQty += item.releaseQty
        existing.pickedQty += item.pickedQty
        existing.sortedQty += item.sortedQty
      } else {
        combinedMap.set(key, { ...item })
      }
    })

    return Array.from(combinedMap.values())
  }

  async resetView() {
    const pageSettings = await fetchPageSettings({
      settings: {
        name: 'name',
        operator: 'in',
        value: [SETTINGS.DISABLE_QC, SETTINGS.QC_SKU, SETTINGS.ENABLE_TOTE_SCANNING, SETTINGS.DISPLAY_CONVERSION]
      }
    })
    const settingsMap = new Map(pageSettings?.settings?.map(setting => [setting.name, setting.value]) || [])

    this._disableQC = settingsMap.get(SETTINGS.DISABLE_QC) === 'true'
    this._useQcSku = settingsMap.get(SETTINGS.QC_SKU) === 'true'
    this._enableToteScanningValue = parseInt(settingsMap.get(SETTINGS.ENABLE_TOTE_SCANNING) || '0', 10)
    this._displayConversion = settingsMap.get(SETTINGS.DISPLAY_CONVERSION) === 'true'
    this._enableToteScanning = this._enableToteScanningValue >= 1
    this.toteNo = ''

    // UX-safe tab selection: Auto-switch to LOADED if LOADING is empty but LOADED has items
    let activeTab = !this._disableQC ? TAB_TYPES.QC : TAB_TYPES.LOADING
    if (this._tabCounts && activeTab === TAB_TYPES.LOADING) {
      const loadingCounts = this._tabCounts.LOADING || { total: 0, pending: 0 }
      const loadedCounts = this._tabCounts.LOADED || { total: 0, pending: 0 }
      if (loadingCounts.total === 0 && loadedCounts.total > 0) {
        activeTab = TAB_TYPES.LOADED
      }
    }
    this.state = { ...this.state, activeTab }

    // Process worksheet details
    const processedDetails = this._useQcSku ? this.combineSameProducts(this.worksheetDetails) : this.worksheetDetails

    // Check if any order inventory has refWorksheetId (when data comes from props)
    if (this.worksheetDetails && this.worksheetDetails.length > 0) {
      this._hasRefWorksheetId = this.worksheetDetails.some(
        item => item?.relatedOrderInv?.refWorksheetId != null && item?.relatedOrderInv?.refWorksheetId !== ''
      )
    }

    // Filter data for different tabs
    // QC tab: items that still need QC (sortedQty < pickedQty)
    this.qcData = processedDetails.filter(data => data?.sortedQty < data?.pickedQty && data.status !== 'LOADED') || []
    // Loading tab: items that have completed QC (sortedQty >= pickedQty) and are not yet loaded
    this.loadingData =
      processedDetails.filter(data => data?.sortedQty >= data?.pickedQty && data.status != WORKSHEET_STATUS.DONE.value) || []
    this.loadedData = this.deliveryOrdersInfo || []

    // Update execution data
    this._executionData = {
      ...this._executionData,
      orderId: this.worksheet?.releaseGood?.id,
      worksheetId: this.worksheet?.worksheet?.id
    }

    // Check seal status after resetting view (needed for Tote button visibility)
    await this._checkAndUpdateSealStatus()
    this.getButton()
    // Update QC banner state after resetting view
    await this._updateQcBannerState()
  }

  get qcListItemConfig() {
    return this._filterConversionField(QC_LIST_CONFIG)
  }

  get loadingListItemConfig() {
    return this._filterConversionField(LOADING_LIST_CONFIG)
  }

  get skuListItemConfig() {
    return SKU_LIST_CONFIG
  }

  _filterConversionField(config) {
    if (this._displayConversion) return config
    return {
      ...config,
      columnRight: {
        ...config.columnRight,
        fields: config.columnRight.fields.filter(f => !(f.type === 'row' && f.content?.[0]?.field === 'conversion'))
      }
    }
  }

  get deliveryOrderConfig() {
    return this._deliveryOrderConfig
  }

  _calculateAndCombineSkuData() {
    if (!this.loadingData || this.loadingData.length === 0) {
      this._combinedSkuData = []
      return
    }

    // Step 1: Group loadingData by orderProductId and sum their releaseQty
    const releaseQtyByOrderProductId = new Map()
    this.loadingData.forEach(item => {
      const orderProductId = item.relatedOrderInv?.orderProduct?.id
      if (orderProductId) {
        const currentReleaseQty = parseFloat(item.relatedOrderInv?.releaseQty || item.releaseQty) || 0
        const existing = releaseQtyByOrderProductId.get(orderProductId) || 0
        releaseQtyByOrderProductId.set(orderProductId, existing + currentReleaseQty)
      }
    })

    // Step 2: Group loadingPackageItems by orderProductId and sum their packedQty
    const packedQtyByOrderProductId = new Map()
    if (this._loadingPackages && this._loadingPackages.length > 0) {
      this._loadingPackages.forEach(pkg => {
        if (pkg.loadingPackageItems && pkg.loadingPackageItems.length > 0) {
          pkg.loadingPackageItems.forEach(item => {
            const orderProductId = item.orderProduct?.id
            if (orderProductId) {
              const packedQty = parseFloat(item.packedQty) || 0
              const existing = packedQtyByOrderProductId.get(orderProductId) || 0
              packedQtyByOrderProductId.set(orderProductId, existing + packedQty)
            }
          })
        }
      })
    }

    // Step 3: Combine items by orderProductId and create simple array
    const combinedMap = new Map()
    
    this.loadingData.forEach(item => {
      const orderProductId = item.relatedOrderInv?.orderProduct?.id
      if (!orderProductId) return

      if (!combinedMap.has(orderProductId)) {
        const totalReleaseQty = releaseQtyByOrderProductId.get(orderProductId) || 0
        const totalPackedQty = packedQtyByOrderProductId.get(orderProductId) || 0
        const remainingQty = Math.max(0, totalReleaseQty - totalPackedQty)

        // Create simple object with only needed fields
        combinedMap.set(orderProductId, {
          id: item.id, // Keep first item's id for selection
          orderProductId: orderProductId,
          remainingQty: remainingQty.toString(),
          packedQty: totalPackedQty,
          sku: item.relatedOrderInv?.product?.sku || '',
          productName: item.relatedOrderInv?.product?.name || '',
          packingType: item.relatedOrderInv?.packingType || '',
          isInventoryDecimal: item.relatedOrderInv?.product?.isInventoryDecimal || false,
          productBarcodes: item.relatedOrderInv?.productDetail?.productBarcodes || [],
          groupQty: null, // Reset to null (empty field, will use full availableQty)
          relatedOrderInv: {
            ...item.relatedOrderInv,
            orderProduct: {
              id: orderProductId
            }
          }
        })
      }
    })

    // Step 4: Filter out items with remainingQty === 0
    this._combinedSkuData = Array.from(combinedMap.values()).filter(item => {
      const remainingQty = parseFloat(item.remainingQty || 0)
      return remainingQty > 0
    })
  }

  get filteredSkuData() {
    return this._combinedSkuData || []
  }

  get packingListConfig() {
    return {
      selectable: false,
      columnLeft: {
        size: 8,
        fields: [
          {
            type: 'row',
            content: [
              {
                header: 'Packing Label No.',
                field: 'displayNumber',
                type: 'number',
                style: 'font-weight: bold;'
              }
            ]
          }
        ]
      },
      columnRight: {
        size: 4,
        fields: [
          {
            type: 'actionBox',
            content: [
              {
                header: 'View Info',
                btnClass: 'btn-common',
                callback: rowData => {
                  const originalPackage = this._loadingPackages.find(pkg => pkg.id === rowData.id)
                  if (originalPackage) {
                    this.openLoadingPackageInfoPopup(originalPackage)
                  } else {
                    console.error('Loading package not found:', rowData.id)
                    showToast({ message: i18next.t('text.error_occurred') || 'Error loading package details', type: 'error' })
                  }
                }
              }
            ]
          }
        ]
      }
    }
  }

  get _skuBarcodeInput() {
    return this.shadowRoot.querySelector('barcode-scanable-input[name="skuBarcode"]')?.shadowRoot.querySelector('input')
  }

  get _skuQtyInput() {
    return this.shadowRoot.querySelector('input[name="skuQty"]')
  }

  get _skuListView() {
    return this.shadowRoot.querySelector('#sku')
  }

  /**
   * Determines if the "Go to LOADED" banner should be shown.
   * Banner appears when:
   * - Current tab is LOADING
   * - LOADING tab has no items (loadingData.length === 0) - uses SAME source as Total SKU
   * - LOADED tab has items (loadedData.deliveryOrders.length > 0)
   *
   * Uses the same data source as Total SKU display to ensure consistency.
   */
  _shouldShowLoadingBanner() {
    // Banner only shows on LOADING tab
    if (this.state?.activeTab !== TAB_TYPES.LOADING) {
      return false
    }

    // Use the SAME source as Total SKU display: this.loadingData?.length
    const loadingItemCount = this.loadingData?.length || 0
    const loadedItemCount = this.loadedData?.deliveryOrders?.length || 0

    // Show banner when LOADING is empty but LOADED has items
    return loadingItemCount === 0 && loadedItemCount > 0
  }

  /**
   * Checks if totes need to be sealed by calling the validation query
   * Returns: { needsSealing: boolean, error?: string, minimumSealNumber?: number }
   */
  async _checkToteSealStatus() {
    if (!this._enableToteScanning) {
      return { needsSealing: false, minimumSealNumber: 0 }
    }

    const orderNo = this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
    if (!orderNo) {
      return { needsSealing: false, minimumSealNumber: 0 }
    }

    try {
      const validationResponse = await client.query({
        query: VALIDATE_QC_SEALS,
        variables: { releaseGoodNo: orderNo },
        context: gqlContext()
      })

      if (!validationResponse.errors && validationResponse.data?.validateQcSeals) {
        const { valid, error, minimumSealNumber } = validationResponse.data.validateQcSeals
        const minSealNum = minimumSealNumber || 0
        // If minimumSealNumber is 0, sealing is not required even if valid is false
        const needsSealing = !valid && minSealNum > 0
        return { needsSealing, error, minimumSealNumber: minSealNum }
      }
    } catch (e) {
      // If validation fails, assume sealing is needed
      return { needsSealing: true, error: e.message || 'Seal validation failed', minimumSealNumber: 0 }
    }

    return { needsSealing: false, minimumSealNumber: 0 }
  }

  /**
   * Updates the QC banner state based on current data
   */
  async _updateQcBannerState() {
    // Banner only shows on QC tab
    if (this.state?.activeTab !== TAB_TYPES.QC) {
      this._qcBannerState = { show: false, needsSealing: false, minimumSealNumber: 0 }
      return
    }

    // Use the SAME source as Total SKU display: this.qcData?.length
    const qcItemCount = this.qcData?.length || 0
    const loadingItemCount = this.loadingData?.length || 0

    // Show banner when QC is empty but LOADING has items
    const shouldShow = qcItemCount === 0 && loadingItemCount > 0

    if (!shouldShow) {
      this._qcBannerState = { show: false, needsSealing: false, minimumSealNumber: 0 }
      return
    }

    // Check if totes need sealing
    const sealStatus = await this._checkToteSealStatus()

    this._qcBannerState = {
      show: true,
      needsSealing: sealStatus.needsSealing,
      error: sealStatus.error,
      minimumSealNumber: sealStatus.minimumSealNumber || 0
    }
    this.requestUpdate()
  }

  /**
   * Determines if the QC banner should be shown (synchronous getter for render)
   */
  get _shouldShowQcBanner() {
    return this._qcBannerState?.show || false
  }

  async openGroupPackingTab(e, tabName) {
    if (this.state?.activeTab !== TAB_TYPES.LOADING) {
      showToast({ message: i18next.t('text.only_available_on_loading_tab'), type: 'error' })
      return
    }

    this._groupPackingActiveTab = tabName
    await this.updateComplete
    
    await this._fetchLoadingPackages()
    if (tabName === GROUP_PACKING_TAB_TYPES.SKU) {
      this._calculateAndCombineSkuData()
    }
  }

  async _fetchLoadingPackages() {
    const releaseGoodNo = this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
    if (!releaseGoodNo) {
      console.warn('No release good number available to fetch loading packages')
      this._loadingPackages = []
      return
    }

    try {
      const response = await client.query({
        query: GET_LOADING_PACKAGES,
        variables: { releaseGoodNo },
      })

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

      const packages = response.data.loadingPackagesByReleaseGoodNo || []
      this._loadingPackages = packages.map((pkg, index) => ({
        ...pkg,
        displayNumber: index + 1
      }))
      this.requestUpdate()
    } catch (error) {
      console.error('Error fetching loading packages:', error)
      showToast({ message: error.message || i18next.t('text.error_occurred'), type: 'error' })
      this._loadingPackages = []
    }
  }


  async openLoadingPackageInfoPopup(loadingPackage) {
    if (!loadingPackage || !loadingPackage.loadingPackageItems || loadingPackage.loadingPackageItems.length === 0) {
      showToast({ message: i18next.t('text.no_items_found') || 'No items found in this package', type: 'info' })
      return
    }

    const items = loadingPackage.loadingPackageItems.map(item => ({
      id: item.id,
      sku: item.orderProduct?.product?.sku || '',
      productName: item.orderProduct?.product?.name || item.orderProduct?.name || '',
      packingType: item.productDetail?.packingType || item.orderProduct?.packingType || '',
      qty: item.packedQty
    }))

    await openPopup(
      html`
        <loading-package-info-popup
          ._data=${items}
          ._packageName=${loadingPackage.name}
          ._packageNumber=${loadingPackage.displayNumber}
          ._packageId=${loadingPackage.id}
          @undo=${async e => {
            await this._fetchLoadingPackages()
            this._calculateAndCombineSkuData()
            this.requestUpdate()
          }}
        ></loading-package-info-popup>
      `,
      {
        backdrop: true,
        size: 'large',
        title: `${i18next.t('text.packing_list_info') || 'Packing List Info'}: ${loadingPackage.name}`
      }
    )
  }

  _handleSkuScanSubmit(e) {
    if (e.keyCode !== 13) return
    e.preventDefault()

    const scannedValue = this._skuBarcodeInput?.value?.trim()
    if (!scannedValue) {
      showToast({ message: i18next.t('text.product_barcode_is_empty'), type: 'error' })
      this._skuBarcodeInput?.focus()
      return
    }

    const matches = this.filteredSkuData.filter(item =>
      (item.productBarcodes || []).some(pb => pb.gtin === scannedValue)
    )

    if (matches.length === 0) {
      // No match — show error and clear barcode
      showToast({ message: i18next.t('text.barcode_not_found'), type: 'error' })
      if (this._skuBarcodeInput) this._skuBarcodeInput.value = ''
      if (this._skuQtyInput) this._skuQtyInput.value = ''
      this._skuBarcodeInput?.focus()
    } else if (matches.length === 1) {
      // Single match — highlight and check checkbox immediately, then validate qty
      const matched = matches[0]
      if (this._skuListView) {
        this._skuListView.selectedRecordId = null
        this._skuListView.highlightedIds = [matched.id]
        this._skuListView.scrollToId(matched.id)
        if (!this._skuListView.selectedItems.includes(matched.id)) {
          this._skuListView.selectedItems = [...this._skuListView.selectedItems, matched.id]
        }
      }

      const qty = parseFloat(this._skuQtyInput?.value)
      const { remainingQty, isInventoryDecimal, sku: productSku } = matched

      if (isNaN(qty)) {
        showToast({ message: i18next.t('text.please_enter_qty'), type: 'error' })
        this._skuQtyInput?.focus()
      } else if (qty === 0) {
        showToast({ message: i18next.t('text.group_quantity_cannot_be_zero'), type: 'error' })
        this._skuQtyInput?.focus()
      } else if (qty < 0) {
        showToast({ message: i18next.t('text.group_quantity_cannot_be_negative'), type: 'error' })
        this._skuQtyInput?.focus()
      } else if (!isInventoryDecimal && !Number.isInteger(qty)) {
        showToast({ message: i18next.t('text.decimal_not_allowed_for_product', { sku: productSku }), type: 'error' })
      } else if (qty > parseFloat(remainingQty)) {
        showToast({ message: i18next.t('text.group_quantity_exceeds_total'), type: 'error' })
      } else {
        matched.groupQty = qty
        this._combinedSkuData = [...this._combinedSkuData]
        if (this._skuQtyInput) this._skuQtyInput.value = ''
        this._skuQtyInput?.focus()
      }
    } else {
      // Multiple matches — highlight all, let user enter qty manually in the list
      if (this._skuListView) {
        this._skuListView.selectedRecordId = null
        this._skuListView.highlightedIds = matches.map(m => m.id)
        this._skuListView.scrollToId(matches[0].id)
      }

      if (this._skuQtyInput?.value?.trim()) {
        showToast({ message: i18next.t('text.multiple_matches_enter_qty_manually'), type: 'warn' })
      }
      if (this._skuQtyInput) this._skuQtyInput.value = ''
    }
  }

  async handleGroupPackages() {
    try {
      if (!this._skuListView) {
        showToast({ message: i18next.t('text.sku_list_view_not_found') })
        return
      }

      const selectedItemIds = this._skuListView.selectedItems || []
      if (selectedItemIds.length === 0) {
        showToast({ message: i18next.t('text.no_sku_selected') })
        return
      }

      const viewData = this._skuListView.data || []
      const selectedItems = viewData.filter(item => selectedItemIds.includes(item.id))

      if (selectedItems.length === 0) {
        showToast({ message: i18next.t('text.selected_items_not_found') })
        return
      }
      
      const groupedItems = selectedItems.map(item => {
        const availableQty = parseFloat(item.remainingQty) || 0
        // Check direct property first (from combined SKU data), then fallback to nested path
        const isInventoryDecimal = item.isInventoryDecimal === true || item.relatedOrderInv?.product?.isInventoryDecimal === true
        const productSku = item.sku || item.relatedOrderInv?.product?.sku || 'Unknown'

        let groupQty

        if (item.groupQty == null) {
          groupQty = availableQty
        } else {
          const enteredQty = parseFloat(item.groupQty)

          if (isNaN(enteredQty)) {
            throw new Error(i18next.t('text.invalid_quantity_input') || 'Invalid quantity input')
          } else if (enteredQty === 0) {
            throw new Error(i18next.t('text.group_quantity_cannot_be_zero') || 'Group quantity cannot be zero')
          } else if (enteredQty < 0) {
            throw new Error(i18next.t('text.group_quantity_cannot_be_negative') || 'Group quantity cannot be negative')
          } else {
            groupQty = enteredQty
          }
        }

        // Validate decimal values - only allow decimals if isInventoryDecimal is true
        if (!isInventoryDecimal && !Number.isInteger(groupQty)) {
          throw new Error(
            i18next.t('text.decimal_not_allowed_for_product', { sku: productSku }) ||
              `Decimal quantity is not allowed for product ${productSku}`
          )
        }

        // Validate groupQty doesn't exceed available quantity
        if (groupQty > availableQty) {
          throw new Error(i18next.t('text.group_quantity_exceeds_total'))
        }

        return {
          orderProductId: item.orderProductId,
          groupQty: groupQty
        }
      })

      const releaseGoodNo = this._currentReleaseGood?.releaseGood?.name
      if (!releaseGoodNo) {
        showToast({ message: i18next.t('text.release_good_number_not_found') })
        return
      }

      const response = await client.mutate({
        mutation: CREATE_GROUP_LOADING_PACKAGES,
        variables: {
          releaseGoodNo: releaseGoodNo,
          groupedItems: groupedItems
        },
        context: gqlContext()
      })

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

      const loadingPackage = response.data.createGroupLoadingPackages
      showToast({
        message: i18next.t('text.new_packing_label_created'),
        type: 'success'
      })

      if (this._isGroupPackingMode) {
        await this._fetchLoadingPackages()
        await this.updateComplete
        if (this._groupPackingActiveTab === GROUP_PACKING_TAB_TYPES.SKU) {
          this._calculateAndCombineSkuData()
          await this.updateComplete
          if (this._skuListView) {
            this._skuListView.selectedItems = []
            this._skuListView.selectAll = false
          }
        }
      }
      
      this.getButton()
    } catch (error) {
      console.error('Error creating group loading packages:', error)
      showToast({ message: error.message || i18next.t('text.failed_to_create_group_loading_packages'), type: 'error' })
    }
  }

  render() {
    if (this._isGroupPackingMode) {
      if (!this._groupPackingActiveTab) this._groupPackingActiveTab = GROUP_PACKING_TAB_TYPES.SKU

      return html`
        <button
          class="order-info text-center"
          ?disabled=${!Boolean(this._currentReleaseGood?.releaseGood?.name)}
          @click=${e => {
            if (this._currentReleaseGood?.releaseGood?.name) {
              this.showOrderInfo()
            }
          }}
        >
          <label class="text-14 font-bold order-no"
            >${i18next.t('label.order_no')}: ${this._currentReleaseGood?.releaseGood?.name || this.worksheet?.binLocationName || ''}</label
          >
          <mwc-icon style="color:#007E7F;">info</mwc-icon>
        </button>

        <div class="tabs">
          ${GROUP_PACKING_TABS.map(
            tab => html`
              <button
                class="font-bold tab-button ${this._groupPackingActiveTab === tab ? 'active' : ''}"
                @click=${async e => {
                  await this.openGroupPackingTab(e, tab)
                }}
              >
                ${tab === GROUP_PACKING_TAB_TYPES.SKU ? i18next.t('label.sku') : i18next.t('label.packing_label')}
              </button>
            `
          )}
        </div>

        ${this._groupPackingActiveTab === GROUP_PACKING_TAB_TYPES.SKU
          ? html`
              <div class="tab-info text-center">
                <label class="text-14 font-bold">${i18next.t('label.total_sku')}: ${this.filteredSkuData.length}</label>
              </div>
            `
          : ''}
        
        ${this._groupPackingActiveTab === GROUP_PACKING_TAB_TYPES.PACKING_LIST
          ? html`
              <div class="tab-info text-center">
                <label class="text-14 font-bold">${i18next.t('label.total_packing_label')}: ${(this._loadingPackages || []).length}</label>
              </div>
            `
          : ''}

        <div class="tab-content ${this._groupPackingActiveTab === GROUP_PACKING_TAB_TYPES.SKU ? 'active' : ''}">
          <form class="multi-column-form">
            <fieldset>
              <label>${i18next.t('label.scan_product_barcode')}</label>
              <barcode-scanable-input
                name="skuBarcode"
                custom-input
                @keypress="${e => this._handleSkuScanSubmit(e)}"
              ></barcode-scanable-input>
              <label>${i18next.t('label.qty')}</label>
              <input
                type="number"
                name="skuQty"
                min="1"
                @keypress="${e => this._handleSkuScanSubmit(e)}"
              />
            </fieldset>
          </form>
          <product-list-view
            id="sku"
            .config=${this.skuListItemConfig}
            .data=${this.filteredSkuData}
          ></product-list-view>
        </div>

        <div class="tab-content ${this._groupPackingActiveTab === GROUP_PACKING_TAB_TYPES.PACKING_LIST ? 'active' : ''}">
          ${this._loadingPackages && this._loadingPackages.length > 0
            ? html`
                <product-list-view
                  .config=${this.packingListConfig}
                  .data=${this._loadingPackages}
                ></product-list-view>
              `
            : ''}
        </div>
      `
    }

    if (!this.state) {
      this.resetView()
    }

    const tabs = !this._disableQC ? DEFAULT_TABS : LOADING_TABS

    // Set initial active tab if not set or if current tab is not in available tabs
    if (!this.state?.activeTab || !tabs.includes(this.state.activeTab)) {
      const initialTab = !this._disableQC ? TAB_TYPES.QC : TAB_TYPES.LOADING
      this.state = { ...this.state, activeTab: initialTab }
    }

    return html`
      <!-- Header Form Section -->
      <div class="side-padding-10">
        <form class="${isMobileDevice() ? 'single-column-form' : 'multi-column-form'}">
          <fieldset>
            ${this.state?.activeTab === TAB_TYPES.QC
              ? html`
                  <!-- QC Tab Inputs -->
                  ${this._enableToteScanning && this._disableQC === true
                    ? html`
                        <label class="font-bold">${i18next.t('field.tote')}</label>
                        <input name="toteNo" custom-input disabled .value="${this.toteNo || ''}" />
                      `
                    : ''}
                  <label class="font-bold">${i18next.t('label.product_barcode')}</label>
                  <barcode-scanable-input
                    name="productBarcode"
                    custom-input
                    @keypress="${async e => {
                      await this._sort(e)
                    }}"
                  ></barcode-scanable-input>

                  <label class="font-bold">${i18next.t('label.quantity')}</label>
                  <input
                    name="quantity"
                    custom-input
                    @keypress="${async e => {
                      await this._sort(e)
                    }}"
                  />
                `
              : this.state?.activeTab === TAB_TYPES.LOADING
              ? html`
                  <!-- LOADING Tab Inputs -->
                  <label class="font-bold">${i18next.t('label.vehicle_no')}</label>
                  <input ?hidden=${!this._executionData?.ownCollection} name="truckNo" custom-input />
                  <input
                    ?hidden=${this._executionData?.ownCollection}
                    name="warehouseTruck"
                    custom-input
                    readonly
                    @click="${this.selectWarehouseTruck}"
                  />

                  <label class="font-bold">${i18next.t('label.total_pallet_qty')}</label>
                  <input name="totalPalletQty" custom-input />

                  <input
                    type="checkbox"
                    name="ownCollection"
                    ?checked="${this._executionData?.ownCollection}"
                    custom-input
                    @change="${e =>
                      (this._executionData = { ...this._executionData, ownCollection: e.currentTarget.checked })}"
                  />
                  <label class="font-bold">${i18next.t('label.own_collection')}</label>
                `
              : ''}
          </fieldset>
        </form>
      </div>

      <button
        class="order-info text-center"
        ?disabled=${!Boolean(this._currentReleaseGood?.releaseGood?.name)}
        @click=${e => {
          if (this._currentReleaseGood?.releaseGood?.name) {
            this.showOrderInfo()
          }
        }}
      >
        <label class="text-14 font-bold order-no"
          >Order No.:
          ${this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
            ? this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
            : this.worksheet?.isReleaseGoodScan
            ? this.worksheet?.releaseGood?.name
            : this._useQcSku
            ? this.worksheet?.binLocationName
            : ''}</label
        >
        <mwc-icon style="color:#007E7F;">info</mwc-icon>
      </button>

      <div class="tabs">
        ${tabs.map(
          tab => html`
            <button
              class="font-bold tab-button ${this.state?.activeTab === tab ? 'active' : ''}"
              @click=${async e => {
                await this.openTab(e, tab)
              }}
            >
              ${tab}
            </button>
          `
        )}
      </div>

      <div class="tab-info text-center">
        <label class="text-14 font-bold">
          ${this.state?.activeTab === TAB_TYPES.LOADED ? `Total DO: ` : `Total SKU: `} ${this._getTotalItem()}</label
        >
      </div>

      ${this._shouldShowLoadingBanner()
        ? html`
            <div class="loading-banner">
              <span
                >${i18next.t('text.all_items_loaded_proceed_to_loaded', {
                  defaultValue: 'All items loaded. Proceed to LOADED to complete dispatch.'
                })}</span
              >
              <button @click=${async e => await this.openTab(e, TAB_TYPES.LOADED)}>
                ${i18next.t('button.go_to_loaded', { defaultValue: 'Go to LOADED' })}
              </button>
            </div>
          `
        : ''}
      ${this._shouldShowQcBanner
        ? html`
            <div class="qc-banner">
              <span
                >${this._qcBannerState?.needsSealing
                  ? this._qcBannerState?.error ||
                    (this._qcBannerState?.minimumSealNumber > 0
                      ? i18next.t('text.tote_needs_to_be_sealed_with_count', {
                          defaultValue: `Tote needs to be sealed before proceeding to LOADING. Minimum ${this._qcBannerState.minimumSealNumber} seal(s) required.`,
                          count: this._qcBannerState.minimumSealNumber
                        })
                      : i18next.t('text.tote_needs_to_be_sealed', {
                          defaultValue: 'Tote needs to be sealed before proceeding to LOADING.'
                        }))
                  : i18next.t('text.all_items_qc_complete_proceed_to_loading', {
                      defaultValue: 'All items QC complete. Proceed to LOADING to continue.'
                    })}</span
              >
              <button
                @click=${async e => {
                  if (this._qcBannerState?.needsSealing) {
                    await this.openTotePopup()
                  } else {
                    await this.openTab(e, TAB_TYPES.LOADING)
                  }
                }}
              >
                ${this._qcBannerState?.needsSealing
                  ? i18next.t('button.seal_tote', { defaultValue: 'Seal Tote' })
                  : i18next.t('button.go_to_loading', { defaultValue: 'Go to LOADING' })}
              </button>
            </div>
          `
        : ''}

      <div id="qc" class="tab-content ${this.state?.activeTab === TAB_TYPES.QC ? 'active' : ''}">
        <product-list-view id="qc" .config=${this.qcListItemConfig} .data=${this.qcData || []}></product-list-view>
      </div>

      <div id="loading" class="tab-content ${this.state?.activeTab === TAB_TYPES.LOADING ? 'active' : ''}">
        <product-list-view
          id="loading"
          .config=${this.loadingListItemConfig}
          .data=${this.loadingData || []}
        ></product-list-view>
      </div>

      <div id="loaded" class="tab-content ${this.state?.activeTab === TAB_TYPES.LOADED ? 'active' : ''}">
        <product-list-view
          id="loaded"
          .config=${this.deliveryOrderConfig}
          .data=${this?.loadedData?.deliveryOrders || []}
        ></product-list-view>
      </div>
    `
  }
}

customElements.define('loading-execution', LoadingExecution)
