<template>
  <div class="mission-list-panel">
    <div class="toolbar">
      <el-input
        v-model="search"
        size="small"
        clearable
        placeholder="搜索任务 ID / 站点 / 车辆"
        class="search"
      />
      <el-checkbox v-model="showFinished" size="small" @change="emitRefresh">
        含已完成
      </el-checkbox>
      <el-checkbox v-model="showAborted" size="small" @change="emitRefresh">
        含取消/异常
      </el-checkbox>
    </div>

    <el-table
      :data="filteredRows"
      size="small"
      stripe
      highlight-current-row
      :row-class-name="rowClassName"
      height="100%"
      class="delivery-table"
      table-layout="fixed"
      @row-click="onRowClick"
      @row-contextmenu="onRowContextMenu"
    >
      <el-table-column prop="id" label="ID" width="72" align="center" show-overflow-tooltip />
      <el-table-column label="起点" show-overflow-tooltip>
        <template #default="{ row }">
          <span class="cell-ellipsis" :title="row.srcLabel">{{ shortSite(row.srcLabel) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="终点" show-overflow-tooltip>
        <template #default="{ row }">
          <span class="cell-ellipsis" :title="row.dstLabel">{{ shortSite(row.dstLabel) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="状态" width="52" align="center">
        <template #default="{ row }">
          <span
            class="status-pill"
            :class="`status-pill--${statusTagType(row.statusCode)}`"
            :title="row.status"
          >
            {{ shortStatus(row.status) }}
          </span>
        </template>
      </el-table-column>
      <el-table-column label="车辆" width="56" show-overflow-tooltip>
        <template #default="{ row }">
          <span v-if="row.carName" class="cell-ellipsis" :title="row.carName">
            {{ shortCar(row.carName) }}
          </span>
          <span v-else class="muted">—</span>
        </template>
      </el-table-column>
    </el-table>

    <div v-if="!filteredRows.length" class="empty muted">暂无搬运任务</div>

    <div
      v-show="ctxVisible"
      class="ctx-menu"
      :style="{ left: `${ctxX}px`, top: `${ctxY}px` }"
      @click.stop
    >
      <button
        type="button"
        class="ctx-item"
        :disabled="!canCancel(ctxRow)"
        @click="runAction('cancel')"
      >
        取消任务
      </button>
      <button type="button" class="ctx-item" @click="runAction('resend')">
        重发任务
      </button>
      <button
        type="button"
        class="ctx-item"
        :disabled="!canForceComplete(ctxRow)"
        @click="runAction('force-complete')"
      >
        强制完成
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { DeliveryTask, DeliveryAction } from '@/types/delivery'
import {
  cancelDelivery,
  forceCompleteDelivery,
  resendDelivery
} from '@/api/delivery'

const props = defineProps<{
  deliveries: DeliveryTask[]
  selectedId?: string | null
  loading?: boolean
}>()

const emit = defineEmits<{
  select: [task: DeliveryTask]
  refresh: [opts: { includeFinished: boolean; includeAborted: boolean }]
  actionDone: []
}>()

const search = ref('')
const showFinished = ref(true)
const showAborted = ref(true)

const ctxVisible = ref(false)
const ctxX = ref(0)
const ctxY = ref(0)
const ctxRow = ref<DeliveryTask | null>(null)

const filteredRows = computed(() => {
  const q = search.value.trim().toLowerCase()
  const tokens = q ? q.split(/\s+/).filter(Boolean) : []
  return props.deliveries.filter((row) => {
    if (!tokens.length) return true
    const hay = [
      String(row.id),
      row.srcLabel,
      row.dstLabel,
      row.status,
      row.carName ?? '',
      row.missionName
    ]
      .join(' ')
      .toLowerCase()
    return tokens.every((t) => hay.includes(t))
  })
})

type TagType = 'success' | 'warning' | 'danger' | 'info' | 'primary'

/** 站点列：优先显示名称段，完整内容靠 tooltip */
function shortSite(label: string, maxLen = 9): string {
  const idx = label.indexOf('-')
  const name = idx >= 0 ? label.slice(idx + 1) : label
  if (name.length <= maxLen) return name
  return `${name.slice(0, maxLen)}…`
}

function shortStatus(status: string): string {
  const map: Record<string, string> = {
    已下发: '待发',
    执行中: '执行',
    已完成: '完成',
    已取消: '取消',
    强制结束: '强结',
    任务异常: '异常'
  }
  return map[status] ?? (status.length > 4 ? `${status.slice(0, 3)}…` : status)
}

function shortCar(name: string, maxLen = 6): string {
  if (name.length <= maxLen) return name
  return `${name.slice(0, maxLen)}…`
}

function statusTagType(code: string): TagType {
  switch (code) {
    case 'Fetching':
    case 'Putting':
      return 'success'
    case 'Waiting':
      return 'primary'
    case 'Finished':
      return 'info'
    case 'Canceled':
    case 'Terminated':
      return 'warning'
    case 'Error':
      return 'danger'
    default:
      return 'info'
  }
}

function rowClassName({ row }: { row: DeliveryTask }) {
  const classes: string[] = []
  if (row.id === props.selectedId) classes.push('is-selected-row')
  if (row.overdue) classes.push('is-overdue-row')
  return classes.join(' ')
}

function isTerminal(code: string) {
  return ['Finished', 'Canceled', 'Terminated', 'Error'].includes(code)
}

function canCancel(row: DeliveryTask | null) {
  return row != null && !isTerminal(row.statusCode)
}

function canForceComplete(row: DeliveryTask | null) {
  return row != null && !isTerminal(row.statusCode)
}

function emitRefresh() {
  emit('refresh', {
    includeFinished: showFinished.value,
    includeAborted: showAborted.value
  })
}

function onRowClick(row: DeliveryTask) {
  hideCtx()
  emit('select', row)
}

function onRowContextMenu(row: DeliveryTask, _col: unknown, e: MouseEvent) {
  e.preventDefault()
  ctxRow.value = row
  ctxX.value = e.clientX
  ctxY.value = e.clientY
  ctxVisible.value = true
}

function hideCtx() {
  ctxVisible.value = false
  ctxRow.value = null
}

const actionLabels: Record<DeliveryAction, string> = {
  cancel: '取消任务',
  resend: '重发任务',
  'force-complete': '强制完成',
  pause: '暂停任务',
  resume: '恢复任务',
  'change-car': '更换车辆'
}

async function runAction(action: DeliveryAction) {
  const row = ctxRow.value
  hideCtx()
  if (!row) return

  if (action === 'cancel' && !canCancel(row)) return
  if (action === 'force-complete' && !canForceComplete(row)) return

  try {
    await ElMessageBox.confirm(
      `确定对任务 #${row.id}（${row.srcLabel} → ${row.dstLabel}）执行「${actionLabels[action]}」？`,
      '确认操作',
      { type: 'warning', confirmButtonText: '确定', cancelButtonText: '取消' }
    )
  } catch {
    return
  }

  try {
    if (action === 'cancel') await cancelDelivery(row.id)
    else if (action === 'resend') await resendDelivery(row.id)
    else await forceCompleteDelivery(row.id)
    ElMessage.success(`${actionLabels[action]} 已提交`)
    emit('actionDone')
  } catch (err) {
    ElMessage.error(`${actionLabels[action]} 失败：${(err as Error).message}`)
  }
}

function onDocClick() {
  hideCtx()
}

onMounted(() => document.addEventListener('click', onDocClick))
onUnmounted(() => document.removeEventListener('click', onDocClick))
</script>

<style scoped>
.mission-list-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  height: 100%;
  position: relative;
}

.toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  flex-wrap: wrap;
}
.toolbar .search {
  flex: 1;
  min-width: 120px;
}

.delivery-table {
  flex: 1;
  min-height: 0;
  width: 100%;
  overflow: hidden;
}

.mission-list-panel :deep(.delivery-table .el-table__inner-wrapper),
.mission-list-panel :deep(.delivery-table .el-table__header-wrapper),
.mission-list-panel :deep(.delivery-table .el-table__body-wrapper) {
  overflow-x: hidden !important;
}
.mission-list-panel :deep(.delivery-table table) {
  table-layout: fixed;
  width: 100% !important;
}
.mission-list-panel :deep(.delivery-table th.el-table__cell),
.mission-list-panel :deep(.delivery-table td.el-table__cell) {
  padding: 3px 2px;
}
.mission-list-panel :deep(.delivery-table .cell) {
  padding: 0 2px;
  font-size: 11px;
  line-height: 1.35;
}
.mission-list-panel :deep(.delivery-table th .cell) {
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.cell-ellipsis {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.status-pill {
  display: inline-block;
  max-width: 100%;
  padding: 0 3px;
  border-radius: 3px;
  font-size: 10px;
  line-height: 16px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.status-pill--success { color: var(--mg-status-success); }
.status-pill--primary { color: var(--mg-status-info); }
.status-pill--warning { color: var(--mg-status-warning); }
.status-pill--danger { color: var(--mg-status-danger); }
.status-pill--info { color: var(--mg-text-muted); }

.mission-list-panel :deep(.el-table),
.mission-list-panel :deep(.el-table th.el-table__cell),
.mission-list-panel :deep(.el-table .cell) {
  color: var(--mg-text-light);
  background: transparent;
}
.mission-list-panel :deep(.el-table tr) {
  background: rgba(255, 255, 255, 0.03);
}
.mission-list-panel :deep(.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell) {
  background: rgba(255, 255, 255, 0.06);
}
.mission-list-panel :deep(.is-selected-row) td {
  background: rgba(109, 40, 217, 0.35) !important;
}
.mission-list-panel :deep(.is-overdue-row) td {
  color: var(--mg-status-danger) !important;
}

.empty {
  text-align: center;
  padding: 16px 0;
  font-size: 12px;
}
.muted {
  color: var(--mg-text-dim);
}

.ctx-menu {
  position: fixed;
  z-index: 9000;
  min-width: 128px;
  padding: 4px 0;
  background: #fffefd;
  border: 1px solid rgba(40, 33, 58, 0.1);
  border-radius: 12px;
  box-shadow:
    0 1px 2px rgba(40, 33, 58, 0.06),
    0 12px 28px rgba(54, 35, 78, 0.14);
}
.ctx-item {
  display: block;
  width: 100%;
  padding: 8px 14px;
  border: none;
  background: transparent;
  color: #28213a;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.ctx-item:hover:not(:disabled) {
  background: rgba(var(--mg-primary-rgb, 117, 67, 232), 0.1);
  color: var(--mg-primary, #7543e8);
}
.ctx-item:disabled {
  color: #b8b0c8;
  cursor: not-allowed;
}
</style>
