<template>
  <div class="pda-container">
    <div class="header-bar">
      <div class="header-left" :class="{ 'header-action-disabled': interfaceBusy }" @click="handleBack">
        <i class="el-icon-arrow-left"></i>
        <span>直接组盘</span>
      </div>
      <div class="header-right" :class="{ 'header-action-disabled': interfaceBusy }" @click="goHome">首页</div>
    </div>

    <div class="table-body" style="max-height: 500px; overflow-y: auto;">
      <div class="main-content form-section">
        <div class="input-group">
          <label class="input-label">栈板编码</label>
          <div style="display: flex; gap: 8px;">
            <el-input
              v-model="palletCode"
              placeholder="请扫描栈板编码"
              class="form-input"
              style="flex: 0.75;"
              clearable
              inputmode="none"
              autocomplete="off"
              autocorrect="off"
              spellcheck="false"
              @keyup.enter.native="handlePalletScan"
              ref="palletInput"
            />
            <button class="action-btn secondary" style="flex: 0.25; margin: 0;" @click="handleCallPallet" :disabled="interfaceBusy">
              Call栈板
            </button>
          </div>
        </div>

        <div v-if="palletScanned" class="input-group">
          <div style="display: flex; gap: 8px; align-items: end;">
            <div style="flex: 0.65;">
              <label class="input-label">栈板类型</label>
              <el-select
                v-model="currentPalletType"
                placeholder="请选择栈板类型"
                style="width: 100%;"
                :disabled="palletTypeDisabled || interfaceBusy"
                @change="handlePalletTypeChange"
              >
                <el-option
                  v-for="type in palletTypeOptions"
                  :key="type.palletType"
                  :label="`${type.palletType} - ${type.typeDesc}`"
                  :value="type.palletType"
                />
              </el-select>
            </div>
            <div style="flex: 0.35;">
              <label class="input-label">自动分拣</label>
              <el-select
                v-model="currentAutoSort"
                placeholder="请选择"
                style="width: 100%;"
                :disabled="autoSortDisabled || interfaceBusy"
                @change="handleAutoSortChange"
              >
                <el-option label="是" value="Y"></el-option>
                <el-option label="否" value="N"></el-option>
              </el-select>
            </div>
          </div>
        </div>

        <div v-if="palletScanned" class="input-group">
          <el-checkbox
            v-model="forceFullPalletOut"
            :disabled="palletTypeDisabled || interfaceBusy"
            @change="handleForceFullPalletOutChange"
            style="width: 100%;"
          >
            是否强制整托出库
          </el-checkbox>
        </div>

        <div v-if="palletScanned" class="input-group">
          <label class="input-label">当前站点</label>
          <div style="display: flex; gap: 8px;">
            <el-input v-model="currentPalletStation" placeholder="栈板当前站点" class="form-input" readonly style="flex: 0.75;" />
            <button class="action-btn secondary" style="flex: 0.25; margin: 0; white-space: nowrap;" @click="refreshTable" :disabled="interfaceBusy">
              刷新
            </button>
          </div>
        </div>

        <div v-if="palletScanned" class="input-group">
          <div style="display: flex; gap: 8px; align-items: center;">
            <div style="flex: 0.75;">
              <el-radio-group v-model="operationType" style="display: flex;" :disabled="interfaceBusy">
                <el-radio label="in" style="margin-right: 0px; white-space: nowrap;">扫进</el-radio>
                <el-radio label="out" style="white-space: nowrap;">扫出</el-radio>
              </el-radio-group>
            </div>
            <button class="action-btn secondary" style="flex: 0.25; margin: 0; white-space: nowrap;" :disabled="interfaceBusy || currentPalletType === ''" @click="showScanModal">
              扫描条码
            </button>
          </div>
        </div>
      </div>

      <div v-if="palletScanned" class="rma-list">
        <div class="list-title-row" style="display: flex; gap: 8px; align-items: center; padding: 0;">
          <div class="list-title" style="flex: 0.4; margin: 0;">
            <button class="action-btn primary" style="margin: 0;" @click="showDetailModal" :disabled="interfaceBusy">
              明细
            </button>
          </div>
          <button class="action-btn warning" style="flex: 0.3; margin: 0;" @click="showScanOutModal" :disabled="interfaceBusy || scanOutList.length === 0">
            扫出({{ scanOutList.length }})
          </button>
          <!-- 与海安组盘入库唯一差异：此处改为“推送组盘”，并且只允许area/location均为空的托盘触发 - rqrq -->
          <button class="action-btn secondary" style="flex: 0.3; margin: 0;" @click="openPushAssemblyDialog" :disabled="interfaceBusy || !canPushAssembly">
            {{ pushAssemblyLoading ? '处理中...' : '推送组盘' }}
          </button>
        </div>
        <div class="list-title" style="flex: 0.5; margin: 0;">
          <label style="margin-left: 5px;">条码数:{{ detailList.length }}</label>
        </div>
        <div class="detail-table">
          <div class="table-header">
            <div class="col-position">位置</div>
            <div class="col-layer">层数</div>
            <div class="col-serial">标签号</div>
          </div>
          <div v-for="(detail, index) in detailList" :key="index" class="table-row">
            <div class="col-position">{{ detail.position }}</div>
            <div class="col-layer">{{ detail.layer }}</div>
            <div class="col-serial">{{ detail.serialNo }}</div>
          </div>
          <div v-if="detailList.length === 0" class="table-row empty-row">
            <div class="empty-hint">暂无栈板明细数据</div>
          </div>
        </div>
      </div>
    </div>

    <el-dialog
      :title="'已扫描数量:' + detailList.length"
      :visible.sync="detailModalVisible"
      width="90%"
      :close-on-click-modal="false"
      :show-close="false"
      :append-to-body="true"
    >
      <div class="table-body" style="max-height: 240px; overflow-y: auto;">
        <div class="detail-table">
          <div class="table-header">
            <div class="col-position">位置</div>
            <div class="col-layer">层数</div>
            <div class="col-serial">标签号</div>
          </div>
          <div v-for="(detail, index) in detailList" :key="index" class="table-row">
            <div class="col-position">{{ detail.position }}</div>
            <div class="col-layer">{{ detail.layer }}</div>
            <div class="col-serial">{{ detail.serialNo }}</div>
          </div>
          <div v-if="detailList.length === 0" class="table-row empty-row">
            <div class="empty-hint">暂无栈板明细数据</div>
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <button class="action-btn secondary" style="margin-left: 10px;" @click="detailModalVisible = false" :disabled="interfaceBusy">取消</button>
      </div>
    </el-dialog>

    <el-dialog
      :title="'扫出记录 (共' + scanOutList.length + '条)'"
      :visible.sync="scanOutModalVisible"
      width="90%"
      :close-on-click-modal="false"
      :show-close="false"
      :append-to-body="true"
    >
      <div class="table-body" style="max-height: 300px; overflow-y: auto;">
        <div class="detail-table">
          <div class="table-header">
            <div class="col-position">位置</div>
            <div class="col-layer">层数</div>
            <div class="col-serial">标签号</div>
          </div>
          <div v-for="(detail, index) in scanOutList" :key="index" class="table-row">
            <div class="col-position">{{ detail.position }}</div>
            <div class="col-layer">{{ detail.layer }}</div>
            <div class="col-serial">{{ detail.serialNo }}</div>
          </div>
          <div v-if="scanOutList.length === 0" class="table-row empty-row">
            <div class="empty-hint">暂无扫出记录</div>
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <button class="action-btn secondary" @click="scanOutModalVisible = false" :disabled="interfaceBusy">关闭</button>
      </div>
    </el-dialog>

    <!-- 扫码模态框：与海安组盘入库保持一致 - rqrq -->
    <el-dialog
      title="扫描标签"
      :visible.sync="scanModalVisible"
      width="90%"
      :close-on-click-modal="false"
      :show-close="false"
      :modal="true"
      :modal-append-to-body="true"
      :append-to-body="true"
    >
      <div class="scan-modal-content">
        <div v-if="operationType === 'in'" class="modal-form">
          <div v-if="!currentMixedMode && scanLayerOptions.length > 0" class="input-group">
            <label class="input-label">层数（当前选择：第{{ scanLayer }}层）</label>
            <div class="layer-grid">
              <div
                v-for="layer in scanLayerOptions"
                :key="layer"
                class="layer-item"
                :class="{ 'layer-selected': scanLayer === layer }"
                @click="handleLayerClick(layer)"
              >
                {{ layer }}
              </div>
            </div>
          </div>
          <div class="input-group">
            <label class="input-label">
              位置{{ currentSelectedPosition ? `（当前选择：${currentSelectedPosition}）` : '' }}
              <span v-if="positionGridLoading" style="color: #909399; font-size: 12px;">（加载中...）</span>
            </label>
            <div class="position-grid" :class="[{ 'position-grid-loading': positionGridLoading }, getPositionGridClass]">
              <div
                v-for="(item, index) in displayPositionGrid"
                :key="index"
                class="position-item"
                :class="{
                  'position-disabled': positionGridLoading || !availablePositions.includes(item.position),
                  'position-selected': currentSelectedPosition === item.position,
                  'position-loading': positionGridLoading,
                  'position-placeholder': item.isPlaceholder
                }"
                @click="handlePositionClick(item.position)"
              >
                <template v-if="!item.isPlaceholder">{{ item.position }}({{ item.count }})</template>
              </div>
            </div>
          </div>
        </div>

        <div class="input-group">
          <label class="input-label">标签二维码</label>
          <el-input
            ref="scanInput"
            v-model="scanCode"
            placeholder="请扫描标签二维码"
            class="form-input"
            clearable
            :disabled="operationType === 'in' && !currentSelectedPosition"
            @keyup.enter.native="handleLabelScan"
            inputmode="none"
            autocomplete="off"
            autocorrect="off"
            spellcheck="false"
          />
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <button class="action-btn secondary" style="margin-left: 10px;" @click="closeScanModal" :disabled="interfaceBusy">取消</button>
      </div>
    </el-dialog>

    <!-- 调用空托盘：与海安组盘入库保持一致 - rqrq -->
    <el-dialog
      title="调用空托盘"
      :visible.sync="callEmptyModalVisible"
      width="90%"
      :close-on-click-modal="false"
      :show-close="false"
      :append-to-body="true"
    >
      <div class="input-group">
        <label class="input-label">区域</label>
        <el-select v-model="callEmptyForm.areaId" placeholder="请选择区域" style="width: 100%;" @change="handleAreaChangeForCall">
          <el-option v-for="a in areaOptions" :key="a.areaId" :label="a.areaDesc" :value="a.areaId" />
        </el-select>
      </div>
      <div class="input-group">
        <label class="input-label">站点</label>
        <el-select v-model="callEmptyForm.stationCode" placeholder="请选择站点" style="width: 100%;" :disabled="!callEmptyForm.areaId">
          <el-option v-for="s in stationOptions" :key="s.stationCode" :label="`${s.stationCode} (${s.status || '-'})`" :value="s.stationCode" />
        </el-select>
      </div>
      <div class="input-group">
        <label class="input-label">栈板类型</label>
        <el-select v-model="callEmptyForm.palletType" placeholder="请选择栈板类型" style="width: 100%;">
          <el-option v-for="t in callEmptyPalletTypeOptions" :key="t.palletType" :label="`${t.palletType} - ${t.typeDesc}`" :value="t.palletType" />
        </el-select>
      </div>
      <div slot="footer" class="dialog-footer">
        <button class="action-btn primary" @click="submitCallEmpty" :disabled="interfaceBusy || callEmptyLoading">{{ callEmptyLoading ? '处理中...' : '确认' }}</button>
        <button class="action-btn secondary" style="margin-left: 8px;" @click="callEmptyModalVisible = false" :disabled="interfaceBusy || callEmptyLoading">取消</button>
      </div>
    </el-dialog>

    <!-- 直接组盘推送弹窗：必须选择入库口1/入库口2 - rqrq -->
    <el-dialog
      title="请选择入库口"
      :visible.sync="pushAssemblyDialogVisible"
      width="90%"
      :close-on-click-modal="false"
      :show-close="false"
      :append-to-body="true"
    >
      <div class="input-group">
        <label class="input-label">入库口</label>
        <el-select v-model="selectedInboundPort" placeholder="请选择入库口" style="width: 100%;">
          <el-option label="入库口1" value="INBOUND_PORT_1"></el-option>
          <el-option label="入库口2" value="INBOUND_PORT_2"></el-option>
        </el-select>
      </div>
      <div slot="footer" class="dialog-footer">
        <button class="action-btn primary" @click="submitPushAssembly" :disabled="interfaceBusy || !selectedInboundPort">
          {{ pushAssemblyLoading ? '处理中...' : '确认推送' }}
        </button>
        <button class="action-btn secondary" style="margin-left: 8px;" @click="closePushAssemblyDialog" :disabled="interfaceBusy">取消</button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  checkPalletExists,
  getPalletDetails,
  savePalletDetail,
  deletePalletDetail,
  getPalletInfo,
  getPalletTypeList,
  updatePalletTypeAndAutoSort,
  getAvailablePositionsForLayer,
  callEmptyPalletToStation,
  getAreaOptionsForChange,
  getStationsByArea,
  pushPalletAssemblyToInboundPort
} from '../../../api/haianAutoWarehouse/palletAssembly'

export default {
  name: 'haianPalletAssembly',
  data() {
    return {
      site: this.$store.state.user.site,
      palletCode: '',
      palletScanned: false,
      operationType: 'in',
      currentPalletFamily: '',
      currentPalletType: '',
      currentAutoSort: 'N',
      currentPalletStation: '',
      forceFullPalletOut: false,
      palletTypeDisabled: false,
      autoSortDisabled: false,
      currentWcsAutoSort: '',
      currentMaxLayer: 0,
      positionOptions: [],
      palletTypeOptions: [],
      callEmptyPalletTypeOptions: [],
      detailList: [],
      scanOutList: [],
      detailModalVisible: false,
      scanOutModalVisible: false,
      palletInfo: {
        palletType: '',
        autoSort: 'N',
        locationCode: '',
        area: ''
      },
      scanModalVisible: false,
      scanCode: '',
      scanPosition: '',
      scanLayer: 1,
      scanLayerOptions: [],
      needRefreshOnClose: false,
      positionGrid: [],
      availablePositions: [],
      currentSelectedPosition: '',
      currentMixedMode: false,
      positionGridLoading: false,
      areaOptions: [],
      stationOptions: [],
      callEmptyModalVisible: false,
      callEmptyLoading: false,
      callEmptyForm: {
        areaId: '',
        stationCode: '',
        palletType: ''
      },
      // 推送组盘弹窗状态 - rqrq
      pushAssemblyDialogVisible: false,
      selectedInboundPort: '',
      // 接口锁状态：推送组盘时要禁用页面所有按钮 - rqrq
      palletScanLoading: false,
      palletConfigLoading: false,
      scanRequestLoading: false,
      pushAssemblyLoading: false
    }
  },
  computed: {
    getPositionGridClass() {
      const len = this.positionGrid.length
      if (len === 1) return 'position-grid-1'
      if (len === 2) return 'position-grid-4'
      if (len === 4) return 'position-grid-4'
      return 'position-grid-9'
    },
    displayPositionGrid() {
      const len = this.positionGrid.length
      if (len === 2) {
        const pos1 = this.positionGrid.find((p) => p.position === '1') || { position: '1', count: 0 }
        const pos2 = this.positionGrid.find((p) => p.position === '2') || { position: '2', count: 0 }
        return [
          { ...pos1, isPlaceholder: false },
          { position: '', count: 0, isPlaceholder: true },
          { position: '', count: 0, isPlaceholder: true },
          { ...pos2, isPlaceholder: false }
        ]
      }
      return this.positionGrid.map((p) => ({ ...p, isPlaceholder: false }))
    },
    // 直接组盘规则：area与location_code同时为空时才允许推送 - rqrq
    canPushAssembly() {
      if (!this.palletScanned) {
        return false
      }
      if (!this.detailList || this.detailList.length === 0) {
        return false
      }
      const area = this.palletInfo && this.palletInfo.area ? String(this.palletInfo.area).trim() : ''
      const locationCode = this.palletInfo && this.palletInfo.locationCode ? String(this.palletInfo.locationCode).trim() : ''
      return area === '' && locationCode === ''
    },
    interfaceBusy() {
      return this.palletScanLoading || this.palletConfigLoading || this.scanRequestLoading || this.callEmptyLoading || this.pushAssemblyLoading
    }
  },
  methods: {
    ensureSite() {
      if (!this.site) {
        this.$alert('当前用户缺少site，无法执行海安组盘业务', '提示', { confirmButtonText: '确定' })
        return false
      }
      return true
    },
    handleBack() {
      if (this.interfaceBusy) {
        return
      }
      this.resetPage(false)
      this.$router.back()
    },
    goHome() {
      if (this.interfaceBusy) {
        return
      }
      this.resetPage(false)
      this.$router.push({ path: '/' })
    },
    resetPage(needFocus = true) {
      this.site = this.$store.state.user.site
      this.palletCode = ''
      this.palletScanned = false
      this.operationType = 'in'
      this.currentPalletFamily = ''
      this.currentPalletType = ''
      this.currentAutoSort = 'N'
      this.currentPalletStation = ''
      this.forceFullPalletOut = false
      this.palletTypeDisabled = false
      this.autoSortDisabled = false
      this.currentWcsAutoSort = ''
      this.currentMaxLayer = 0
      this.positionOptions = []
      this.palletTypeOptions = []
      this.callEmptyPalletTypeOptions = []
      this.detailList = []
      this.scanOutList = []
      this.detailModalVisible = false
      this.scanOutModalVisible = false
      this.palletInfo = {
        palletType: '',
        autoSort: 'N',
        locationCode: '',
        area: ''
      }
      this.scanModalVisible = false
      this.scanCode = ''
      this.scanPosition = ''
      this.scanLayer = 1
      this.scanLayerOptions = []
      this.needRefreshOnClose = false
      this.positionGrid = []
      this.availablePositions = []
      this.currentSelectedPosition = ''
      this.currentMixedMode = false
      this.positionGridLoading = false
      this.areaOptions = []
      this.stationOptions = []
      this.callEmptyModalVisible = false
      this.callEmptyLoading = false
      this.callEmptyForm = {
        areaId: '',
        stationCode: '',
        palletType: ''
      }
      this.pushAssemblyDialogVisible = false
      this.selectedInboundPort = ''
      this.palletScanLoading = false
      this.palletConfigLoading = false
      this.scanRequestLoading = false
      this.pushAssemblyLoading = false
      if (needFocus) {
        this.$nextTick(() => {
          if (this.$refs.palletInput) {
            this.$refs.palletInput.focus()
          }
        })
      }
    },
    handlePalletScan() {
      if (!this.ensureSite() || this.interfaceBusy) {
        return
      }
      if (!this.palletCode || !this.palletCode.trim()) {
        this.$alert('请输入栈板编码', '提示', { confirmButtonText: '确定' })
        return
      }
      this.palletScanLoading = true
      checkPalletExists({
        site: this.site,
        palletId: this.palletCode.trim()
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.palletCode = data.palletId
          this.positionOptions = data.positions || []
          this.palletScanned = true
          this.scanOutList = []
          this.scanCode = ''
          this.scanPosition = ''
          this.scanLayer = 1
          this.currentSelectedPosition = ''
          this.loadPalletInfo()
          this.refreshTable()
        } else {
          this.$alert((data && data.msg) || '栈板校验失败', '错误', { confirmButtonText: '确定' })
        }
      }).catch((error) => {
        this.$alert(error.message || '栈板校验失败', '错误', { confirmButtonText: '确定' })
      }).finally(() => {
        this.palletScanLoading = false
      })
    },
    loadPalletInfo() {
      getPalletInfo({
        site: this.site,
        palletId: this.palletCode
      }).then(({ data }) => {
        if (data && data.code === 0) {
          const row = data.row || {}
          this.currentPalletFamily = row.palletFamily || ''
          this.currentPalletType = row.palletType || ''
          this.currentAutoSort = row.autoSort || 'N'
          this.currentPalletStation = row.locationCode || ''
          this.forceFullPalletOut = Number(row.soreType) === 3
          this.palletInfo.palletType = this.currentPalletType
          this.palletInfo.autoSort = this.currentAutoSort
          this.palletInfo.locationCode = row.locationCode || ''
          this.palletInfo.area = row.area || ''
          this.loadPalletTypeList()
        }
      })
    },
    loadPalletTypeList() {
      getPalletTypeList({
        site: this.site,
        palletFamily: this.currentPalletFamily || '',
        active: 'Y'
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.palletTypeOptions = data.rows || []
          const selectedType = this.palletTypeOptions.find((item) => item.palletType === this.currentPalletType)
          this.currentWcsAutoSort = selectedType ? (selectedType.wcsAutoSort || 'N') : ''
          this.currentMaxLayer = selectedType ? Number(selectedType.maxLayer || 0) : 0
          this.updateAutoSortControl()
        }
      })
    },
    loadAllPalletTypeListForCallEmpty() {
      getPalletTypeList({
        site: this.site,
        palletFamily: '',
        active: 'Y'
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.callEmptyPalletTypeOptions = data.rows || []
          const hasSelectedType = this.callEmptyPalletTypeOptions.some((item) => item.palletType === this.callEmptyForm.palletType)
          if (!hasSelectedType) {
            this.callEmptyForm.palletType = ''
          }
        } else {
          this.callEmptyPalletTypeOptions = []
          this.callEmptyForm.palletType = ''
        }
      }).catch(() => {
        this.callEmptyPalletTypeOptions = []
        this.callEmptyForm.palletType = ''
      })
    },
    refreshTable() {
      getPalletDetails({
        site: this.site,
        palletId: this.palletCode,
        position: '',
        layer: null
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.detailList = data.details || []
        } else {
          this.detailList = []
        }
        this.palletTypeDisabled = this.detailList.length > 0
        this.updateAutoSortControl()
      }).catch(() => {
        this.detailList = []
        this.palletTypeDisabled = false
        this.updateAutoSortControl()
      })
    },
    handlePalletTypeChange() {
      const selectedType = this.palletTypeOptions.find((item) => item.palletType === this.currentPalletType)
      this.currentWcsAutoSort = selectedType ? (selectedType.wcsAutoSort || 'N') : ''
      this.currentMaxLayer = selectedType ? Number(selectedType.maxLayer || 0) : 0
      if (this.currentPalletType === 'A0103' || this.currentPalletType === 'A0206') {
        this.forceFullPalletOut = true
      }
      this.updateAutoSortControl()
      this.savePalletTypeConfig()
    },
    handleAutoSortChange() {
      this.savePalletTypeConfig()
    },
    handleForceFullPalletOutChange() {
      this.savePalletTypeConfig()
    },
    updateAutoSortControl() {
      if (this.forceFullPalletOut || this.currentPalletType === 'A0103') {
        this.currentAutoSort = 'N'
        this.autoSortDisabled = true
        return
      }
      if (this.currentWcsAutoSort === 'N') {
        this.currentAutoSort = 'N'
        this.autoSortDisabled = true
        return
      }
      this.autoSortDisabled = this.detailList.length > 0 || this.interfaceBusy
    },
    savePalletTypeConfig() {
      if (this.interfaceBusy) {
        return
      }
      this.palletConfigLoading = true
      updatePalletTypeAndAutoSort({
        site: this.site,
        palletId: this.palletCode,
        palletType: this.currentPalletType,
        autoSort: this.currentAutoSort,
        forceFullPalletOut: this.forceFullPalletOut
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.palletInfo.palletType = this.currentPalletType
          this.palletInfo.autoSort = this.currentAutoSort
          this.$message.success('托盘配置已更新')
        } else {
          this.$alert((data && data.msg) || '托盘配置更新失败', '错误', { confirmButtonText: '确定' })
        }
      }).catch((error) => {
        this.$alert(error.message || '托盘配置更新失败', '错误', { confirmButtonText: '确定' })
      }).finally(() => {
        this.palletConfigLoading = false
      })
    },
    handleCallPallet() {
      if (this.interfaceBusy) {
        return
      }
      this.openCallEmptyModal()
    },
    showScanModal() {
      this.scanModalVisible = true
      this.scanCode = ''
      this.currentSelectedPosition = ''
      this.needRefreshOnClose = false
      if (this.operationType === 'in') {
        this.scanLayer = 1
        this.loadLayerOptions()
      } else {
        this.$nextTick(() => {
          if (this.$refs.scanInput) {
            this.$refs.scanInput.focus()
          }
        })
      }
    },
    showDetailModal() {
      this.detailModalVisible = true
    },
    showScanOutModal() {
      this.scanOutModalVisible = true
    },
    loadLayerOptions() {
      getPalletDetails({
        site: this.site,
        palletId: this.palletCode,
        position: '',
        layer: null
      }).then(({ data }) => {
        if (data && data.code === 0) {
          const details = data.details || []
          let maxExistingLayer = 0
          if (details.length > 0) {
            maxExistingLayer = Math.max(...details.map((d) => d.layer || 0))
          }
          if (this.currentMaxLayer === 0) {
            this.currentMixedMode = false
            this.scanLayerOptions = Array.from({ length: maxExistingLayer + 1 }, (_, i) => i + 1)
          } else {
            this.currentMixedMode = false
            this.scanLayerOptions = Array.from({ length: this.currentMaxLayer }, (_, i) => i + 1)
          }
          this.loadAvailablePositions()
        } else {
          this.$alert((data && data.msg) || '获取栈板信息失败', '错误', { confirmButtonText: '确定' })
        }
      }).catch(() => {
        this.$alert('获取栈板信息失败', '错误', { confirmButtonText: '确定' })
      })
    },
    loadAvailablePositions() {
      this.positionGridLoading = true
      this.availablePositions = []
      getPalletDetails({
        site: this.site,
        palletId: this.palletCode,
        position: '',
        layer: this.scanLayer
      }).then(({ data: detailData }) => {
        const positionCountMap = {}
        if (detailData && detailData.code === 0) {
          const details = detailData.details || []
          details.forEach((detail) => {
            const pos = detail.position
            positionCountMap[pos] = (positionCountMap[pos] || 0) + 1
          })
        }
        return getAvailablePositionsForLayer({
          site: this.site,
          palletId: this.palletCode,
          layer: this.scanLayer
        }).then(({ data }) => {
          if (data && data.code === 0) {
            const result = data.data || {}
            const positions = result.positions || []
            this.availablePositions = result.availablePositions || []
            this.positionGrid = positions.map((position) => ({
              position,
              count: positionCountMap[position] || 0
            }))
          } else {
            this.availablePositions = []
            this.positionGrid = []
            this.$alert((data && data.msg) || '获取位置信息失败', '错误', { confirmButtonText: '确定' })
          }
        })
      }).catch(() => {
        this.availablePositions = []
        this.positionGrid = []
        this.$alert('获取位置信息失败', '错误', { confirmButtonText: '确定' })
      }).finally(() => {
        this.positionGridLoading = false
      })
    },
    handleLayerClick(layer) {
      if (this.scanLayer === layer) {
        return
      }
      this.scanLayer = layer
      this.currentSelectedPosition = ''
      this.loadAvailablePositions()
    },
    handlePositionClick(position) {
      if (this.positionGridLoading) {
        this.$message.warning('位置信息加载中，请稍候')
        return
      }
      if (!this.availablePositions.includes(position)) {
        this.$message.warning('该位置不可用')
        return
      }
      this.currentSelectedPosition = position
      this.scanPosition = position
      this.$nextTick(() => {
        if (this.$refs.scanInput) {
          this.$refs.scanInput.focus()
        }
      })
    },
    moveFocusToScanInput() {
      this.$nextTick(() => {
        if (this.$refs.scanInput) {
          this.$refs.scanInput.focus()
        }
      })
    },
    closeScanModal() {
      this.scanModalVisible = false
      if (this.needRefreshOnClose) {
        this.refreshTable()
        this.needRefreshOnClose = false
      }
    },
    handleLabelScan() {
      if (!this.ensureSite() || this.interfaceBusy) {
        return
      }
      if (!this.scanCode || !this.scanCode.trim()) {
        this.scanCode = ''
        this.$alert('请输入标签编码', '错误', { confirmButtonText: '确定' })
        this.moveFocusToScanInput()
        return
      }
      if (this.operationType === 'in') {
        if (!this.scanPosition) {
          this.scanCode = ''
          this.$alert('请选择位置', '错误', { confirmButtonText: '确定' })
          this.moveFocusToScanInput()
          return
        }
        if (!this.scanLayer) {
          this.scanCode = ''
          this.$alert('请选择层数', '错误', { confirmButtonText: '确定' })
          this.moveFocusToScanInput()
          return
        }
        this.scanRequestLoading = true
        savePalletDetail({
          site: this.site,
          palletId: this.palletCode,
          position: this.scanPosition,
          layer: this.scanLayer,
          serialNo: this.scanCode,
          sortFlag: 0
        }).then(({ data }) => {
          if (data && data.code === 0) {
            this.$message.success('扫进成功')
            this.needRefreshOnClose = true
            this.scanCode = ''
            this.loadLayerOptions()
            this.moveFocusToScanInput()
          } else {
            this.scanCode = ''
            this.$alert((data && data.msg) || '扫进失败', '错误', { confirmButtonText: '确定' })
            this.moveFocusToScanInput()
          }
        }).catch((error) => {
          this.scanCode = ''
          this.$alert(error.message || '扫进失败', '错误', { confirmButtonText: '确定' })
          this.moveFocusToScanInput()
        }).finally(() => {
          this.scanRequestLoading = false
        })
      } else {
        const scanOutItem = this.detailList.find((item) => item.serialNo === this.scanCode)
        this.scanRequestLoading = true
        deletePalletDetail({
          site: this.site,
          palletId: this.palletCode,
          serialNo: this.scanCode
        }).then(({ data }) => {
          if (data && data.code === 0) {
            if (scanOutItem) {
              this.scanOutList.push({
                position: scanOutItem.position,
                layer: scanOutItem.layer,
                serialNo: scanOutItem.serialNo
              })
            }
            this.$message.success('扫出成功')
            this.needRefreshOnClose = true
            this.scanCode = ''
            this.moveFocusToScanInput()
          } else {
            this.scanCode = ''
            this.$alert((data && data.msg) || '扫出失败', '错误', { confirmButtonText: '确定' })
            this.moveFocusToScanInput()
          }
        }).catch((error) => {
          this.scanCode = ''
          this.$alert(error.message || '扫出失败', '错误', { confirmButtonText: '确定' })
          this.moveFocusToScanInput()
        }).finally(() => {
          this.scanRequestLoading = false
        })
      }
    },
    loadAreaOptions() {
      getAreaOptionsForChange({ site: this.site }).then(({ data }) => {
        if (data && data.code === 0) {
          this.areaOptions = data.rows || []
        } else {
          this.areaOptions = []
        }
      }).catch(() => {
        this.areaOptions = []
      })
    },
    openCallEmptyModal() {
      if (!this.ensureSite()) {
        return
      }
      this.callEmptyForm = { areaId: '', stationCode: '', palletType: this.currentPalletType || '' }
      this.stationOptions = []
      this.loadAreaOptions()
      this.loadAllPalletTypeListForCallEmpty()
      this.callEmptyModalVisible = true
    },
    handleAreaChangeForCall() {
      this.callEmptyForm.stationCode = ''
      if (!this.callEmptyForm.areaId) {
        this.stationOptions = []
        return
      }
      getStationsByArea({
        site: this.site,
        areaId: this.callEmptyForm.areaId
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.stationOptions = data.rows || []
        } else {
          this.stationOptions = []
        }
      }).catch(() => {
        this.stationOptions = []
      })
    },
    submitCallEmpty() {
      if (this.interfaceBusy) {
        return
      }
      if (!this.callEmptyForm.areaId || !this.callEmptyForm.stationCode || !this.callEmptyForm.palletType) {
        this.$alert('请完整选择区域、站点和栈板类型', '提示', { confirmButtonText: '确定' })
        return
      }
      this.callEmptyLoading = true
      callEmptyPalletToStation({
        site: this.site,
        // 调用空托盘下发时，targetArea传业务区域ID，由后端映射haian_area.wcs_area_code - rqrq
        areaId: this.callEmptyForm.areaId,
        targetArea: this.callEmptyForm.areaId,
        stationCode: this.callEmptyForm.stationCode,
        palletType: this.callEmptyForm.palletType
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.$message.success('调用空托盘成功')
          this.callEmptyModalVisible = false
        } else {
          this.$alert((data && data.msg) || '调用空托盘失败', '错误', { confirmButtonText: '确定' })
        }
      }).catch((error) => {
        this.$alert(error.message || '调用空托盘失败', '错误', { confirmButtonText: '确定' })
      }).finally(() => {
        this.callEmptyLoading = false
      })
    },
    // 推送组盘前校验：area/location任何一个有值都必须阻断 - rqrq
    openPushAssemblyDialog() {
      if (!this.ensureSite() || this.interfaceBusy) {
        return
      }
      if (!this.palletScanned) {
        this.$alert('请先扫描栈板', '提示', { confirmButtonText: '确定' })
        return
      }
      if (!this.detailList || this.detailList.length === 0) {
        this.$alert('栈板明细为空，请先扫进物料', '提示', { confirmButtonText: '确定' })
        return
      }
      if (!this.canPushAssembly) {
        this.$alert('推送组盘仅允许未绑定站点的栈板，当前栈板area或location_code存在值', '提示', { confirmButtonText: '确定' })
        return
      }
      this.selectedInboundPort = ''
      this.pushAssemblyDialogVisible = true
    },
    closePushAssemblyDialog() {
      if (this.interfaceBusy) {
        return
      }
      this.pushAssemblyDialogVisible = false
      this.selectedInboundPort = ''
    },
    // 推送组盘：确认入库口后调用海安专用后端方法，调用期间保持全页面按钮锁定 - rqrq
    submitPushAssembly() {
      if (!this.selectedInboundPort) {
        this.$alert('请选择入库口', '提示', { confirmButtonText: '确定' })
        return
      }
      this.$confirm('确认推送组盘数据吗？', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.pushAssemblyLoading = true
        pushPalletAssemblyToInboundPort({
          site: this.site,
          palletId: this.palletCode,
          inboundPort: this.selectedInboundPort
        }).then(({ data }) => {
          if (data && data.code === 0) {
            this.$message.success('推送组盘成功')
            this.pushAssemblyDialogVisible = false
            this.resetPage(true)
          } else {
            this.$alert((data && data.msg) || '推送组盘失败', '错误', { confirmButtonText: '确定' })
          }
        }).catch((error) => {
          this.$alert(error.message || '推送组盘失败', '错误', { confirmButtonText: '确定' })
        }).finally(() => {
          this.pushAssemblyLoading = false
        })
      }).catch(() => {
        // 用户取消确认时不清空数据，便于继续核对后再提交 - rqrq
      })
    }
  },
  activated() {
    this.resetPage(true)
  },
  beforeRouteLeave(to, from, next) {
    this.resetPage(false)
    next()
  },
  mounted() {
    this.resetPage(true)
  }
}
</script>

<style scoped>
.header-action-disabled {
  opacity: 0.5;
  pointer-events: none;
}

.detail-table {
  background: white;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #e0e0e0;
}

.table-header,
.table-row {
  display: flex;
  align-items: center;
  padding: 8px;
  border-bottom: 1px solid #e0e0e0;
}

.table-header {
  background: #f5f5f5;
  font-weight: bold;
  font-size: 14px;
}

.col-position {
  flex: 1;
  text-align: center;
}

.col-layer {
  flex: 1;
  text-align: center;
}

.col-serial {
  flex: 4;
  text-align: center;
  word-break: break-all;
}

.empty-row {
  justify-content: center;
  align-items: center;
  padding: 20px;
  border-bottom: none;
}

.empty-hint {
  text-align: center;
  color: #999;
  width: 100%;
}

.scan-modal-content {
  padding: 10px 0;
}

.modal-form {
  margin-bottom: 16px;
}

.dialog-footer {
  text-align: center;
}

.action-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: #ccc !important;
  border-color: #ccc !important;
}

.action-btn.warning {
  background-color: #f59e0b;
  border-color: #f59e0b;
  color: #fff;
}

::v-deep .el-dialog__wrapper {
  z-index: 2000 !important;
}

::v-deep .el-overlay {
  z-index: 2000 !important;
}

::v-deep .el-radio {
  margin-right: 8px !important;
}

::v-deep .el-radio__label {
  font-size: 14px;
}

.layer-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.layer-item {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 50px;
  height: 45px;
  padding: 0 12px;
  background-color: #fff;
  border: 2px solid #dcdfe6;
  border-radius: 6px;
  font-size: 15px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.3s;
  user-select: none;
}

.layer-item:hover {
  border-color: #409eff;
  background-color: #ecf5ff;
}

.layer-item.layer-selected {
  border-color: #409eff;
  background-color: #409eff;
  color: #fff;
}

.position-grid {
  display: grid;
  gap: 10px;
  margin-top: 8px;
  position: relative;
}

.position-grid.position-grid-1 {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}

.position-grid.position-grid-4 {
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-auto-flow: column;
}

.position-grid.position-grid-9 {
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  grid-auto-flow: row;
}

.position-item.position-placeholder {
  background-color: #f0f0f0 !important;
  border: 1px dashed #d0d0d0 !important;
  color: transparent !important;
  cursor: not-allowed !important;
  pointer-events: none !important;
}

.position-grid.position-grid-loading {
  opacity: 0.7;
  pointer-events: none;
}

.position-item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60px;
  background-color: #fff;
  border: 2px solid #dcdfe6;
  border-radius: 6px;
  font-size: 16px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.3s;
  user-select: none;
}

.position-item:hover:not(.position-disabled) {
  border-color: #409eff;
  background-color: #ecf5ff;
}

.position-item.position-selected {
  border-color: #409eff;
  background-color: #409eff;
  color: #fff;
}

.position-item.position-disabled {
  background-color: #f5f7fa;
  color: #c0c4cc;
  cursor: not-allowed;
  opacity: 0.6;
}

.position-item.position-loading {
  background: linear-gradient(90deg, #f5f7fa 25%, #e4e7ed 50%, #f5f7fa 75%);
  background-size: 200% 100%;
  animation: loading 1.5s ease-in-out infinite;
}

@keyframes loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
</style>
