<template>
  <div class="facade-panel">
    <div class="toolbar">
      <el-select v-model="areaId" placeholder="选择库区" style="width: 200px">
        <el-option v-for="a in areas" :key="a.id" :label="`${a.code} ${a.name}`" :value="a.id" />
      </el-select>
      <el-select v-model="depthNo" placeholder="进深" style="width: 120px">
        <el-option v-for="d in depthOptions" :key="d" :label="`进深 ${d}`" :value="d" />
      </el-select>
      <span class="hint">层×列立面（仅 Grid 货位）；点击单元格可编辑</span>
    </div>

    <div v-if="!areaId" class="empty">请选择库区</div>
    <div v-else-if="columns.length === 0" class="empty">该库区暂无网格货位，可先「批量生成网格」</div>
    <div v-else class="facade-scroll">
      <table class="facade-table">
        <thead>
          <tr>
            <th class="corner">层\列</th>
            <th v-for="c in columns" :key="c">{{ c }}</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="lv in levelsDesc" :key="lv">
            <th>{{ lv }}</th>
            <td
              v-for="col in columns"
              :key="`${lv}-${col}`"
              :class="cellClass(cellAt(col, lv))"
              :title="cellTitle(cellAt(col, lv))"
              @click="onCellClick(cellAt(col, lv))"
            >
              <template v-if="cellAt(col, lv)">
                <div class="code">{{ cellAt(col, lv)!.code }}</div>
                <div class="status">{{ statusLabel(cellAt(col, lv)!.status) }}</div>
              </template>
              <span v-else class="miss">—</span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import type { WarehouseArea, Storage } from '@/types/wms'
import { STORAGE_STATUSES, labelOf } from './wmsOptions'

const props = defineProps<{
  areas: WarehouseArea[]
  storages: Storage[]
}>()

const emit = defineEmits<{
  edit: [Storage]
}>()

const areaId = ref('')
const depthNo = ref(1)

watch(
  () => props.areas,
  (list) => {
    if (!areaId.value && list.length) areaId.value = list[0].id
  },
  { immediate: true }
)

const gridBins = computed(() =>
  props.storages.filter(
    (s) => s.areaId === areaId.value && s.locationKind === 'Grid' && s.depthNo === depthNo.value
  )
)

const depthOptions = computed(() => {
  const set = new Set(
    props.storages
      .filter((s) => s.areaId === areaId.value && s.locationKind === 'Grid')
      .map((s) => s.depthNo || 1)
  )
  const arr = [...set].sort((a, b) => a - b)
  return arr.length ? arr : [1]
})

watch(depthOptions, (opts) => {
  if (!opts.includes(depthNo.value)) depthNo.value = opts[0]
})

const columns = computed(() => {
  const set = new Set(gridBins.value.map((s) => s.columnNo || 0).filter((n) => n > 0))
  return [...set].sort((a, b) => a - b)
})

const levelsDesc = computed(() => {
  const set = new Set(gridBins.value.map((s) => s.levelNo || 1))
  return [...set].sort((a, b) => b - a)
})

const cellMap = computed(() => {
  const map = new Map<string, Storage>()
  for (const s of gridBins.value) {
    map.set(`${s.columnNo}:${s.levelNo}`, s)
  }
  return map
})

function cellAt(col: number, level: number) {
  return cellMap.value.get(`${col}:${level}`)
}

function statusLabel(status: string) {
  return labelOf(STORAGE_STATUSES, status)
}

function cellClass(s?: Storage) {
  if (!s) return 'cell empty-slot'
  if (!s.enabled || s.status === 'Disabled') return 'cell disabled'
  if (s.status === 'FullContainer') return 'cell full'
  if (s.status === 'EmptyContainer') return 'cell empty-c'
  return 'cell vacant'
}

function cellTitle(s?: Storage) {
  if (!s) return '无货位'
  return `${s.code} · ${s.name}\n列${s.columnNo} 层${s.levelNo} 深${s.depthNo}\n${statusLabel(s.status)}`
}

function onCellClick(s?: Storage) {
  if (s) emit('edit', s)
}
</script>

<style scoped>
.facade-panel { min-height: 280px; }
.toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
.hint { font-size: 12px; color: var(--mg-text-muted, #888); }
.empty { padding: 48px; text-align: center; color: var(--mg-text-muted, #888); }
.facade-scroll { overflow: auto; max-height: 520px; border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 6px; }
.facade-table { border-collapse: collapse; font-size: 12px; min-width: 100%; }
.facade-table th,
.facade-table td { border: 1px solid rgba(0, 0, 0, 0.08); padding: 6px 8px; text-align: center; min-width: 72px; }
.facade-table thead th,
.facade-table tbody th { background: rgba(0, 0, 0, 0.03); font-weight: 600; position: sticky; }
.facade-table thead th { top: 0; z-index: 2; }
.facade-table tbody th { left: 0; z-index: 1; }
.corner { left: 0; z-index: 3 !important; }
.cell { cursor: pointer; transition: background 0.15s; }
.cell:hover { outline: 2px solid rgba(64, 158, 255, 0.45); outline-offset: -2px; }
.cell .code { font-weight: 600; line-height: 1.2; }
.cell .status { margin-top: 2px; opacity: 0.75; font-size: 11px; }
.miss { color: #bbb; }
.vacant { background: #e8f5e9; }
.empty-c { background: #fff8e1; }
.full { background: #ffebee; }
.disabled { background: #eceff1; color: #90a4ae; cursor: default; }
.empty-slot { background: #fafafa; cursor: default; }
</style>
