<script setup lang="ts">
import {
  ClockCircleOutlined,
  CopyOutlined,
  DesktopOutlined,
  ExportOutlined,
  ReloadOutlined,
  RetweetOutlined,
  SearchOutlined,
} from '@ant-design/icons-vue'
import type { DesktopTaskInfo, JsonValue, TenantPublishTaskListResponse } from '@geo/shared-types'
import { useQuery } from '@tanstack/vue-query'
import type { TableColumnsType } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'

import { publishTasksApi, tenantAccountsApi } from '@/lib/api'
import { copyTextToClipboard } from '@/lib/clipboard'
import { formatDateTime } from '@/lib/display'
import { formatError } from '@/lib/errors'
import { resolvePlatformLogoUrl } from '@/lib/publish-account-cards'
import { getPublishPlatformMeta, normalizePublishPlatformId } from '@/lib/publish-platforms'
import { useCompanyStore } from '@/stores/company'

const PAGE_SIZE = 10
const INLINE_ERROR_HEAD_CHARS = 52
const INLINE_ERROR_TAIL_CHARS = 10
const ACTIVE_PUBLISH_TASK_POLL_INTERVAL_MS = 5_000
const DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE =
  '懂车帝平台返回异常，请打开懂车帝后台查看并处理平台提示，确认账号状态后再重试。'

type PublishTaskStatus = DesktopTaskInfo['status']

interface PublishTaskItem {
  id: string
  title: string
  articleId: number | null
  platform: string
  platformName: string
  platformShortName: string
  platformAccent: string
  platformLogoUrl: string | null
  accountId: string
  accountName: string
  platformUid: string
  status: PublishTaskStatus
  statusLabel: string
  statusColor: string
  summary: string
  attempts: number
  leaseExpiresAt: string | null
  createdAt: string
  updatedAt: string
  externalUrl: string | null
  workbenchUrl: string
  publishType: string | null
  errorMessage: string | null
  complianceBlockedRecordId: number | null
  complianceBlockedAt: string | null
  canOpenWorkbench: boolean
}

function isPlainRecord(value: unknown): value is Record<string, JsonValue> {
  return typeof value === 'object' && value !== null && !Array.isArray(value)
}

function extractNumber(value: JsonValue | null | undefined): number | null {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return value
  }
  if (typeof value === 'string' && /^\d+$/.test(value.trim())) {
    return Number.parseInt(value.trim(), 10)
  }
  return null
}

function extractString(value: JsonValue | string | null | undefined): string | null {
  if (typeof value !== 'string') {
    return null
  }
  const trimmed = value.trim()
  return trimmed ? trimmed : null
}

function extractStringId(value: JsonValue | null | undefined): string | null {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return String(Math.trunc(value))
  }
  return extractString(value)
}

function normalizePublishTaskStatus(status: PublishTaskStatus): PublishTaskStatus {
  return status === 'unknown' ? 'failed' : status
}

function isPendingStatus(status: PublishTaskStatus): boolean {
  return status === 'queued' || status === 'in_progress'
}

function hasActivePublishingTask(page: TenantPublishTaskListResponse | undefined): boolean {
  return Boolean(page?.items.some((task) => normalizePublishTaskStatus(task.status) === 'in_progress'))
}

function normalizeTaskErrorMessage(messageText: string | null, platform?: string | null): string | null {
  const normalized = extractString(messageText)
  if (!normalized) {
    return null
  }
  if (normalized.includes('scaffold-only') || normalized.includes('requires later reconcile')) {
    return '当前平台的桌面发布适配器未实现，任务已按失败处理。'
  }
  if (normalized.includes('adapter is not implemented for this platform')) {
    return '当前平台的桌面发布适配器未实现，任务已按失败处理。'
  }
  if (
    platform === 'dongchedi' &&
    (/\bserver[\s_-]*exception\b/i.test(normalized) ||
      /\bdongchedi_platform_exception\b/i.test(normalized))
  ) {
    return DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE
  }
  return normalized
}

function complianceLevelLabel(level: string | null): string {
  const normalized = level?.trim().toLowerCase()
  switch (normalized) {
    case 'block':
      return '阻断'
    case 'high':
      return '高风险'
    case 'medium':
      return '中风险'
    case 'info':
      return '提示'
    default:
      return '风险'
  }
}

function summarizeComplianceBlockedReason(raw: string | null): string | null {
  const normalized = extractString(raw)
  if (!normalized) {
    return null
  }

  try {
    const parsed = JSON.parse(normalized) as unknown
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
      return normalized
    }
    const record = parsed as Record<string, unknown>
    const manualStatus =
      typeof record.manual_review_status === 'string' ? record.manual_review_status : ''
    if (manualStatus === 'pending') {
      return '文章版本正在等待运营人工审阅，旧定时任务已停止派发。'
    }
    if (manualStatus === 'rejected') {
      return '文章版本已被运营驳回，请修改文章后重新发布。'
    }

    const hitCount = typeof record.hit_count === 'number' ? record.hit_count : null
    const highestLevel =
      typeof record.highest_level === 'string' ? complianceLevelLabel(record.highest_level) : '风险'
    const violations = Array.isArray(record.violations) ? record.violations : []
    const matchedTerms = violations
      .map((item) => {
        if (!item || typeof item !== 'object' || Array.isArray(item)) {
          return null
        }
        const violation = item as Record<string, unknown>
        return typeof violation.matched_text === 'string' ? violation.matched_text.trim() : null
      })
      .filter((item): item is string => Boolean(item))
      .slice(0, 3)

    const hitPart =
      hitCount !== null && hitCount > 0
        ? `命中 ${hitCount} 条${highestLevel}规则`
        : `命中${highestLevel}规则`
    return matchedTerms.length > 0
      ? `${hitPart}：${matchedTerms.join('、')}`
      : `${hitPart}，请修改文章后重新发布。`
  } catch {
    return normalized === 'compliance_blocked' ? null : normalized
  }
}

function inlineErrorPreview(messageText: string): string {
  const compact = messageText.replace(/\s+/g, ' ').trim()
  const maxLength = INLINE_ERROR_HEAD_CHARS + INLINE_ERROR_TAIL_CHARS + 3
  if (compact.length <= maxLength) {
    return compact
  }
  return `${compact.slice(0, INLINE_ERROR_HEAD_CHARS)}...${compact.slice(-INLINE_ERROR_TAIL_CHARS)}`
}

function summaryForTask(
  status: PublishTaskStatus,
  publishType: string | null = null,
  fallbackReason: string | null = null,
): string {
  if (status === 'aborted' && fallbackReason === 'compliance_blocked') {
    return '定时发布前的合规重检拦截了本次任务，请修改文章后重新发布。'
  }
  switch (status) {
    case 'queued':
      return '任务已进入队列，待桌面端继续执行。'
    case 'in_progress':
      return '当前正在由桌面端执行发送，请避免重复触发。'
    case 'succeeded':
      return publishType === 'draft'
        ? '文章已保存到草稿箱，需在平台后台完成发表。'
        : '文章已成功发送到目标平台。'
    case 'failed':
      return '本次发送失败，请检查账号状态或平台提示后重新创建发布。'
    case 'aborted':
      return '任务已被取消，请检查原因后重新创建发布。'
    case 'unknown':
    default:
      return '发送结果异常，已按失败处理，请检查平台侧结果后重新创建发布。'
  }
}

function statusMetaForTask(
  status: PublishTaskStatus,
  publishType: string | null,
  complianceBlockedRecordId: number | null,
): { label: string; color: string } {
  if (status === 'aborted' && complianceBlockedRecordId !== null) {
    return { label: '合规阻断', color: 'error' }
  }
  if (status === 'succeeded' && publishType === 'draft') {
    return { label: '已存草稿', color: 'warning' }
  }
  switch (status) {
    case 'queued':
      return { label: '等待发布', color: 'processing' }
    case 'in_progress':
      return { label: '正在发布', color: 'processing' }
    case 'succeeded':
      return { label: '发送成功', color: 'success' }
    case 'failed':
    case 'unknown':
      return { label: '发送失败', color: 'error' }
    case 'aborted':
      return { label: '已取消', color: 'default' }
    default:
      return { label: status, color: 'default' }
  }
}

function buildSohuArticleUrl(
  task: DesktopTaskInfo,
  result: Record<string, JsonValue>,
): string | null {
  if (task.platform !== 'sohuhao' || extractString(result.publish_type) === 'draft') {
    return null
  }

  const articleId = extractStringId(result.external_article_id)
  const accountUid = accountMap.value.get(task.target_account_id)?.platform_uid?.trim() ?? ''
  if (!articleId || !accountUid) {
    return null
  }

  return `https://www.sohu.com/a/${encodeURIComponent(articleId)}_${encodeURIComponent(accountUid)}`
}

function buildWangyihaoArticleUrl(
  task: DesktopTaskInfo,
  result: Record<string, JsonValue>,
): string | null {
  if (task.platform !== 'wangyihao' || extractString(result.publish_type) === 'draft') {
    return null
  }

  const articleId = extractStringId(result.external_article_id)
  if (!articleId) {
    return null
  }

  return `https://www.163.com/dy/article/${encodeURIComponent(articleId)}.html`
}

function isSafeHttpUrl(url: string | null): url is string {
  if (!url) {
    return false
  }
  try {
    const parsed = new URL(url)
    return parsed.protocol === 'http:' || parsed.protocol === 'https:'
  } catch {
    return false
  }
}

function buildDesktopWorkbenchUrl(record: {
  accountId: string
  platform: string
  platformUid: string
  accountName: string
}): string {
  const params = new URLSearchParams({
    action: 'open-publish-account-console',
    account_id: record.accountId,
    platform: record.platform,
    platform_uid: record.platformUid,
    display_name: record.accountName,
  })
  return `shengxintui://desktop/workbench?${params.toString()}`
}

const { t } = useI18n()
const companyStore = useCompanyStore()
const page = ref(1)
const searchTitle = ref('')
const appliedTitle = ref('')
const copiedErrorTaskId = ref<string | null>(null)
const retryingTaskId = ref<string | null>(null)
const manualRefreshing = ref(false)

const accountsQuery = useQuery({
  queryKey: ['tenant', 'desktop-accounts', 'publish-management'],
  queryFn: () => tenantAccountsApi.list(),
})

const tasksQuery = useQuery({
  queryKey: computed(() => [
    'tenant',
    'publish-tasks',
    companyStore.currentBrandId,
    { page: page.value, page_size: PAGE_SIZE, title: appliedTitle.value },
  ]),
  enabled: computed(() => Boolean(companyStore.currentBrandId)),
  queryFn: () =>
    publishTasksApi.list({
      page: page.value,
      page_size: PAGE_SIZE,
      title: appliedTitle.value || undefined,
    }),
  refetchInterval: (query) => {
    const data = query.state.data as TenantPublishTaskListResponse | undefined
    return hasActivePublishingTask(data) ? ACTIVE_PUBLISH_TASK_POLL_INTERVAL_MS : false
  },
  refetchIntervalInBackground: false,
})

const loading = computed(() => tasksQuery.isPending.value || accountsQuery.isPending.value)
const refreshing = computed(() => manualRefreshing.value)
const taskPage = computed(() => tasksQuery.data.value)
const pendingCount = computed(() => taskPage.value?.pending_count ?? 0)
const historyTotal = computed(() => taskPage.value?.history_total ?? 0)
const totalCount = computed(() => taskPage.value?.total ?? 0)

const accountMap = computed(() => {
  return new Map((accountsQuery.data.value ?? []).map((account) => [account.id, account]))
})

const publishTasks = computed<PublishTaskItem[]>(() =>
  (taskPage.value?.items ?? []).map((task) => {
    const status = normalizePublishTaskStatus(task.status)
    const payload = task.payload ?? {}
    const result = task.result ?? {}
    const taskError = task.error ?? {}
    const platformId = normalizePublishPlatformId(task.platform)
    const platformMeta = getPublishPlatformMeta(platformId)
    const account = accountMap.value.get(task.target_account_id)
    const publishType = extractString(result.publish_type)
    const complianceBlockedRecordId =
      task.compliance_blocked_record_id ??
      extractNumber(taskError.record_id) ??
      extractNumber(taskError.check_record_id)
    const complianceBlockedReason = summarizeComplianceBlockedReason(
      task.compliance_blocked_reason ?? extractString(taskError.detail),
    )
    const fallbackReason =
      task.publish_job_status === 'blocked_by_compliance'
        ? 'compliance_blocked'
        : extractString(result.fallback_reason)
    const nestedContentRef = isPlainRecord(payload.content_ref) ? payload.content_ref : null
    const articleId =
      extractNumber(payload.article_id) ??
      extractNumber(nestedContentRef?.article_id ?? nestedContentRef?.id)
    const accountName = account?.display_name || '待同步账号'
    const platformUid = account?.platform_uid ?? ''
    const statusMeta = statusMetaForTask(status, publishType, complianceBlockedRecordId)
    const externalUrl =
      publishType === 'draft'
        ? null
        : (extractString(result.external_article_url) ??
          extractString(result.externalArticleUrl) ??
          buildWangyihaoArticleUrl(task, result) ??
          buildSohuArticleUrl(task, result) ??
          extractString(result.external_manage_url) ??
          extractString(result.externalManageUrl))

    return {
      id: task.id,
      title: extractString(payload.title) ?? `发布任务 · ${platformMeta.name}`,
      articleId,
      platform: platformId,
      platformName: platformMeta.name,
      platformShortName: platformMeta.shortName,
      platformAccent: platformMeta.accent,
      platformLogoUrl: resolvePlatformLogoUrl(platformId),
      accountId: task.target_account_id,
      accountName,
      platformUid,
      status,
      statusLabel: statusMeta.label,
      statusColor: statusMeta.color,
      summary: summaryForTask(status, publishType, fallbackReason),
      attempts: task.attempts,
      leaseExpiresAt: task.lease_expires_at,
      createdAt: task.created_at,
      updatedAt: task.updated_at,
      externalUrl: isSafeHttpUrl(externalUrl) ? externalUrl : null,
      workbenchUrl: buildDesktopWorkbenchUrl({
        accountId: task.target_account_id,
        platform: platformId,
        platformUid,
        accountName,
      }),
      publishType,
      errorMessage: normalizeTaskErrorMessage(
        complianceBlockedReason ??
          extractString(taskError.message) ??
          extractString(taskError.detail) ??
          extractString(taskError.code),
        platformId,
      ),
      complianceBlockedRecordId,
      complianceBlockedAt: task.compliance_blocked_at ?? null,
      canOpenWorkbench: Boolean(task.target_account_id),
    }
  }),
)

const columns = computed<TableColumnsType<PublishTaskItem>>(() => [
  { title: '发文标题', key: 'title', dataIndex: 'title', width: 280, ellipsis: true },
  { title: '账号 / 平台', key: 'account', dataIndex: 'account', width: 190 },
  { title: '状态', key: 'status', dataIndex: 'status', width: 110 },
  { title: '任务信息', key: 'meta', dataIndex: 'meta', width: 320 },
  { title: '时间', key: 'time', dataIndex: 'time', width: 170 },
  { title: '操作', key: 'actions', align: 'right', width: 150, fixed: 'right' },
])

watch(searchTitle, (value) => {
  if (!value.trim() && appliedTitle.value) {
    appliedTitle.value = ''
    page.value = 1
  }
})

async function refresh(): Promise<void> {
  if (manualRefreshing.value) {
    return
  }

  manualRefreshing.value = true
  try {
    await Promise.all([tasksQuery.refetch(), accountsQuery.refetch()])
  } finally {
    manualRefreshing.value = false
  }
}

function applySearch(): void {
  page.value = 1
  appliedTitle.value = searchTitle.value.trim()
}

function handlePageChange(nextPage: number): void {
  page.value = nextPage
}

function rowClassName(record: PublishTaskItem): string {
  return isPendingStatus(record.status) ? 'publish-management-row--pending' : ''
}

function canRetryTask(record: PublishTaskItem): boolean {
  return record.status === 'failed' || record.status === 'aborted' || record.status === 'unknown'
}

async function retryTask(record: PublishTaskItem): Promise<void> {
  retryingTaskId.value = record.id
  try {
    const result = await publishTasksApi.retry(record.id)
    const created = result.created_task_ids.length
    const existing = result.existing_task_ids.length
    if (created > 0) {
      message.success(created === 1 ? '已重新创建发布任务' : `已重新创建 ${created} 个发布任务`)
    } else if (existing > 0) {
      if (record.status === 'unknown') {
        message.warning('原任务结果未知且已有发布记录，可能已成功，请先核实平台侧结果。')
      } else {
        message.info('发布任务已存在，无需重复创建')
      }
    } else {
      message.success('已提交重试请求')
    }
    await tasksQuery.refetch()
  } catch (error) {
    message.error(formatError(error))
  } finally {
    retryingTaskId.value = null
  }
}

async function copyErrorMessage(record: PublishTaskItem): Promise<void> {
  if (!record.errorMessage) {
    return
  }

  try {
    await copyTextToClipboard(record.errorMessage)
    copiedErrorTaskId.value = record.id
    message.success('错误详情已复制')
    window.setTimeout(() => {
      if (copiedErrorTaskId.value === record.id) {
        copiedErrorTaskId.value = null
      }
    }, 1500)
  } catch (error) {
    message.error(formatError(error))
  }
}
</script>

<template>
  <div class="publish-management-view">
    <section class="publish-management-view__top-card">
      <div class="publish-management-view__header">
        <div class="publish-management-view__header-title">
          <h2>{{ t('route.publishManagement.title') }}</h2>
          <p>{{ t('route.publishManagement.description') }}</p>
        </div>
        <div class="publish-management-view__header-actions">
          <a-button :loading="refreshing" @click="refresh">
            <template #icon><ReloadOutlined /></template>
            {{ t('common.refresh') }}
          </a-button>
        </div>
      </div>

      <div class="publish-management-view__summary">
        <div class="summary-chip">
          <span>等待发布</span>
          <strong :class="{ 'summary-chip__value--accent': pendingCount > 0 }">
            {{ pendingCount }}
          </strong>
        </div>
        <div class="summary-chip">
          <span>已发送</span>
          <strong>{{ historyTotal }}</strong>
        </div>
        <div class="summary-chip">
          <span>历史总数</span>
          <strong>{{ totalCount }}</strong>
        </div>
      </div>
    </section>

    <section class="publish-management-view__table-card">
      <div class="publish-management-view__toolbar">
        <div>
          <p class="eyebrow">Publish Queue</p>
          <h3>待发布与已发送记录</h3>
        </div>
        <div class="publish-management-view__filters">
          <a-input
            v-model:value="searchTitle"
            allow-clear
            placeholder="搜索发文标题"
            class="publish-management-view__search"
            @pressEnter="applySearch"
          >
            <template #prefix>
              <SearchOutlined />
            </template>
          </a-input>
          <a-button type="primary" @click="applySearch">{{ t('common.search') }}</a-button>
        </div>
      </div>

      <a-table
        row-key="id"
        class="publish-management-table"
        :columns="columns"
        :data-source="publishTasks"
        :pagination="false"
        :loading="loading"
        :scroll="{ x: 1220 }"
        :row-class-name="rowClassName"
        :locale="{ emptyText: '暂无匹配的发文任务' }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'title'">
            <div class="publish-cell-stack">
              <a-tooltip :title="record.title" placement="topLeft">
                <span class="publish-cell-title">{{ record.title }}</span>
              </a-tooltip>
              <span class="publish-cell-sub">
                <template v-if="record.articleId">文章 #{{ record.articleId }}</template>
                <template v-else>未关联文章</template>
              </span>
            </div>
          </template>

          <template v-else-if="column.key === 'account'">
            <div class="publish-account-cell">
              <span class="platform-avatar" :style="{ color: record.platformAccent }">
                <img
                  v-if="record.platformLogoUrl"
                  :src="record.platformLogoUrl"
                  :alt="record.platformName"
                />
                <template v-else>{{ record.platformShortName }}</template>
              </span>
              <div class="publish-cell-stack">
                <span class="publish-cell-title publish-cell-title--compact">
                  {{ record.accountName }}
                </span>
                <span class="publish-cell-sub">{{ record.platformName }}</span>
              </div>
            </div>
          </template>

          <template v-else-if="column.key === 'status'">
            <a-tag :color="record.statusColor">{{ record.statusLabel }}</a-tag>
          </template>

          <template v-else-if="column.key === 'meta'">
            <div class="publish-cell-stack publish-meta-cell">
              <span v-if="record.errorMessage" class="publish-error-row">
                <a-popover placement="topLeft" overlay-class-name="publish-error-popover">
                  <template #content>
                    <div class="publish-error-panel" @click.stop>
                      <div class="publish-error-panel__title">发布错误</div>
                      <pre>{{ record.errorMessage }}</pre>
                      <button
                        type="button"
                        class="publish-error-panel__copy"
                        @click.stop="copyErrorMessage(record)"
                      >
                        <CopyOutlined />
                        <span>
                          {{ copiedErrorTaskId === record.id ? '已复制' : '复制错误详情' }}
                        </span>
                      </button>
                    </div>
                  </template>
                  <span class="publish-error-text">
                    {{ inlineErrorPreview(record.errorMessage) }}
                  </span>
                </a-popover>
              </span>
              <span v-else class="publish-cell-sub publish-cell-sub--strong">
                {{ record.summary }}
              </span>
              <span class="publish-meta-footer">
                <span class="attempt-chip">尝试 {{ record.attempts }} 次</span>
                <template v-if="record.complianceBlockedRecordId">
                  <span class="meta-divider">·</span>
                  <span>合规记录 #{{ record.complianceBlockedRecordId }}</span>
                </template>
                <template v-if="record.complianceBlockedAt">
                  <span class="meta-divider">·</span>
                  <span>{{ formatDateTime(record.complianceBlockedAt) }} 拦截</span>
                </template>
                <template v-if="record.leaseExpiresAt">
                  <span class="meta-divider">·</span>
                  <span>租约至 {{ formatDateTime(record.leaseExpiresAt, 'HH:mm') }}</span>
                </template>
              </span>
            </div>
          </template>

          <template v-else-if="column.key === 'time'">
            <a-tooltip
              :title="`创建 ${formatDateTime(record.createdAt)} · 更新 ${formatDateTime(record.updatedAt)}`"
              placement="topLeft"
            >
              <div class="publish-cell-stack">
                <span class="publish-cell-title publish-cell-title--compact">
                  {{ formatDateTime(record.updatedAt) }}
                </span>
                <span class="publish-cell-sub">创建 {{ formatDateTime(record.createdAt) }}</span>
              </div>
            </a-tooltip>
          </template>

          <template v-else-if="column.key === 'actions'">
            <div class="publish-actions">
              <a-tooltip :title="record.externalUrl ? '打开外链' : '无外链'" placement="top">
                <span class="publish-action-tooltip-wrap">
                  <a-button
                    type="text"
                    class="publish-action-btn"
                    :disabled="!record.externalUrl"
                    :href="record.externalUrl || undefined"
                    :target="record.externalUrl ? '_blank' : undefined"
                    :rel="record.externalUrl ? 'noopener noreferrer' : undefined"
                    :aria-label="
                      record.externalUrl ? `打开外链：${record.title}` : `无外链：${record.title}`
                    "
                  >
                    <template #icon><ExportOutlined /></template>
                  </a-button>
                </span>
              </a-tooltip>
              <a-tooltip
                :title="`打开 ${record.accountName} 的${record.platformName}工作台`"
                placement="top"
              >
                <a-button
                  type="text"
                  class="publish-action-btn"
                  :href="record.workbenchUrl"
                  :disabled="!record.canOpenWorkbench"
                  :aria-label="`打开 ${record.accountName} 的${record.platformName}工作台`"
                >
                  <template #icon><DesktopOutlined /></template>
                </a-button>
              </a-tooltip>
              <a-tooltip v-if="canRetryTask(record)" title="重新创建发布任务" placement="top">
                <a-button
                  type="text"
                  class="publish-action-btn"
                  :loading="retryingTaskId === record.id"
                  :aria-label="`重新创建发布任务：${record.title}`"
                  @click.stop="retryTask(record)"
                >
                  <template #icon><RetweetOutlined /></template>
                </a-button>
              </a-tooltip>
              <a-tooltip v-if="isPendingStatus(record.status)" title="发布任务进行中">
                <span class="publish-action-placeholder">
                  <ClockCircleOutlined />
                </span>
              </a-tooltip>
            </div>
          </template>
        </template>
      </a-table>

      <div class="publish-management-view__pagination">
        <a-pagination
          :current="page"
          :page-size="PAGE_SIZE"
          :total="totalCount"
          :show-size-changer="false"
          @change="handlePageChange"
        />
      </div>
    </section>
  </div>
</template>

<style scoped>
.publish-management-view {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.publish-management-view__top-card,
.publish-management-view__table-card {
  background: #fff;
  border: 1px solid #e6edf5;
  border-radius: 12px;
  overflow: hidden;
}

.publish-management-view__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding: 24px;
}

.publish-management-view__header-title h2 {
  margin: 0;
  color: #1a1a1a;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.4;
}

.publish-management-view__header-title p {
  margin: 6px 0 0;
  color: #8c8c8c;
  font-size: 13px;
  line-height: 1.7;
}

.publish-management-view__summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid #eef2f7;
}

.summary-chip {
  padding: 18px 24px;
  border-right: 1px solid #eef2f7;
}

.summary-chip:last-child {
  border-right: none;
}

.summary-chip span {
  display: block;
  color: #8c8c8c;
  font-size: 12px;
}

.summary-chip strong {
  display: block;
  margin-top: 8px;
  color: #1a1a1a;
  font-size: 24px;
  font-weight: 700;
}

.summary-chip__value--accent {
  color: #d48806 !important;
}

.publish-management-view__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 24px;
  border-bottom: 1px solid #f0f0f0;
}

.publish-management-view__toolbar h3 {
  margin: 0;
  color: #1a1a1a;
  font-size: 16px;
  font-weight: 700;
}

.publish-management-view__filters {
  display: flex;
  align-items: center;
  gap: 12px;
}

.publish-management-view__search {
  width: 280px;
}

.publish-management-table {
  padding: 0 24px 12px;
}

:deep(.publish-management-table .ant-table-thead > tr > th) {
  color: #6b7280;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

:deep(.publish-management-table .ant-table-tbody > tr > td) {
  padding: 15px 12px;
  vertical-align: middle;
}

:deep(.publish-management-table .publish-management-row--pending > td) {
  background: #fffbeb;
}

.publish-cell-stack {
  display: flex;
  min-width: 0;
  max-width: 100%;
  flex-direction: column;
  gap: 2px;
}

.publish-cell-title {
  display: block;
  overflow: hidden;
  color: #1f2937;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.publish-cell-title--compact {
  font-size: 13px;
}

.publish-cell-sub {
  display: block;
  overflow: hidden;
  margin-top: 3px;
  color: #8c8c8c;
  font-size: 12px;
  line-height: 1.5;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.publish-cell-sub--strong {
  color: #475569;
  font-weight: 500;
}

.publish-account-cell {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 10px;
}

.platform-avatar {
  display: inline-flex;
  overflow: hidden;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  border: 1px solid #e6edf5;
  border-radius: 8px;
  background: #f7f9fc;
  font-size: 12px;
  font-weight: 800;
}

.platform-avatar img {
  width: 20px;
  height: 20px;
  object-fit: contain;
}

.publish-meta-cell {
  width: 100%;
}

.publish-meta-footer {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  color: #94a3b8;
  font-size: 11.5px;
  line-height: 1.6;
}

.attempt-chip {
  display: inline-flex;
  height: 18px;
  align-items: center;
  padding: 0 6px;
  border-radius: 4px;
  background: #f1f5f9;
  color: #475569;
  font-size: 11px;
  font-weight: 600;
}

.meta-divider {
  color: #cbd5e1;
}

.publish-error-row {
  display: block;
  width: 100%;
  min-width: 0;
}

.publish-error-text {
  display: block;
  overflow: hidden;
  max-width: 100%;
  color: #dc2626;
  font-size: 12.5px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.publish-actions {
  display: flex;
  justify-content: flex-end;
  gap: 4px;
}

.publish-action-btn {
  display: inline-flex;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 7px;
  color: #64748b;
}

.publish-action-btn:hover:not(:disabled) {
  background: #eff6ff;
  color: #1677ff;
}

.publish-action-tooltip-wrap {
  display: inline-flex;
}

.publish-action-placeholder {
  display: inline-flex;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  color: #cbd5e1;
}

.publish-management-view__pagination {
  display: flex;
  justify-content: flex-end;
  padding: 16px 24px 24px;
}

:global(.publish-error-popover .ant-popover-inner) {
  max-width: min(720px, 82vw);
  border: 1px solid #fecaca;
  border-radius: 8px;
  box-shadow: 0 18px 38px rgba(15, 23, 42, 0.16);
}

:global(.publish-error-popover .ant-popover-inner-content) {
  padding: 12px;
}

:global(.publish-error-panel) {
  display: flex;
  min-width: min(520px, 76vw);
  max-width: min(720px, 82vw);
  flex-direction: column;
  gap: 10px;
}

:global(.publish-error-panel__title) {
  color: #dc2626;
  font-size: 13px;
  font-weight: 700;
}

:global(.publish-error-panel pre) {
  max-height: 360px;
  margin: 0;
  overflow: auto;
  padding: 10px;
  border: 1px solid #fee2e2;
  border-radius: 6px;
  background: #fff7f7;
  color: #991b1b;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 12px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}

:global(.publish-error-panel__copy) {
  display: inline-flex;
  align-self: flex-end;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 28px;
  padding: 0 10px;
  border: 1px solid #fecaca;
  border-radius: 6px;
  background: #fff;
  color: #dc2626;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
}

@media (max-width: 900px) {
  .publish-management-view__header,
  .publish-management-view__toolbar {
    flex-direction: column;
    align-items: stretch;
  }

  .publish-management-view__summary {
    grid-template-columns: 1fr;
  }

  .summary-chip {
    border-right: none;
    border-bottom: 1px solid #eef2f7;
  }

  .summary-chip:last-child {
    border-bottom: none;
  }

  .publish-management-view__filters {
    flex-direction: column;
    align-items: stretch;
  }

  .publish-management-view__search {
    width: 100%;
  }
}
</style>
