<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import { useRoute } from 'vue-router'

import AdminStatusTag from '@/components/admin/AdminStatusTag.vue'
import { showConfirm, showError, showSuccess } from '@/lib/feedback'
import {
  closeAdminTask,
  confirmAdminTaskAssistedRole,
  completeAdminTaskManualDispatch,
  redeemAdminTaskAssisted,
  fetchAdminTaskScreenshot,
  fetchAdminTaskDetail,
  markAdminTaskManualReview,
  regenerateAdminTaskClaimLink,
  releaseAdminTaskInventoryBinding,
  retryAdminTask,
} from '@/services/admin'
import type { AdminTaskActionResponse, AdminTaskDetail } from '@/types/admin'
import { hasAdminRole } from '@/utils/admin-auth'
import { formatTaskEventType } from '@/utils/admin-display'
import { formatAdminDateTime } from '@/utils/admin-time'

const route = useRoute()
const loading = ref(true)
const actionLoading = ref(false)
const errorMessage = ref('')
const detail = ref<AdminTaskDetail | null>(null)
const lastClaimUrl = ref('')
const screenshotPreviewUrl = ref('')
const manualDispatchForm = reactive({
  deliveryReference: '',
  deliveredCredential: '',
  resultMessage: '',
})
const canOperateTasks = computed(() => hasAdminRole('operator'))
const canViewSensitiveTaskData = computed(() => Boolean(detail.value?.operations.canViewSensitiveTaskData))
const claimUrl = computed(() => lastClaimUrl.value || detail.value?.claimToken?.claimUrl || '')
const screenshotSectionTitle = computed(() => {
  if (detail.value?.task.status === 'redeemed') {
    return '结果截图'
  }

  return detail.value?.review.required ? '客服复核截图' : '结果截图'
})

async function loadDetail() {
  loading.value = true
  errorMessage.value = ''

  try {
    const response = await fetchAdminTaskDetail(String(route.params.taskId || ''))
    detail.value = response.data
    syncManualDispatchForm(response.data)
    await loadScreenshotPreview(response.data)
  } catch (error) {
    errorMessage.value = error instanceof Error ? error.message : '读取任务详情失败'
  } finally {
    loading.value = false
  }
}

async function runAction(
  action: () => Promise<{ data: AdminTaskActionResponse }>,
  successMessage: string,
  confirmText: string,
) {
  try {
    await showConfirm(confirmText, '确认操作', {
      type: 'warning',
      confirmButtonText: '继续执行',
      cancelButtonText: '取消',
    })
  } catch {
    return
  }

  actionLoading.value = true

  try {
    const response = await action()
    if (response.data.claimUrl) {
      lastClaimUrl.value = response.data.claimUrl
    }
    showSuccess(successMessage)
    await loadDetail()
  } catch (error) {
    showError(error instanceof Error ? error.message : '操作失败')
  } finally {
    actionLoading.value = false
  }
}

async function loadScreenshotPreview(taskDetail: AdminTaskDetail) {
  clearScreenshotPreview()

  if (!taskDetail.screenshotUrl) {
    return
  }

  try {
    const blob = await fetchAdminTaskScreenshot(taskDetail.task.taskId)
    screenshotPreviewUrl.value = URL.createObjectURL(blob)
  } catch {
    screenshotPreviewUrl.value = ''
  }
}

function clearScreenshotPreview() {
  if (screenshotPreviewUrl.value) {
    URL.revokeObjectURL(screenshotPreviewUrl.value)
    screenshotPreviewUrl.value = ''
  }
}

function syncManualDispatchForm(taskDetail: AdminTaskDetail) {
  manualDispatchForm.deliveryReference = taskDetail.manualDispatch?.deliveryReference || ''
  manualDispatchForm.deliveredCredential = taskDetail.manualDispatch?.deliveredCredential || ''
  manualDispatchForm.resultMessage = taskDetail.manualDispatch?.resultMessage || taskDetail.task.resultMessage || ''
}

async function submitManualDispatch(outcome: 'delivered' | 'failed') {
  if (!detail.value) {
    return
  }

  const actionLabel = outcome === 'failed' ? '标记履约失败' : '标记已完成履约'
  const confirmText = outcome === 'failed'
    ? `确认把任务 ${detail.value.task.taskNo} 回写为人工履约失败吗？这会把任务直接收口并保留失败原因。`
    : `确认把任务 ${detail.value.task.taskNo} 回写为人工履约完成吗？这会把任务直接标记为已发放。`

  await runAction(
    () => completeAdminTaskManualDispatch(detail.value!.task.taskId, {
      outcome,
      resultMessage: manualDispatchForm.resultMessage,
      deliveryReference: manualDispatchForm.deliveryReference,
      deliveredCredential: manualDispatchForm.deliveredCredential,
    }),
    actionLabel,
    confirmText,
  )
}

function formatTaskEventPayload(payload: Record<string, unknown>) {
  const parts = [
    payload.outcome ? `结果 ${payload.outcome}` : '',
    payload.resultCode ? `代码 ${payload.resultCode}` : '',
    payload.resultMessage ? `说明 ${payload.resultMessage}` : '',
    payload.codeMasked ? `凭据 ${payload.codeMasked}` : '',
    payload.previousCodeMasked ? `旧码 ${payload.previousCodeMasked}` : '',
    payload.nextCodeMasked ? `新码 ${payload.nextCodeMasked}` : '',
    payload.inventoryItemId ? `库存项 #${payload.inventoryItemId}` : '',
    payload.previousInventoryItemId ? `旧库存 #${payload.previousInventoryItemId}` : '',
    payload.nextInventoryItemId ? `新库存 #${payload.nextInventoryItemId}` : '',
    payload.previousOutcome ? `切换原因 ${formatRedeemOutcomeLabel(String(payload.previousOutcome || ''))}` : '',
    payload.deliveryReference ? `单号 ${payload.deliveryReference}` : '',
    payload.platformOrderId ? `平台单 ${payload.platformOrderId}` : '',
    payload.trigger ? `触发 ${formatAutoDeliveryTrigger(String(payload.trigger || ''))}` : '',
    payload.reason ? `原因 ${payload.reason}` : '',
    payload.responseStatus ? `HTTP ${payload.responseStatus}` : '',
    payload.requestId ? `请求 ${payload.requestId}` : '',
    payload.errorMessage ? `错误 ${payload.errorMessage}` : '',
  ].filter(Boolean)

  if (parts.length > 0) {
    return parts.join(' · ')
  }

  return JSON.stringify(payload || {})
}

function formatRedeemOutcomeLabel(value: string) {
  const normalized = String(value || '').trim()

  switch (normalized) {
    case 'success':
      return '兑换成功'
    case 'code_used':
      return '兑换码已使用'
    case 'code_invalid':
      return '兑换码错误'
    case 'captcha_rejected':
      return '验证码错误'
    case 'failed':
      return '兑换失败'
    default:
      return normalized || '-'
  }
}

function formatRedeemResolutionStatus(value: string) {
  return value === 'success' ? '已完成' : value === 'failed' ? '失败收口' : (value || '-')
}

function formatAutoDeliveryTrigger(value: string) {
  const normalized = String(value || '').trim()

  switch (normalized) {
    case 'claim_redeemed':
      return '用户兑换完成后触发'
    case 'manual_dispatch_completed':
      return '人工履约完成后触发'
    case 'task_delivered':
      return '任务交付完成后触发'
    default:
      return normalized || '-'
  }
}

function formatAutoDeliveryReason(value: string) {
  const normalized = String(value || '').trim()

  switch (normalized) {
    case 'waiting_other_tasks':
      return '订单下仍有任务未完成交付'
    case 'already_sent':
      return '该订单已经执行过自动发货'
    case 'auto_delivery_disabled':
      return '自动发货开关已关闭'
    case 'missing_config':
      return '缺少 Agiso 自动发货配置'
    case 'request_failed':
      return 'Agiso 接口返回失败'
    case 'request_error':
      return '请求 Agiso 接口时发生异常'
    case 'delivery_not_confirmed':
      return '接口返回成功，但订单状态未确认进入已发货'
    case 'task_not_delivered':
      return '当前任务尚未进入已交付状态'
    case 'not_supported':
      return '当前订单不支持 Agiso 咸鱼自动发货'
    default:
      return normalized || '-'
  }
}

function resolveTaskAutoDeliveryStatus(taskDetail: AdminTaskDetail) {
  if (taskDetail.task.agisoAutoDelivery?.status) {
    return taskDetail.task.agisoAutoDelivery.status
  }

  return taskDetail.task.deliveryStatus === 'delivered' ? 'pending' : 'waiting'
}

function resolveTaskAutoDeliverySummary(taskDetail: AdminTaskDetail) {
  const autoDelivery = taskDetail.task.agisoAutoDelivery

  if (autoDelivery?.errorMessage) {
    return autoDelivery.errorMessage
  }

  if (autoDelivery?.reason) {
    return formatAutoDeliveryReason(autoDelivery.reason)
  }

  return taskDetail.task.deliveryStatus === 'delivered'
    ? '当前任务已交付，等待订单下其他任务完成后统一自动发货'
    : '当前任务尚未完成交付，暂不会触发自动发货'
}

onMounted(loadDetail)
onBeforeUnmount(clearScreenshotPreview)
</script>

<template>
  <section class="admin-panel">
    <header class="panel-header">
      <div>
        <h1>任务详情</h1>
        <p>查看任务全量信息并执行人工操作。</p>
      </div>
    </header>

    <p v-if="errorMessage" class="error-copy">{{ errorMessage }}</p>
    <div v-if="loading" class="empty-block">任务详情加载中</div>

    <template v-else-if="detail">
      <section class="info-card">
        <h2>{{ detail.task.taskNo }}</h2>
        <p>状态：<AdminStatusTag :status="detail.task.status" /> · 订单：{{ detail.order?.platformOrderId || '-' }}</p>
        <p>执行器：{{ detail.task.executorKey || '-' }} · 履约：<AdminStatusTag :status="detail.task.deliveryStatus" /></p>
        <p>系统绑定：<AdminStatusTag :status="detail.task.systemBindingStatus" /> · 完整绑定：<AdminStatusTag :status="detail.task.userBindingStatus" /></p>
        <p>角色：{{ detail.task.roleName || '-' }} / {{ detail.task.roleId || '-' }}</p>
        <p>最后错误：{{ detail.task.lastError || '-' }}</p>
        <p v-if="claimUrl">
          领取链接：
          <a class="claim-link" :href="claimUrl" target="_blank" rel="noreferrer">{{ claimUrl }}</a>
        </p>
      </section>

      <section class="action-row">
        <el-button
          :disabled="!detail.operations.canRetry"
          :loading="actionLoading"
          round
          type="primary"
          @click="runAction(() => retryAdminTask(detail!.task.taskId), '任务已重试', `确认重试任务 ${detail!.task.taskNo} 吗？`)"
        >
          重试任务
        </el-button>
        <el-button
          v-if="detail.operations.canRegenerateClaimLink"
          :disabled="!detail.operations.canRegenerateClaimLink"
          :loading="actionLoading"
          round
          @click="runAction(() => regenerateAdminTaskClaimLink(detail!.task.taskId), '领取链接已重新生成', `确认重新生成任务 ${detail!.task.taskNo} 的领取链接吗？旧链接会失效。`)"
        >
          重发链接
        </el-button>
        <el-button
          v-if="detail.operations.canSupportConfirmRole"
          :loading="actionLoading"
          round
          type="warning"
          @click="runAction(
            () => confirmAdminTaskAssistedRole(detail!.task.taskId),
            '角色已确认',
            `确认以客服身份锁定任务 ${detail!.task.taskNo} 当前识别到的角色信息吗？`
          )"
        >
          客服确认角色
        </el-button>
        <el-button
          v-if="detail.operations.canSupportRedeem"
          :loading="actionLoading"
          round
          type="success"
          @click="runAction(
            () => redeemAdminTaskAssisted(detail!.task.taskId),
            '兑换任务已启动',
            `确认开始执行任务 ${detail!.task.taskNo} 的自动兑换吗？`
          )"
        >
          客服开始兑换
        </el-button>
        <el-button
          v-if="canOperateTasks"
          :disabled="!detail.operations.canMarkManualReview"
          :loading="actionLoading"
          round
          @click="runAction(() => markAdminTaskManualReview(detail!.task.taskId), '任务已转人工处理', `确认将任务 ${detail!.task.taskNo} 转为人工处理吗？`)"
        >
          转人工
        </el-button>
        <el-button
          v-if="canOperateTasks && detail.operations.canCompleteManualDispatch"
          :loading="actionLoading"
          round
          type="success"
          @click="submitManualDispatch('delivered')"
        >
          人工完成
        </el-button>
        <el-button
          v-if="canOperateTasks && detail.operations.canCompleteManualDispatch"
          :loading="actionLoading"
          round
          type="danger"
          plain
          @click="submitManualDispatch('failed')"
        >
          履约失败
        </el-button>
        <el-button
          v-if="canOperateTasks"
          :disabled="!detail.operations.canClose"
          :loading="actionLoading"
          round
          type="danger"
          @click="runAction(() => closeAdminTask(detail!.task.taskId), '任务已关闭', `确认关闭任务 ${detail!.task.taskNo} 吗？关闭后不会自动继续推进。`)"
        >
          关闭任务
        </el-button>
      </section>

	      <section class="table-card">
	        <h3>任务信息</h3>
        <table class="data-table">
          <tbody>
            <tr><th>商品</th><td>{{ detail.orderItem?.skuName || '-' }}</td></tr>
            <tr><th>SKU</th><td>{{ detail.orderItem?.skuCode || '-' }}</td></tr>
            <tr><th>任务执行器</th><td>{{ detail.task.executorKey || '-' }}</td></tr>
            <tr><th>履约状态</th><td><AdminStatusTag :status="detail.task.deliveryStatus || ''" /></td></tr>
            <tr><th>结果代码</th><td>{{ detail.task.resultCode || '-' }}</td></tr>
            <tr><th>结果说明</th><td>{{ detail.task.resultMessage || '-' }}</td></tr>
            <tr v-if="canViewSensitiveTaskData"><th>库存凭据</th><td>{{ detail.inventory?.displayValue || '-' }}</td></tr>
            <tr v-if="canViewSensitiveTaskData"><th>凭据类型</th><td>{{ detail.inventory?.credentialType || '-' }}</td></tr>
            <tr v-if="canViewSensitiveTaskData"><th>库存状态</th><td><AdminStatusTag :status="detail.inventory?.status || ''" /></td></tr>
            <tr v-if="canViewSensitiveTaskData"><th>Claim Token</th><td>{{ detail.claimToken?.token || '-' }}</td></tr>
            <tr v-else><th>库存 / Token</th><td>客服账号不可查看库存凭据与原始领取 Token</td></tr>
            <tr><th>Token 状态</th><td><AdminStatusTag :status="detail.claimToken?.status || ''" /></td></tr>
            <tr><th>Token 过期</th><td>{{ formatAdminDateTime(detail.claimToken?.expiredAt) }}</td></tr>
            <tr>
              <th>领取链接</th>
              <td>
                <a v-if="claimUrl" class="claim-link" :href="claimUrl" target="_blank" rel="noreferrer">{{ claimUrl }}</a>
                <span v-else>-</span>
              </td>
            </tr>
            <tr><th>浏览器会话</th><td>{{ detail.task.browserSessionId || '-' }}</td></tr>
            <tr><th>用户打开链接</th><td>{{ formatAdminDateTime(detail.task.claimedAt) }}</td></tr>
            <tr><th>用户提交绑定</th><td>{{ formatAdminDateTime(detail.task.roleConfirmedAt) }}</td></tr>
            <tr><th>完整绑定成功</th><td>{{ formatAdminDateTime(detail.task.redeemedAt) }}</td></tr>
            <tr><th>截图路径</th><td>{{ detail.task.screenshotPath || '-' }}</td></tr>
          </tbody>
        </table>
	      </section>

      <section
        v-if="detail.order?.provider === 'agiso' && detail.order?.platform === 'xianyu'"
        class="table-card"
      >
        <h3>咸鱼自动发货</h3>
        <p class="section-copy">这里展示这条任务最近一次触发咸鱼自动发货的状态、原因和接口回执摘要。</p>

        <div class="redeem-summary-grid">
          <article class="redeem-summary-card">
            <span>当前状态</span>
            <div class="auto-delivery-tag-line">
              <AdminStatusTag :status="resolveTaskAutoDeliveryStatus(detail)" />
            </div>
          </article>
          <article class="redeem-summary-card">
            <span>触发来源</span>
            <strong>{{ formatAutoDeliveryTrigger(detail.task.agisoAutoDelivery?.trigger || '') }}</strong>
          </article>
          <article class="redeem-summary-card">
            <span>最近执行</span>
            <strong>{{ formatAdminDateTime(detail.task.agisoAutoDelivery?.updatedAt) }}</strong>
          </article>
          <article class="redeem-summary-card">
            <span>接口回执</span>
            <strong>
              {{ detail.task.agisoAutoDelivery?.requestId || (detail.task.agisoAutoDelivery?.responseStatus ? `HTTP ${detail.task.agisoAutoDelivery.responseStatus}` : '-') }}
            </strong>
          </article>
        </div>

        <div class="auto-delivery-note">
          <p>{{ resolveTaskAutoDeliverySummary(detail) }}</p>
          <p v-if="detail.task.agisoAutoDelivery?.reason">原因：{{ formatAutoDeliveryReason(detail.task.agisoAutoDelivery.reason) }}</p>
          <p v-if="detail.task.agisoAutoDelivery?.responseStatus">HTTP：{{ detail.task.agisoAutoDelivery.responseStatus }}</p>
          <p v-if="detail.task.agisoAutoDelivery?.requestId">请求 ID：{{ detail.task.agisoAutoDelivery.requestId }}</p>
        </div>
      </section>

	      <section v-if="detail.redeemResolution" class="table-card">
        <h3>兑换重试链路</h3>
        <p class="section-copy">这里记录自动兑换时每次使用过的 CDK、判定结果，以及是否切换到了新的同类型凭据。</p>

        <div class="redeem-summary-grid">
          <article class="redeem-summary-card">
            <span>处理结果</span>
            <strong>{{ formatRedeemResolutionStatus(detail.redeemResolution.status) }}</strong>
          </article>
          <article class="redeem-summary-card">
            <span>任务收口状态</span>
            <strong>{{ detail.redeemResolution.taskStatus || detail.task.status || '-' }}</strong>
          </article>
          <article class="redeem-summary-card">
            <span>更换新码次数</span>
            <strong>{{ detail.redeemResolution.replacementCount }}</strong>
          </article>
          <article class="redeem-summary-card">
            <span>完成时间</span>
            <strong>{{ formatAdminDateTime(detail.redeemResolution.finishedAt) }}</strong>
          </article>
        </div>

        <div v-if="detail.redeemResolution.attempts.length > 0" class="redeem-attempts">
          <article
            v-for="attempt in detail.redeemResolution.attempts"
            :key="`${attempt.attempt}-${attempt.inventoryItemId || 'na'}`"
            class="redeem-attempt-card"
          >
            <div class="redeem-attempt-head">
              <strong>第 {{ attempt.attempt }} 次尝试</strong>
              <span class="redeem-outcome">{{ formatRedeemOutcomeLabel(attempt.outcome) }}</span>
            </div>
            <div class="redeem-attempt-grid">
              <div>
                <span>库存项</span>
                <strong>{{ attempt.inventoryItemId ? `#${attempt.inventoryItemId}` : '-' }}</strong>
              </div>
              <div>
                <span>凭据</span>
                <strong>{{ attempt.codeMasked || '-' }}</strong>
              </div>
              <div>
                <span>类型</span>
                <strong>{{ attempt.credentialType || '-' }}</strong>
              </div>
              <div>
                <span>结果码</span>
                <strong>{{ attempt.resultCode || '-' }}</strong>
              </div>
            </div>
            <p class="redeem-attempt-copy">{{ attempt.resultMessage || '-' }}</p>
          </article>
        </div>
      </section>

      <section class="table-card">
        <h3>库存绑定</h3>
        <p class="section-copy">这里展示任务当前和历史绑定过的库存项，便于核对多库存任务的真实履约轨迹。</p>
        <table class="data-table">
          <thead>
            <tr>
              <th>绑定</th>
              <th>角色</th>
              <th>库存项</th>
              <th>状态</th>
              <th>凭据内容</th>
              <th>时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-if="detail.inventoryBindings.length === 0">
              <td colspan="7" class="table-empty">当前任务还没有库存绑定记录</td>
            </tr>
            <tr v-for="binding in detail.inventoryBindings" :key="binding.bindingId">
              <td>
                <div>#{{ binding.bindingId }}</div>
                <div v-if="binding.isPrimary" class="binding-primary">主库存项</div>
              </td>
              <td>
                <div>{{ binding.roleKey || '-' }}</div>
                <div class="binding-meta">数量 {{ binding.quantity }}</div>
              </td>
              <td>
                <div>ID {{ binding.inventoryItemId }}</div>
                <div>{{ binding.skuCode || '-' }}</div>
                <div class="binding-meta">{{ binding.credentialType || '-' }} · {{ binding.batchNo || '无批次' }}</div>
              </td>
              <td>
                <div class="status-stack">
                  <AdminStatusTag :status="binding.bindingStatus" />
                  <AdminStatusTag :status="binding.inventoryStatus" />
                </div>
                <div v-if="binding.invalidReason" class="binding-meta">
                  {{ binding.inventoryStatus === 'invalid' ? '作废原因' : binding.inventoryStatus === 'consumed' ? '消耗原因' : '处理原因' }}：{{ binding.invalidReason }}
                </div>
              </td>
              <td>{{ canViewSensitiveTaskData ? (binding.displayValue || '-') : '客服不可见' }}</td>
              <td>
                <div>绑定 {{ formatAdminDateTime(binding.createdAt) }}</div>
                <div class="binding-meta">消费 {{ formatAdminDateTime(binding.consumedAt) }}</div>
                <div class="binding-meta">释放 {{ formatAdminDateTime(binding.releasedAt) }}</div>
              </td>
              <td>
                <el-button
                  v-if="hasAdminRole('admin') && binding.canRelease"
                  :loading="actionLoading"
                  link
                  @click="runAction(
                    () => releaseAdminTaskInventoryBinding(detail!.task.taskId, binding.bindingId),
                    '库存绑定已释放',
                    `确认释放绑定 #${binding.bindingId} 对应的库存项 ${binding.displayValue || binding.inventoryItemId} 吗？`
                  )"
                >
                  释放绑定
                </el-button>
                <span v-else class="binding-meta">-</span>
              </td>
            </tr>
          </tbody>
        </table>
      </section>

      <section v-if="detail.task.executorKey === 'manual_dispatch'" class="table-card">
        <h3>人工履约回写</h3>
        <div class="manual-grid">
          <label class="field-block">
            <span>外部流水 / 单号</span>
            <el-input
              v-model="manualDispatchForm.deliveryReference"
              :disabled="!canOperateTasks"
              maxlength="120"
              placeholder="例如快递单号、平台消息回执号"
            />
          </label>
          <label class="field-block">
            <span>已交付内容</span>
            <el-input
              v-model="manualDispatchForm.deliveredCredential"
              :disabled="!canOperateTasks"
              maxlength="500"
              placeholder="可填写人工发送的卡密、链接或关键信息"
              type="textarea"
              :rows="3"
            />
          </label>
          <label class="field-block">
            <span>处理备注</span>
            <el-input
              v-model="manualDispatchForm.resultMessage"
              :disabled="!canOperateTasks"
              maxlength="500"
              placeholder="说明实际履约结果，失败时建议写清原因"
              type="textarea"
              :rows="4"
            />
          </label>
        </div>
        <p class="manual-hint">回写后会直接更新任务终态，不再走旧式领取链接流程。</p>
        <div v-if="detail.manualDispatch" class="manual-summary">
          <p>最近回写：<AdminStatusTag :status="detail.manualDispatch.outcome || detail.task.deliveryStatus" /> · {{ formatAdminDateTime(detail.manualDispatch.completedAt) }}</p>
          <p>处理人：{{ detail.manualDispatch.completedBy?.username || '-' }} / {{ detail.manualDispatch.completedBy?.role || '-' }}</p>
          <p>流水号：{{ detail.manualDispatch.deliveryReference || '-' }}</p>
          <p>交付内容：{{ detail.manualDispatch.deliveredCredential || '-' }}</p>
          <p>备注：{{ detail.manualDispatch.resultMessage || '-' }}</p>
        </div>
      </section>

      <section v-if="detail.events.length > 0" class="table-card">
        <h3>任务事件</h3>
        <table class="data-table">
          <tbody>
            <tr v-for="event in detail.events" :key="event.eventId">
              <th>{{ formatTaskEventType(event.eventType) }}</th>
              <td>
                <div class="event-copy">{{ formatTaskEventPayload(event.payload) }}</div>
                <div class="event-time">{{ formatAdminDateTime(event.createdAt) }}</div>
              </td>
            </tr>
          </tbody>
        </table>
      </section>

      <section v-if="detail.screenshotUrl" class="table-card">
        <h3>{{ screenshotSectionTitle }}</h3>
        <p v-if="!screenshotPreviewUrl" class="screenshot-empty">截图加载中或当前不可读取。</p>
        <a v-else class="screenshot-link" :href="screenshotPreviewUrl" target="_blank" rel="noreferrer">打开原图</a>
        <img v-if="screenshotPreviewUrl" class="screenshot-preview" :src="screenshotPreviewUrl" :alt="screenshotSectionTitle" />
      </section>
    </template>
  </section>
</template>

<style scoped>
.admin-panel { display: grid; gap: 16px; }
.panel-header h1 { margin: 0; color: #1d3555; }
.panel-header p { margin: 8px 0 0; color: #64748b; }
.claim-link { color: #175cd3; text-decoration: none; word-break: break-all; }
.info-card,.table-card,.empty-block,.error-copy {
  padding: 18px; border-radius: 20px; background: rgba(255,255,255,.94); border: 1px solid rgba(86,108,138,.1);
}
.error-copy { color: #b42318; }
.action-row { display: flex; flex-wrap: wrap; gap: 12px; }
.table-card h3 { margin: 0 0 12px; color: #1d3555; }
.section-copy { margin: 0 0 12px; color: #64748b; }
.auto-delivery-tag-line { display: flex; align-items: center; }
.auto-delivery-note {
  margin-top: 14px;
  padding: 14px 16px;
  border-radius: 16px;
  background: rgba(248,250,252,.92);
  border: 1px solid rgba(86,108,138,.08);
}
.auto-delivery-note p { margin: 0 0 8px; color: #334155; }
.auto-delivery-note p:last-child { margin-bottom: 0; }
.data-table { width: 100%; border-collapse: collapse; }
.data-table th,.data-table td { padding: 12px 10px; text-align: left; border-bottom: 1px solid rgba(86,108,138,.08); }
.data-table th { width: 160px; color: #64748b; }
.status-stack { display: flex; flex-wrap: wrap; gap: 8px; }
.redeem-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
.redeem-summary-card,
.redeem-attempt-card {
  padding: 14px 16px;
  border-radius: 16px;
  border: 1px solid rgba(86,108,138,.1);
  background: rgba(248,250,252,.92);
}
.redeem-summary-card span,
.redeem-attempt-grid span {
  display: block;
  color: #64748b;
  font-size: 12px;
  margin-bottom: 6px;
}
.redeem-summary-card strong,
.redeem-attempt-grid strong {
  color: #1d3555;
}
.redeem-attempts {
  display: grid;
  gap: 12px;
}
.redeem-attempt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.redeem-outcome {
  color: #175cd3;
  font-size: 13px;
  font-weight: 600;
}
.redeem-attempt-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-top: 12px;
}
.redeem-attempt-copy {
  margin: 12px 0 0;
  color: #334155;
  line-height: 1.6;
}
.table-empty { text-align: center; color: #64748b; }
.binding-primary { margin-top: 4px; color: #0f766e; font-size: 12px; font-weight: 600; }
.binding-meta { margin-top: 4px; color: #64748b; font-size: 12px; }
.manual-grid { display: grid; gap: 14px; }
.field-block { display: grid; gap: 8px; color: #1d3555; font-weight: 600; }
.manual-hint { margin: 14px 0 0; color: #64748b; }
.manual-summary { margin-top: 16px; padding: 14px; border-radius: 16px; background: rgba(248,250,252,.9); }
.manual-summary p { margin: 0 0 8px; color: #334155; }
.manual-summary p:last-child { margin-bottom: 0; }
.event-copy { color: #334155; }
.event-time { margin-top: 6px; color: #64748b; font-size: 12px; }
.screenshot-link { display: inline-block; margin-bottom: 12px; color: #175cd3; text-decoration: none; }
.screenshot-empty { margin: 0 0 12px; color: #64748b; }
.screenshot-preview {
  display: block;
  width: min(100%, 720px);
  border-radius: 18px;
  border: 1px solid rgba(86,108,138,.12);
  box-shadow: 0 20px 48px rgba(15,23,42,.08);
}
</style>
