<script setup lang="ts">
import { DownloadOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons-vue'
import type {
  DesktopAccountInfo,
  DesktopClientDownloadableRelease,
  MediaPlatform,
} from '@geo/shared-types'
import { useQuery } from '@tanstack/vue-query'
import { message } from 'ant-design-vue'
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'

import { desktopClientApi, mediaApi, resolveApiURL, tenantAccountsApi } from '@/lib/api'
import { resolveAccountCheckedAt, resolveAccountHealth } from '@/lib/desktop-account-runtime'
import { formatBytes, formatDateTime } from '@/lib/display'
import {
  getPublishPlatformMeta,
  isMediaPublishAccount,
  normalizePublishPlatformId,
} from '@/lib/publish-platforms'

type AccountHealthFilter = 'all' | 'live' | 'captcha' | 'risk' | 'expired'
type PublishState = 'immediate' | 'queued' | 'unavailable'

interface MediaAccountCard {
  id: string
  platform: string
  platformLabel: string
  platformShortName: string
  platformAccent: string
  platformLogoUrl: string | null
  displayName: string
  platformUid: string
  avatarUrl: string | null
  health: DesktopAccountInfo['health']
  verifiedAt: string | null
  clientId: string | null
  clientOnline: boolean | null
  clientDeviceName: string | null
  clientLastSeenAt: string | null
  publishState: PublishState
  publishHint: string
  deleteRequestedAt: string | null
}

const platformLogoCatalog: Record<string, string> = {
  toutiaohao: '/logos/logo_toutiao.png',
  baijiahao: '/logos/logo_baijiahao.png',
  sohuhao: '/logos/logo_souhu.png',
  qiehao: '/logos/logo_qiehao.png',
  zhihu: '/logos/logo_zhihu.png',
  wangyihao: '/logos/logo_wangyihao.png',
  jianshu: '/logos/logo_jianshu.svg',
  bilibili: '/logos/logo_bilibili.png',
  juejin: '/logos/logo_juejin.png',
  smzdm: '/logos/logo_smzdm.svg',
  weixin_gzh: '/logos/logo_weixin_gzh.svg',
  zol: '/logos/logo_zol.png',
  dongchedi: '/logos/logo_dongchedi.svg',
}

const { t } = useI18n()

const searchQuery = ref('')
const selectedHealth = ref<AccountHealthFilter>('all')
const downloadingReleaseKey = ref<string | null>(null)

const platformsQuery = useQuery({
  queryKey: ['media', 'platforms', 'media-view'],
  queryFn: () => mediaApi.platforms(),
})

const accountsQuery = useQuery({
  queryKey: ['tenant', 'desktop-accounts', 'media-view'],
  queryFn: () => tenantAccountsApi.list(),
  staleTime: 0,
  refetchInterval: 5_000,
  refetchOnWindowFocus: true,
})

const downloadableReleasesQuery = useQuery({
  queryKey: ['tenant', 'desktop-client', 'downloadable-releases', 'stable'],
  queryFn: async () => {
    try {
      return await desktopClientApi.downloadableReleases('stable')
    } catch {
      return desktopClientApi.publicFallbackDownloadableReleases()
    }
  },
  staleTime: 60_000,
  refetchOnWindowFocus: true,
})

const loading = computed(() => platformsQuery.isPending.value || accountsQuery.isPending.value)
const refreshing = computed(
  () =>
    platformsQuery.isFetching.value ||
    accountsQuery.isFetching.value ||
    downloadableReleasesQuery.isFetching.value,
)

const platformMap = computed(() => {
  return new Map(
    (platformsQuery.data.value ?? []).map((platform: MediaPlatform) => [
      normalizePublishPlatformId(platform.platform_id),
      platform,
    ]),
  )
})

const mediaAccounts = computed<MediaAccountCard[]>(() => {
  return [...(accountsQuery.data.value ?? [])]
    .filter(isMediaPublishAccount)
    .map((account) => {
      const platformId = normalizePublishPlatformId(account.platform)
      const platform = platformMap.value.get(platformId)
      const fallback = getPublishPlatformMeta(platformId)
      const publishState = resolvePublishState(account)
      const health = resolveAccountHealth(account)

      return {
        id: account.id,
        platform: platformId,
        platformLabel: platform?.name || fallback.name,
        platformShortName: platform?.short_name || fallback.shortName,
        platformAccent: platform?.accent_color || fallback.accent,
        platformLogoUrl: resolvePlatformLogoUrl(platformId, platform?.logo_url),
        displayName: account.display_name,
        platformUid: normalizePlatformUid(account.platform_uid),
        avatarUrl: resolveApiURL(account.avatar_url),
        health,
        verifiedAt: resolveAccountCheckedAt(account),
        clientId: account.client_id,
        clientOnline: account.client_online,
        clientDeviceName: account.client_device_name,
        clientLastSeenAt: account.client_last_seen_at,
        publishState,
        publishHint: resolvePublishHint(account, publishState),
        deleteRequestedAt: account.delete_requested_at,
      }
    })
    .sort((left, right) => {
      const publishGap = publishRank(left.publishState) - publishRank(right.publishState)
      if (publishGap !== 0) {
        return publishGap
      }

      const leftAt = Date.parse(left.verifiedAt ?? '') || 0
      const rightAt = Date.parse(right.verifiedAt ?? '') || 0
      return rightAt - leftAt
    })
})

const overview = computed(() => ({
  total: mediaAccounts.value.length,
  live: mediaAccounts.value.filter((item) => item.health === 'live').length,
  immediate: mediaAccounts.value.filter((item) => item.publishState === 'immediate').length,
  queued: mediaAccounts.value.filter((item) => item.publishState === 'queued').length,
  attention: mediaAccounts.value.filter((item) => item.publishState === 'unavailable').length,
}))

const filteredAccounts = computed(() => {
  const keyword = searchQuery.value.trim().toLowerCase()

  return mediaAccounts.value.filter((account) => {
    if (selectedHealth.value !== 'all' && account.health !== selectedHealth.value) {
      return false
    }

    if (!keyword) {
      return true
    }

    return [
      account.displayName,
      account.platformLabel,
      account.platformUid,
      account.clientDeviceName ?? '',
    ]
      .join(' ')
      .toLowerCase()
      .includes(keyword)
  })
})

const downloadableReleases = computed(() => downloadableReleasesQuery.data.value?.items ?? [])
const downloadableReleasesError = computed(() => {
  const error = downloadableReleasesQuery.error.value
  if (!error) {
    return ''
  }
  if (error instanceof Error) {
    return error.message
  }
  return String(error)
})

function resolvePublishState(account: DesktopAccountInfo): PublishState {
  if (resolveAccountHealth(account) !== 'live') {
    return 'unavailable'
  }
  if (!account.client_id) {
    return 'unavailable'
  }
  return account.client_online === true ? 'immediate' : 'queued'
}

function resolvePublishHint(account: DesktopAccountInfo, publishState: PublishState): string {
  if (publishState === 'immediate') {
    return ''
  }
  if (publishState === 'queued') {
    return '客户端当前离线，任务会先进入发布队列，等桌面端上线后自动继续。'
  }
  if (resolveAccountHealth(account) !== 'live') {
    return '授权状态异常，先在桌面端重新校验后再发布。'
  }
  return '还没有绑定桌面客户端，当前无法加入发布队列。'
}

function normalizePlatformUid(value?: string | null): string {
  let normalized = String(value ?? '').trim()
  while (normalized.toLowerCase().startsWith('platform:')) {
    normalized = normalized.slice('platform:'.length).trim()
  }
  return normalized || '--'
}

function resolvePlatformLogoUrl(platformId: string, remoteLogoUrl?: string | null): string | null {
  const localLogoUrl = platformLogoCatalog[platformId]
  if (localLogoUrl) {
    return localLogoUrl
  }

  const resolvedRemoteLogoUrl = resolveApiURL(remoteLogoUrl)
  return resolvedRemoteLogoUrl || null
}

function accountInitial(account: MediaAccountCard): string {
  const name = account.displayName.trim()
  return name ? name.slice(0, 1).toUpperCase() : account.platformShortName
}

function publishRank(state: PublishState): number {
  switch (state) {
    case 'immediate':
      return 0
    case 'queued':
      return 1
    default:
      return 2
  }
}

function healthLabel(health: DesktopAccountInfo['health']): string {
  switch (health) {
    case 'live':
      return '授权正常'
    case 'captcha':
      return '待处理'
    case 'risk':
      return '风险观察'
    default:
      return '授权异常'
  }
}

function healthColor(health: DesktopAccountInfo['health']): string {
  switch (health) {
    case 'live':
      return 'green'
    case 'captcha':
      return 'orange'
    case 'risk':
      return 'gold'
    default:
      return 'red'
  }
}

function clientStatusLabel(account: MediaAccountCard): string {
  if (!account.clientId) {
    return '未绑定'
  }
  return account.clientOnline ? '在线' : '离线'
}

function clientStatusColor(account: MediaAccountCard): string {
  if (!account.clientId) {
    return 'default'
  }
  return account.clientOnline ? 'green' : 'gold'
}

function clientStatusText(account: MediaAccountCard): string {
  if (!account.clientId) {
    return '未绑定桌面客户端'
  }

  const device = account.clientDeviceName?.trim()
  return device ? `${clientStatusLabel(account)} · ${device}` : clientStatusLabel(account)
}

function publishStateLabel(state: PublishState): string {
  switch (state) {
    case 'immediate':
      return '可立即发布'
    case 'queued':
      return '离线排队'
    default:
      return '不可发布'
  }
}

function publishStateColor(state: PublishState): string {
  switch (state) {
    case 'immediate':
      return 'green'
    case 'queued':
      return 'gold'
    default:
      return 'red'
  }
}

async function refreshAll(): Promise<void> {
  await Promise.all([
    platformsQuery.refetch(),
    accountsQuery.refetch(),
    downloadableReleasesQuery.refetch(),
  ])
}

async function downloadRelease(release: DesktopClientDownloadableRelease): Promise<void> {
  const key = releaseDownloadKey(release)
  if (downloadingReleaseKey.value) {
    return
  }

  downloadingReleaseKey.value = key
  const downloadWindow = window.open('about:blank', '_blank')
  if (downloadWindow) {
    downloadWindow.opener = null
  }
  try {
    const result = await desktopClientApi.publicDownloadURL({
      platform: release.platform,
      arch: release.arch,
      channel: release.channel,
    })
    const downloadURL = String(result.download_url ?? '').trim()
    if (!downloadURL) {
      message.warning('下载地址为空')
      downloadWindow?.close()
      return
    }
    if (downloadWindow) {
      downloadWindow.location.href = downloadURL
    } else {
      window.open(downloadURL, '_blank', 'noopener,noreferrer')
    }
  } catch (error) {
    downloadWindow?.close()
    const detail =
      typeof error === 'object' && error !== null && 'detail' in error ? error.detail : null
    const reason =
      typeof detail === 'string' && detail.trim()
        ? detail
        : error instanceof Error
          ? error.message
          : '请稍后重试'
    message.error(`获取下载地址失败：${reason}`)
  } finally {
    if (downloadingReleaseKey.value === key) {
      downloadingReleaseKey.value = null
    }
  }
}

function releaseDownloadKey(release: DesktopClientDownloadableRelease): string {
  return `${release.platform}:${release.arch}:${release.channel}`
}

function releaseTargetLabel(release: DesktopClientDownloadableRelease): string {
  return `${releasePlatformLabel(release.platform)} ${releaseArchLabel(release.arch)}`
}

function releasePlatformLabel(platform: string): string {
  switch (platform) {
    case 'darwin':
      return 'macOS'
    case 'win32':
      return 'Windows'
    case 'linux':
      return 'Linux'
    default:
      return platform
  }
}

function releasePlatformMark(platform: string): string {
  switch (platform) {
    case 'darwin':
      return 'MAC'
    case 'win32':
      return 'WIN'
    case 'linux':
      return 'LIN'
    default:
      return platform.slice(0, 3).toUpperCase()
  }
}

function releasePlatformClass(platform: string): string {
  return ['darwin', 'win32', 'linux'].includes(platform) ? platform : 'default'
}

function releaseArchLabel(arch: string): string {
  switch (arch) {
    case 'arm64':
      return 'ARM64'
    case 'x64':
      return 'x64'
    case 'ia32':
      return 'ia32'
    case 'universal':
      return 'Universal'
    default:
      return arch
  }
}

function releaseDate(release: DesktopClientDownloadableRelease): string {
  return formatDateTime(release.published_at ?? release.updated_at)
}

function releaseSize(value?: number | null): string {
  return typeof value === 'number' && Number.isFinite(value) ? formatBytes(value) : '--'
}
</script>

<template>
  <div class="media-view">
    <!-- Premium Dark Banner Section -->
    <section class="media-view__top-card">
      <div class="banner-gradient-orbs">
        <div class="orb orb-1"></div>
        <div class="orb orb-2"></div>
      </div>
      <div class="media-view__header">
        <div class="media-view__header-title">
          <h2>
            {{ t('route.media.title') }}
          </h2>
          <p>
            展示客户端里当前已绑定的媒体账号，集成发布队列状态，提供多渠道账号集中式生命周期管理。
          </p>
        </div>
        <div class="media-view__header-actions">
          <a-button class="btn-refresh" :loading="refreshing" @click="refreshAll">
            <template #icon><ReloadOutlined /></template>
            刷新状态
          </a-button>
        </div>
      </div>

      <div class="overview-strip border-t">
        <div class="overview-chip">
          <div class="chip-icon-box total-bg">
            <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
              <path d="M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2zm1 14h-2v-6h2v6zm0-8h-2V6h2v2z"/>
            </svg>
          </div>
          <div class="chip-copy">
            <span>账号总数</span>
            <strong>{{ overview.total }}</strong>
          </div>
        </div>
        <div class="overview-chip">
          <div class="chip-icon-box live-bg">
            <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
              <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
            </svg>
          </div>
          <div class="chip-copy">
            <span>可立即发布</span>
            <strong>{{ overview.immediate }}</strong>
          </div>
        </div>
        <div class="overview-chip">
          <div class="chip-icon-box queued-bg">
            <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
              <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
            </svg>
          </div>
          <div class="chip-copy">
            <span>离线排队</span>
            <strong>{{ overview.queued }}</strong>
          </div>
        </div>
        <div class="overview-chip">
          <div class="chip-icon-box attention-bg">
            <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
              <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
            </svg>
          </div>
          <div class="chip-copy">
            <span>需处理</span>
            <strong>{{ overview.attention }}</strong>
          </div>
        </div>
      </div>
    </section>

    <!-- Client Download Section (App Store Style) -->
    <section class="panel client-download-panel">
      <div class="client-download-head">
        <div>
          <div class="title-with-badge">
            <h3 class="panel-title">客户端下载</h3>
            <span class="badge-pulsing-stable">Stable</span>
          </div>
          <p class="panel-desc">高并发发布与任务执行节点，版本根据后台发布配置自动更新与推送。</p>
        </div>
      </div>

      <a-spin :spinning="downloadableReleasesQuery.isPending.value">
        <a-alert
          v-if="downloadableReleasesError"
          type="warning"
          show-icon
          class="premium-alert"
          :message="`客户端列表读取失败：${downloadableReleasesError}`"
        />

        <a-empty
          v-else-if="!downloadableReleases.length"
          class="premium-empty"
          description="当前暂无可下载客户端，请等待运营后台发布。"
        />

        <div v-else class="client-download-grid">
          <article
            v-for="release in downloadableReleases"
            :key="release.id"
            class="client-download-card"
          >
            <div class="client-download-card__body">
              <div class="client-download-card__logo" :class="`logo-${release.platform}`">
                <template v-if="release.platform === 'darwin'">
                  <svg viewBox="0 0 24 24" class="os-svg-icon">
                    <path fill="currentColor" d="M18.71,19.5 C17.88,20.74 17,21.95 15.66,21.97 C14.32,22 13.89,21.18 12.37,21.18 C10.84,21.18 10.37,21.95 9.1,22 C7.79,22.05 6.8,20.68 5.96,19.48 C4.25,17 2.94,12.45 4.7,9.39 C5.57,7.87 7.13,6.91 8.82,6.88 C10.1,6.86 11.32,7.75 12.11,7.75 C12.89,7.75 14.37,6.68 15.92,6.84 C16.57,6.87 18.39,7.1 19.56,8.82 C19.47,8.88 17.39,10.1 17.41,12.63 C17.44,15.65 20.06,16.66 20.1,16.67 C20.08,16.74 19.67,18.11 18.71,19.5 M15.97,4.17 C16.63,3.37 17.07,2.28 16.95,1 C16,1.04 14.9,1.6 14.24,2.38 C13.68,3.04 13.19,4.14 13.34,5.39 C14.39,5.47 15.4,4.88 15.97,4.17 Z" />
                  </svg>
                </template>
                <template v-else-if="release.platform === 'win32'">
                  <svg viewBox="0 0 24 24" class="os-svg-icon">
                    <path fill="currentColor" d="M0 3.449L9.75 2.1v9.45H0V3.449zM0 12.45h9.75v9.45L0 20.551V12.45zm11.25-10.549L24 0v11.55H11.25V1.901zM11.25 12.45H24v11.55l-12.75-1.901V12.45z"/>
                  </svg>
                </template>
                <template v-else>
                  <svg viewBox="0 0 24 24" class="os-svg-icon" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <polyline points="4 17 10 11 4 5"></polyline>
                    <line x1="12" y1="19" x2="20" y2="19"></line>
                  </svg>
                </template>
              </div>
              <div class="client-download-card__content">
                <h4>{{ releaseTargetLabel(release) }}</h4>
                <div class="meta-inline">
                  <span class="version-tag">v{{ release.version }}</span>
                  <span class="dot-separator">•</span>
                  <span>{{ releaseSize(release.file_size_bytes) }}</span>
                  <span class="dot-separator">•</span>
                  <span>{{ releaseDate(release) }}</span>
                </div>
              </div>
            </div>

            <div class="client-download-card__file">
              <span class="file-icon">
                <svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2">
                  <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                  <polyline points="14 2 14 8 20 8"></polyline>
                </svg>
              </span>
              <span class="file-name" :title="release.file_name || '安装包'">
                {{ release.file_name || '安装包' }}
              </span>
            </div>

            <div class="client-download-card__actions">
              <a-button
                type="primary"
                class="btn-download"
                :loading="downloadingReleaseKey === releaseDownloadKey(release)"
                :disabled="Boolean(downloadingReleaseKey)"
                @click="downloadRelease(release)"
              >
                <template #icon><DownloadOutlined /></template>
                获取客户端
              </a-button>
            </div>
          </article>
        </div>
      </a-spin>
    </section>

    <!-- Bound accounts grid section -->
    <section class="panel media-list-panel">
      <div class="media-list-header-row">
        <div class="media-list-title-box">
          <h3 class="panel-title">已绑定媒体账号</h3>
          <p class="panel-desc">管理各媒体账号的授权效期、排队就绪状态和客户端物理节点映射。</p>
        </div>

        <div class="media-list-toolbar">
          <a-input
            v-model:value="searchQuery"
            placeholder="搜索账号昵称、UID、发布渠道..."
            class="media-search"
            allow-clear
          >
            <template #prefix>
              <SearchOutlined style="color: #a0aec0" />
            </template>
          </a-input>

          <a-select v-model:value="selectedHealth" class="media-select" style="width: 150px">
            <a-select-option value="all">全部状态</a-select-option>
            <a-select-option value="live">授权正常</a-select-option>
            <a-select-option value="captcha">待处理</a-select-option>
            <a-select-option value="risk">风险观察</a-select-option>
            <a-select-option value="expired">授权异常</a-select-option>
          </a-select>
        </div>
      </div>

      <a-spin :spinning="loading">
        <a-empty
          v-if="!filteredAccounts.length"
          class="premium-empty"
          description="没有符合过滤条件的媒体账号，请确保桌面端客户端在线并已绑定账号。"
        />

        <section v-else class="media-grid">
          <article v-for="account in filteredAccounts" :key="account.id" class="media-card">
            <!-- Top brand line accent using accent color -->
            <div class="media-card__accent-bar" :style="{ background: account.platformAccent }"></div>
            
            <div class="media-card__head">
              <div class="media-card__identity">
                <span class="media-card__avatar" :style="{ border: `2px solid ${account.platformAccent}` }">
                  <img
                    v-if="account.avatarUrl"
                    :src="account.avatarUrl"
                    :alt="account.displayName"
                    referrerpolicy="no-referrer"
                  />
                  <span v-else class="avatar-initial" :style="{ background: account.platformAccent }">
                    {{ accountInitial(account) }}
                  </span>
                </span>

                <div class="media-card__identity-copy">
                  <h3 :title="account.displayName">
                    {{ account.displayName }}
                    <span class="platform-logo-container">
                      <img
                        v-if="account.platformLogoUrl"
                        :src="account.platformLogoUrl"
                        :alt="account.platformLabel"
                        class="media-card__inline-platform-icon"
                      />
                      <span
                        v-else
                        class="media-card__inline-platform-text"
                        :style="{ color: account.platformAccent, background: `${account.platformAccent}15` }"
                      >
                        {{ account.platformShortName }}
                      </span>
                    </span>
                  </h3>
                  <p>
                    <span class="media-card__platform-name">{{ account.platformLabel }}</span>
                    <span class="media-card__uid-divider">•</span>
                    <span class="media-card__uid" :title="account.platformUid">ID: {{ account.platformUid }}</span>
                  </p>
                </div>
              </div>
            </div>

            <div class="media-card__tags">
              <span class="badge-status" :class="`badge-status--${healthColor(account.health)}`">
                <span class="indicator-dot"></span>
                {{ healthLabel(account.health) }}
              </span>
              
              <span class="badge-status" :class="`badge-status--${publishStateColor(account.publishState)}`">
                <span class="indicator-dot"></span>
                {{ publishStateLabel(account.publishState) }}
              </span>
            </div>

            <!-- Client mapping connection card -->
            <div class="media-card__client-info">
              <div class="client-info-inner">
                <span class="client-label">运行节点</span>
                <a-tooltip :title="clientStatusText(account)" placement="top">
                  <span class="client-value" :class="`client-value--${clientStatusColor(account)}`">
                    {{ clientStatusText(account) }}
                  </span>
                </a-tooltip>
              </div>
            </div>

            <div class="media-card__meta-box">
              <div class="meta-box-item">
                <span class="meta-label">安全校验</span>
                <span class="meta-value">
                  {{ account.verifiedAt ? formatDateTime(account.verifiedAt) : '--' }}
                </span>
              </div>
              <div class="meta-box-item">
                <span class="meta-label">节点心跳</span>
                <span class="meta-value">
                  {{ account.clientLastSeenAt ? formatDateTime(account.clientLastSeenAt) : '--' }}
                </span>
              </div>
            </div>

            <!-- Foot note panel -->
            <div v-if="account.deleteRequestedAt || account.publishHint" class="media-card__footer">
              <div v-if="account.deleteRequestedAt" class="footer-alert footer-alert--warning">
                <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
                  <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
                </svg>
                <span>已申请解绑账号</span>
              </div>
              <div v-else-if="account.publishHint" class="footer-alert">
                <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
                  <path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"/>
                </svg>
                <span :title="account.publishHint">{{ account.publishHint }}</span>
              </div>
            </div>
          </article>
        </section>
      </a-spin>
    </section>
  </div>
</template>

<style scoped>
/* Page Layout */
.media-view {
  display: flex;
  flex-direction: column;
  gap: 24px;
  background-color: #f8fafc;
  min-height: 100%;
}

/* Premium Dark Banner Section */
.media-view__top-card {
  position: relative;
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
  border: 1px solid #e2e8f0;
  border-radius: 16px;
  overflow: hidden;
  padding: 0;
  box-shadow: 0 10px 30px rgba(148, 163, 184, 0.06);
}

/* Fuzzy Floating Gradient Orbs */
.banner-gradient-orbs {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
  z-index: 1;
}

.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.6;
}

.orb-1 {
  top: -40px;
  right: 15%;
  width: 250px;
  height: 250px;
  background: radial-gradient(circle, #e0e7ff 0%, transparent 80%);
  animation: float-slow-1 12s infinite alternate ease-in-out;
}

.orb-2 {
  bottom: -60px;
  left: 10%;
  width: 300px;
  height: 300px;
  background: radial-gradient(circle, #f5f3ff 0%, transparent 80%);
  animation: float-slow-2 15s infinite alternate ease-in-out;
}

@keyframes float-slow-1 {
  0% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(40px, 20px) scale(1.1); }
}

@keyframes float-slow-2 {
  0% { transform: translate(0, 0) scale(1.1); }
  100% { transform: translate(-30px, -20px) scale(0.9); }
}

.media-view__header {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 32px;
  z-index: 2;
}

.media-view__header-title {
  max-width: 650px;
}

.media-view__header-title h2 {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.3;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  letter-spacing: -0.02em;
}



.media-view__header-title p {
  margin: 8px 0 0;
  font-size: 13.5px;
  color: #475569;
  line-height: 1.6;
  font-weight: 400;
}

.media-view__header-actions {
  display: flex;
  gap: 12px;
}

/* Premium Refresh Button Override */
:deep(.btn-refresh.ant-btn) {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  color: #0f172a;
  border-radius: 8px;
  height: 40px;
  padding: 0 18px;
  font-weight: 500;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 2px 4px rgba(148, 163, 184, 0.05);
}

:deep(.btn-refresh.ant-btn:hover) {
  background: #f8fafc;
  border-color: #cbd5e1;
  color: #4f46e5;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(148, 163, 184, 0.08);
}

/* Metrics strip styling */
.overview-strip {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(12px);
  border-top: 1px solid #e2e8f0;
  z-index: 2;
}

.overview-chip {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px 32px;
  border-right: 1px solid #e2e8f0;
  transition: all 0.25s ease;
}

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

.overview-chip:hover {
  background: rgba(255, 255, 255, 0.7);
}

.chip-icon-box {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Metric colored boxes styling */
.total-bg {
  background: #e0e7ff;
  color: #4f46e5;
  border: 1px solid #c7d2fe;
}

.live-bg {
  background: #d1fae5;
  color: #059669;
  border: 1px solid #a7f3d0;
}

.queued-bg {
  background: #fef3c7;
  color: #d97706;
  border: 1px solid #fde68a;
}

.attention-bg {
  background: #ffe4e6;
  color: #e11d48;
  border: 1px solid #fecdd3;
}

.chip-copy {
  display: flex;
  flex-direction: column;
}

.chip-copy span {
  color: #64748b;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
}

.chip-copy strong {
  color: #0f172a;
  font-size: 26px;
  font-weight: 700;
  margin-top: 4px;
  line-height: 1;
  font-family: 'Inter', system-ui, sans-serif;
  letter-spacing: -0.02em;
}

/* Panel Layout Styling */
.panel {
  background: #ffffff;
  border-radius: 16px;
  padding: 32px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 4px 20px rgba(148, 163, 184, 0.05);
  transition: box-shadow 0.3s ease, border-color 0.3s ease;
}

.panel:hover {
  box-shadow: 0 10px 30px rgba(148, 163, 184, 0.08);
}

.panel-title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: #0f172a;
  letter-spacing: -0.01em;
}

.panel-desc {
  margin: 6px 0 0;
  color: #64748b;
  font-size: 13.5px;
  line-height: 1.5;
}

/* Client download header and grid */
.client-download-panel {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.client-download-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.title-with-badge {
  display: flex;
  align-items: center;
  gap: 12px;
}

.badge-pulsing-stable {
  background: rgba(99, 102, 241, 0.1);
  color: #4f46e5;
  border: 1px solid rgba(99, 102, 241, 0.2);
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 99px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  position: relative;
  overflow: hidden;
}

.badge-pulsing-stable::after {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(99, 102, 241, 0.2), transparent);
  animation: shine-sweep 3s infinite linear;
}

@keyframes shine-sweep {
  0% { left: -100%; }
  100% { left: 100%; }
}

.client-download-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
}

/* Client download cards */
.client-download-card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 200px;
  padding: 24px;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
}

.client-download-card:hover {
  transform: translateY(-4px);
  border-color: #cbd5e1;
  box-shadow: 0 12px 24px rgba(148, 163, 184, 0.12);
}

.client-download-card__body {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

/* Elegant custom OS SVGs logos wrapper */
.client-download-card__logo {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all 0.3s ease;
}

.logo-darwin {
  background: #0f172a;
  color: #ffffff;
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.15);
}

.logo-win32 {
  background: #0078d4;
  color: #ffffff;
  box-shadow: 0 4px 12px rgba(0, 120, 212, 0.2);
}

.logo-default, .logo-linux {
  background: #1e293b;
  color: #38bdf8;
  box-shadow: 0 4px 12px rgba(30, 41, 59, 0.2);
}

.os-svg-icon {
  width: 22px;
  height: 22px;
}

.client-download-card__content {
  min-width: 0;
}

.client-download-card__content h4 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.3;
}

.meta-inline {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
  color: #64748b;
  font-size: 12px;
}

.version-tag {
  background: #f1f5f9;
  color: #475569;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 4px;
}

.dot-separator {
  color: #cbd5e1;
  font-size: 8px;
}

/* Code-looking filename strip */
.client-download-card__file {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #f1f5f9;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: 18px;
  margin-bottom: 18px;
  overflow: hidden;
}

.file-icon {
  color: #64748b;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.file-name {
  color: #334155;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 11.5px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.client-download-card__actions {
  display: flex;
}

/* Download Button styling */
:deep(.btn-download.ant-btn-primary) {
  background: #4f46e5;
  border-color: #4f46e5;
  border-radius: 8px;
  height: 38px;
  width: 100%;
  font-weight: 600;
  font-size: 13px;
  box-shadow: 0 4px 12px rgba(79, 70, 229, 0.2);
  transition: all 0.25s ease;
}

:deep(.btn-download.ant-btn-primary:hover:not(:disabled)) {
  background: #4338ca;
  border-color: #4338ca;
  box-shadow: 0 6px 18px rgba(79, 70, 229, 0.3);
  transform: translateY(-1px);
}

:deep(.btn-download.ant-btn-primary:disabled) {
  background: #cbd5e1;
  border-color: #cbd5e1;
  color: #94a3b8;
  box-shadow: none;
}

/* Spinners, alerts, empty state styling */
.premium-alert {
  border-radius: 12px;
  border: 1px solid #fecaca;
  background: #fef2f2;
}

.premium-empty {
  padding: 40px 0;
  border: 1px dashed #e2e8f0;
  border-radius: 12px;
}

/* Media list panel & search toolbar */
.media-list-panel {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.media-list-header-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
}

.media-list-title-box {
  flex: 1;
  min-width: 250px;
}

.media-list-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

/* Styled Inputs & Selects */
:deep(.media-search.ant-input-affix-wrapper) {
  width: 320px;
  height: 40px;
  border-radius: 8px;
  border-color: #cbd5e1;
  background-color: #ffffff;
  padding-left: 12px;
  transition: all 0.2s ease;
}

:deep(.media-search.ant-input-affix-wrapper:hover) {
  border-color: #94a3b8;
}

:deep(.media-search.ant-input-affix-wrapper-focused) {
  border-color: #4f46e5;
  box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

:deep(.media-select.ant-select .ant-select-selector) {
  height: 40px !important;
  border-radius: 8px !important;
  border-color: #cbd5e1 !important;
  padding: 4px 12px !important;
  transition: all 0.2s ease;
}

:deep(.media-select.ant-select:hover .ant-select-selector) {
  border-color: #94a3b8 !important;
}

:deep(.media-select.ant-select-focused .ant-select-selector) {
  border-color: #4f46e5 !important;
  box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15) !important;
}

/* Media Card Grid */
.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(295px, 1fr));
  gap: 20px;
}

/* Premium Media Card */
.media-card {
  position: relative;
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 14px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(148, 163, 184, 0.03);
}

.media-card__accent-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  opacity: 0.85;
}

.media-card:hover {
  transform: translateY(-5px);
  border-color: #cbd5e1;
  box-shadow: 0 16px 36px rgba(148, 163, 184, 0.12);
}

.media-card__head {
  display: flex;
  align-items: center;
}

.media-card__identity {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  width: 100%;
}

/* Circular Avatar glow container */
.media-card__avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
  background: #f1f5f9;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  transition: transform 0.3s ease;
}

.media-card:hover .media-card__avatar {
  transform: scale(1.05);
}

.media-card__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-initial {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  font-weight: 700;
  font-size: 16px;
}

.media-card__identity-copy {
  min-width: 0;
  flex: 1;
}

.media-card__identity-copy h3 {
  margin: 0;
  color: #0f172a;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.3;
  display: flex;
  align-items: center;
  gap: 6px;
}

.platform-logo-container {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

.media-card__inline-platform-icon {
  width: 16px;
  height: 16px;
  object-fit: contain;
}

.media-card__inline-platform-text {
  font-size: 10px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 4px;
  letter-spacing: 0.02em;
}

.media-card__identity-copy p {
  margin: 5px 0 0;
  color: #64748b;
  font-size: 12.5px;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.media-card__platform-name {
  font-weight: 600;
  color: #475569;
}

.media-card__uid-divider {
  color: #cbd5e1;
  font-weight: bold;
}

.media-card__uid {
  color: #94a3b8;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

/* Polished Pill Badges */
.media-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

.badge-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 99px;
  line-height: 1.4;
}

.indicator-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
}

/* Colorful status mapping */
.badge-status--green {
  background: rgba(16, 185, 129, 0.08);
  color: #059669;
  border: 1px solid rgba(16, 185, 129, 0.15);
}
.badge-status--green .indicator-dot {
  background-color: #10b981;
}

.badge-status--orange {
  background: rgba(245, 158, 11, 0.08);
  color: #d97706;
  border: 1px solid rgba(245, 158, 11, 0.15);
}
.badge-status--orange .indicator-dot {
  background-color: #f59e0b;
}

.badge-status--gold {
  background: rgba(217, 119, 6, 0.08);
  color: #b45309;
  border: 1px solid rgba(217, 119, 6, 0.15);
}
.badge-status--gold .indicator-dot {
  background-color: #d97706;
}

.badge-status--red {
  background: rgba(244, 63, 94, 0.08);
  color: #e11d48;
  border: 1px solid rgba(244, 63, 94, 0.15);
}
.badge-status--red .indicator-dot {
  background-color: #f43f5e;
}

.badge-status--default {
  background: rgba(100, 116, 139, 0.08);
  color: #475569;
  border: 1px solid rgba(100, 116, 139, 0.15);
}
.badge-status--default .indicator-dot {
  background-color: #64748b;
}

/* Client runtime block */
.media-card__client-info {
  background: #f8fafc;
  border: 1px solid #f1f5f9;
  border-radius: 8px;
  padding: 10px 12px;
}

.client-info-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
}

.client-label {
  color: #64748b;
  font-weight: 500;
}

.client-value {
  font-weight: 600;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.client-value--green {
  color: #059669;
}

.client-value--gold {
  color: #d97706;
}

.client-value--default {
  color: #64748b;
}

/* Metadata box */
.media-card__meta-box {
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-top: 1px solid #f1f5f9;
  padding-top: 12px;
}

.meta-box-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11.5px;
}

.meta-label {
  color: #94a3b8;
  font-weight: 500;
}

.meta-value {
  color: #475569;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-weight: 500;
}

/* Card footer details hints */
.media-card__footer {
  margin-top: auto;
  border-top: 1px dashed #f1f5f9;
  padding-top: 12px;
}

.footer-alert {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: #64748b;
  background: #f8fafc;
  border-radius: 6px;
  padding: 6px 10px;
  line-height: 1.4;
}

.footer-alert svg {
  flex-shrink: 0;
  color: #94a3b8;
}

.footer-alert span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.footer-alert--warning {
  background: #fffbeb;
  color: #b45309;
  border: 1px solid #fef3c7;
}

.footer-alert--warning svg {
  color: #d97706;
}

/* Responsiveness adjustments */
@media (max-width: 1024px) {
  .overview-strip {
    grid-template-columns: repeat(2, 1fr);
  }

  .overview-chip {
    border-bottom: 1px solid #e2e8f0;
  }

  .overview-chip:nth-child(even) {
    border-right: none;
  }

  .overview-chip:nth-child(n+3) {
    border-bottom: none;
  }
}

@media (max-width: 768px) {
  .media-view__header {
    flex-direction: column;
    align-items: stretch;
    gap: 20px;
    padding: 24px;
  }

  .media-view__header-actions {
    width: 100%;
  }

  .media-view__header-actions :deep(.ant-btn) {
    width: 100%;
  }

  .overview-chip {
    padding: 16px 20px;
  }

  .panel {
    padding: 20px;
  }

  .media-list-header-row {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
  }

  .media-list-toolbar {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }

  :deep(.media-search.ant-input-affix-wrapper) {
    width: 100%;
  }

  :deep(.media-select.ant-select) {
    width: 100% !important;
  }
}

@media (max-width: 480px) {
  .overview-strip {
    grid-template-columns: 1fr;
  }

  .overview-chip {
    border-right: none;
    border-bottom: 1px solid #e2e8f0;
  }

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

  .client-download-grid, .media-grid {
    grid-template-columns: 1fr;
  }
}
</style>
