<template>
  <div class="page-container">
    <el-card shadow="hover" class="filter-card">
      <div class="filter-actions">
        <div class="filter-warehouse">
          <span class="filter-label">仓库</span>
          <el-input
            v-model="warehouse"
            placeholder="如 WH01"
            clearable
            @keyup.enter="loadData"
          />
        </div>
        <el-button type="primary" :loading="loading" @click="loadData">查询</el-button>
      </div>
      <el-alert type="info" show-icon :closable="false" class="hint">
        站点为固定工作站列表（ASRS 工作站中排除 A1、A2、A5，含 B1–B4、A3、A4、A6、WH01-3-2）；排队数据来自 Redis；未单独配置上限时使用默认上限。
      </el-alert>
    </el-card>

    <div class="board-toolbar">
      <div class="board-titles">
        <span class="board-title">站点排队</span>
        <span v-if="rows.length" class="board-sub">{{ rows.length }} 个站点</span>
      </div>
      <div class="board-actions">
        <span class="board-hint">点击条目查看任务链详情 · 排队无序（Set）</span>
        <el-button type="primary" size="small" :loading="loading" @click="loadData">刷新</el-button>
      </div>
    </div>

    <div class="board-body" v-loading="loading">
      <el-empty v-if="rows.length === 0 && !loading" description="暂无数据，请确认仓库编码" />
      <div v-else class="station-grid">
        <el-card
          v-for="row in rows"
          :key="row.stationCode"
          class="station-card"
          shadow="hover"
        >
          <template #header>
            <div class="station-card-head">
              <div class="station-card-head__main">
                <span class="station-code">{{ row.stationCode }}</span>
                <el-tag :type="queueStressType(row)" size="small" effect="plain" class="queue-pill">
                  排队 {{ row.queueSize }} / 上限 {{ row.effectiveMaxCapacity }}
                </el-tag>
              </div>
              <el-tooltip v-if="!isMonitorMode" content="修改上限" placement="top">
                <el-button
                  type="primary"
                  link
                  size="small"
                  class="card-edit-btn"
                  :icon="Edit"
                  @click.stop="openEditDialog(row)"
                />
              </el-tooltip>
            </div>
          </template>
          <div class="station-card-body">
            <div class="stat-row">
              <span class="stat-k">已配置上限</span>
              <span v-if="row.configuredMaxCapacity != null" class="stat-v">{{ row.configuredMaxCapacity }}</span>
              <el-tag v-else type="info" size="small">默认</el-tag>
            </div>

            <div class="chains-section">
              <div class="chains-head">
                <span class="chains-title">排队任务链</span>
                <span v-if="row.queuedChainCodes?.length" class="chains-n">{{ row.queuedChainCodes.length }} 条</span>
              </div>
              <div v-if="row.queuedChainCodes?.length" class="chains-scroll">
                <button
                  v-for="c in row.queuedChainCodes"
                  :key="c"
                  type="button"
                  class="chain-row"
                  @click="goChainDetail(c)"
                >
                  <span class="chain-row__code">{{ c }}</span>
                  <span class="chain-row__sep" aria-hidden="true">：</span>
                  <span class="chain-row__containers">{{ chainContainersText(c) }}</span>
                </button>
              </div>
              <div v-else class="chains-empty">无</div>
            </div>
          </div>
        </el-card>
      </div>
    </div>

    <el-dialog v-model="editVisible" title="修改排队上限" width="420px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item label="仓库">
          <el-input :model-value="editForm.warehouse" disabled />
        </el-form-item>
        <el-form-item label="站点">
          <el-input :model-value="editForm.stationCode" disabled />
        </el-form-item>
        <el-form-item label="排队上限">
          <el-input-number v-model="editForm.maxCapacity" :min="0" :max="9999" controls-position="right" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editVisible = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="submitEdit">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
defineOptions({ name: 'StationQueueView' })
import {
  listStationQueues,
  updateStationQueueMax,
  type MachineStationQueueVO,
} from '@/api/stationQueue'
import { getChainDetail, type TaskChainDetailVO } from '@/api/task'
import { Edit } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { computed, onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/user'

const userStore = useUserStore()
const isMonitorMode = computed(() => userStore.isMonitorMode())
const router = useRouter()

const warehouse = ref('WH01')
const rows = ref<MachineStationQueueVO[]>([])
const loading = ref(false)

/** 任务链号 -> 容器串（冒号拼接）；载入中 / 失败为占位标记 */
const chainContainersLabel = ref<Record<string, string>>({})

const editVisible = ref(false)
const editForm = reactive({
  warehouse: '',
  stationCode: '',
  maxCapacity: 3,
})

const saving = ref(false)

function collectContainersFromDetail(d: TaskChainDetailVO): string[] {
  const out: string[] = []
  const push = (v: string | undefined) => {
    const t = v?.trim()
    if (t) out.push(t)
  }
  push(d.sourceContainer)
  for (const task of d.tasks ?? []) {
    push(task.sourceContainer)
  }
  return [...new Set(out)]
}

function chainContainersText(code: string): string {
  const v = chainContainersLabel.value[code]
  if (v === '__loading__') return '容器载入中…'
  if (v === '__error__') return '容器加载失败'
  return v ?? '—'
}

function queueStressType(row: MachineStationQueueVO): 'success' | 'warning' | 'danger' | 'info' {
  const max = row.effectiveMaxCapacity
  const q = row.queueSize
  if (max <= 0) return q > 0 ? 'danger' : 'info'
  if (q >= max) return 'danger'
  if (q / max >= 0.8) return 'warning'
  return 'success'
}

async function loadData() {
  const wh = warehouse.value?.trim()
  if (!wh) {
    ElMessage.warning('请输入仓库编码')
    return
  }
  loading.value = true
  chainContainersLabel.value = {}
  try {
    const res = await listStationQueues(wh)
    rows.value = res.data || []
    const codes = [
      ...new Set(
        rows.value.flatMap((r) => r.queuedChainCodes ?? []).filter((c) => !!c?.trim()),
      ),
    ]
    for (const c of codes) {
      chainContainersLabel.value[c] = '__loading__'
    }
    await Promise.all(
      codes.map(async (code) => {
        try {
          const detailRes = await getChainDetail(code)
          const list = collectContainersFromDetail(detailRes.data)
          chainContainersLabel.value[code] = list.length ? list.join(':') : '—'
        } catch {
          chainContainersLabel.value[code] = '__error__'
        }
      }),
    )
  } catch {
    rows.value = []
    chainContainersLabel.value = {}
  } finally {
    loading.value = false
  }
}

function goChainDetail(code: string) {
  if (!code) return
  router.push(`/task/chain/${encodeURIComponent(code)}`)
}

function openEditDialog(row: MachineStationQueueVO) {
  editForm.warehouse = row.warehouse
  editForm.stationCode = row.stationCode
  editForm.maxCapacity = row.configuredMaxCapacity ?? row.effectiveMaxCapacity
  editVisible.value = true
}

async function submitEdit() {
  saving.value = true
  try {
    await updateStationQueueMax({
      warehouse: editForm.warehouse.trim(),
      stationCode: editForm.stationCode.trim(),
      maxCapacity: editForm.maxCapacity,
    })
    ElMessage.success('已保存')
    editVisible.value = false
    await loadData()
  } catch { /* interceptor */ } finally {
    saving.value = false
  }
}

onMounted(loadData)
</script>

<style scoped>
.page-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.filter-card .hint {
  margin-top: 12px;
}

.filter-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 16px;
}

.filter-warehouse {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 200px;
  flex: 1;
  max-width: 280px;
}

.filter-label {
  font-size: 13px;
  color: var(--el-text-color-regular);
}

.board-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.board-titles {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
}

.board-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.board-sub {
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.board-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
}

.board-hint {
  font-size: 12px;
  color: var(--el-text-color-secondary);
  max-width: min(420px, 100%);
  line-height: 1.4;
}

.board-body {
  min-height: 120px;
}

.station-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
  gap: 16px;
}

.station-card :deep(.el-card__header) {
  padding: 14px 16px;
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.station-card :deep(.el-card__body) {
  padding: 16px;
}

.station-card-head {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 4px;
}

.station-card-head__main {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.station-code {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--el-text-color-primary);
}

.queue-pill {
  flex-shrink: 0;
}

.card-edit-btn {
  flex-shrink: 0;
  margin: -6px -10px -6px 0;
  padding: 4px 6px;
}

.station-card-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.stat-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  font-size: 13px;
}

.stat-k {
  color: var(--el-text-color-secondary);
}

.stat-v {
  font-weight: 500;
  color: var(--el-text-color-primary);
}

.chains-section {
  border-radius: 8px;
  background: var(--el-fill-color-lighter);
  padding: 10px 12px;
}

.chains-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.chains-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--el-text-color-regular);
}

.chains-n {
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.chains-scroll {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  max-height: 240px;
  overflow-x: auto;
  overflow-y: auto;
  padding: 2px;
  margin: 0 -2px;
  scrollbar-gutter: stable;
}

.chain-row {
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0 4px;
  width: max-content;
  max-width: none;
  margin: 0;
  padding: 6px 10px;
  box-sizing: border-box;
  text-align: left;
  font: inherit;
  line-height: 1.45;
  white-space: nowrap;
  color: var(--el-text-color-primary);
  background: var(--el-bg-color);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 8px;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease,
    box-shadow 0.15s ease;
}

.chain-row:hover {
  background: var(--el-fill-color-blank);
  border-color: var(--el-color-primary-light-7);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

.chain-row:active {
  background: var(--el-fill-color-light);
}

.chain-row:focus-visible {
  outline: 2px solid var(--el-color-primary-light-5);
  outline-offset: 1px;
}

.chain-row__code {
  font-size: 13px;
  font-weight: 600;
  color: var(--el-color-primary);
  letter-spacing: 0.02em;
  flex-shrink: 0;
}

.chain-row__sep {
  font-size: 13px;
  color: var(--el-text-color-placeholder);
  flex-shrink: 0;
}

.chain-row__containers {
  font-size: 13px;
  font-weight: 400;
  color: var(--el-text-color-regular);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.chains-empty {
  font-size: 13px;
  color: var(--el-text-color-placeholder);
}

@media (max-width: 640px) {
  .filter-warehouse {
    max-width: none;
  }

  .board-actions {
    width: 100%;
    justify-content: space-between;
  }
}
</style>
