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

import { articlesApi, mediaApi } from '@/lib/api'
import { getPublishStatusMeta } from '@/lib/display'
import { getPublishPlatformMeta, normalizePublishPlatformId } from '@/lib/publish-platforms'

interface PublishPlatformEntry {
  key: string
  name: string
  shortName: string
  accent: string
  accountName: string
  avatarUrl: string
  status: PublishRecordStatus
}

type PublishRecordStatus = 'success' | 'failed' | 'publishing'

interface PublishPlatformSection {
  key: PublishRecordStatus
  label: string
  tone: 'success' | 'failed' | 'pending'
  entries: PublishPlatformEntry[]
}

const props = withDefaults(
  defineProps<{
    status?: string | null
    articleId?: number | null
    showPlatforms?: boolean
  }>(),
  {
    status: null,
    articleId: null,
    showPlatforms: true,
  },
)

const { t } = useI18n()
const popoverOpen = ref(false)
const shouldLoadRecords = computed(() => Boolean(props.articleId) && props.status !== 'unpublished')
const shouldLoadPlatforms = computed(() => props.showPlatforms && shouldLoadRecords.value)

const platformsQuery = useQuery({
  queryKey: ['media', 'platforms', 'publish-status'],
  enabled: computed(() => popoverOpen.value && shouldLoadPlatforms.value),
  queryFn: () => mediaApi.platforms(),
  staleTime: 5 * 60 * 1000,
})

const publishRecordsQuery = useQuery({
  queryKey: computed(() => ['articles', 'publish-records', props.articleId]),
  enabled: shouldLoadRecords,
  queryFn: () => articlesApi.publishRecords(props.articleId as number),
  staleTime: 30 * 1000,
})

const hasPopover = computed(() => props.showPlatforms && shouldLoadRecords.value)

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

const platformEntries = computed<PublishPlatformEntry[]>(() => {
  const seen = new Set<string>()
  const entries: PublishPlatformEntry[] = []

  for (const record of publishRecordsQuery.data.value ?? []) {
    const key = `${record.platform_id}:${record.platform_account_id}`
    if (seen.has(key)) {
      continue
    }
    seen.add(key)

    const normalizedId = normalizePublishPlatformId(record.platform_id)
    const platform = platformMap.value.get(normalizedId)
    const fallback = getPublishPlatformMeta(normalizedId)

    entries.push({
      key,
      name: record.platform_name || platform?.name || fallback.name,
      shortName: platform?.short_name || fallback.shortName,
      accent: platform?.accent_color || fallback.accent,
      accountName: record.platform_nickname || '--',
      avatarUrl: '',
      status: normalizePublishRecordStatus(record.status),
    })
  }

  return entries
})

const successEntries = computed(() =>
  platformEntries.value.filter((entry) => entry.status === 'success'),
)

const failedEntries = computed(() =>
  platformEntries.value.filter((entry) => entry.status === 'failed'),
)

const pendingEntries = computed(() =>
  platformEntries.value.filter((entry) => entry.status === 'publishing'),
)

const displayStatus = computed(() => {
  if (successEntries.value.length > 0 && failedEntries.value.length > 0) {
    return 'partial_success'
  }

  if (failedEntries.value.length > 0) {
    return 'failed'
  }

  if (pendingEntries.value.length > 0) {
    return 'publishing'
  }

  if (successEntries.value.length > 0) {
    return 'success'
  }

  if (props.status === 'partial_success') {
    return 'partial_success'
  }

  if (props.status === 'publish_success' || props.status === 'published') {
    return 'success'
  }

  if (props.status === 'publish_failed') {
    return 'failed'
  }

  if (props.status === 'pending_review') {
    return 'failed'
  }

  return props.status ?? null
})

const statusMeta = computed(() => getPublishStatusMeta(displayStatus.value))

const statusTone = computed(() => {
  switch (displayStatus.value) {
    case 'success':
      return 'success'
    case 'failed':
      return 'failed'
    case 'publishing':
      return 'processing'
    case 'partial_success':
      return 'warning'
    default:
      return 'default'
  }
})

const popoverSections = computed<PublishPlatformSection[]>(() => {
  const sections: PublishPlatformSection[] = []

  if (failedEntries.value.length > 0) {
    sections.push({
      key: 'failed',
      label: `${getPublishStatusMeta('failed').label}：`,
      tone: 'failed',
      entries: failedEntries.value,
    })
  }

  if (pendingEntries.value.length > 0) {
    sections.push({
      key: 'publishing',
      label: `${getPublishStatusMeta('publishing').label}：`,
      tone: 'pending',
      entries: pendingEntries.value,
    })
  }

  if (successEntries.value.length > 0) {
    sections.push({
      key: 'success',
      label: `${getPublishStatusMeta('success').label}：`,
      tone: 'success',
      entries: successEntries.value,
    })
  }

  return sections
})

function handlePopoverChange(nextOpen: boolean): void {
  popoverOpen.value = nextOpen
}

function normalizePublishRecordStatus(status?: string | null): PublishRecordStatus {
  switch (String(status ?? '').trim()) {
    case 'success':
    case 'published':
    case 'publish_success':
      return 'success'
    case 'publishing':
    case 'running':
    case 'queued':
      return 'publishing'
    case 'pending_review':
      return 'failed'
    case 'failed':
    case 'publish_failed':
    default:
      return 'failed'
  }
}

function getAccountInitial(accountName: string): string {
  const trimmed = String(accountName ?? '').trim()
  if (!trimmed || trimmed === '--') {
    return ''
  }

  return trimmed.slice(0, 1).toUpperCase()
}
</script>

<template>
  <a-popover
    v-if="hasPopover"
    placement="top"
    trigger="hover"
    overlay-class-name="article-publish-status__popover-overlay"
    @openChange="handlePopoverChange"
  >
    <template #content>
      <div class="article-publish-status__popover">
        <div
          v-if="publishRecordsQuery.isPending.value || platformsQuery.isPending.value"
          class="article-publish-status__loading"
        >
          <a-spin size="small" />
          <span>{{ t('common.loading') }}</span>
        </div>

        <div v-else-if="popoverSections.length" class="article-publish-status__sections">
          <section
            v-for="section in popoverSections"
            :key="section.key"
            class="article-publish-status__section"
          >
            <header
              class="article-publish-status__section-title"
              :class="`article-publish-status__section-title--${section.tone}`"
            >
              <span class="article-publish-status__section-dot" />
              <span>{{ section.label }}</span>
            </header>

            <div class="article-publish-status__platforms">
              <a-popover
                v-for="entry in section.entries"
                :key="entry.key"
                placement="top"
                overlay-class-name="article-publish-status__account-popover"
              >
                <template #content>
                  <div class="article-publish-status__account-card">
                    <span class="article-publish-status__account-avatar">
                      <img
                        v-if="entry.avatarUrl"
                        :src="entry.avatarUrl"
                        :alt="entry.accountName"
                        class="article-publish-status__account-avatar-img"
                        referrerpolicy="no-referrer"
                      />
                      <template v-else-if="getAccountInitial(entry.accountName)">
                        {{ getAccountInitial(entry.accountName) }}
                      </template>
                      <UserOutlined v-else />
                    </span>
                    <span class="article-publish-status__account-name">
                      {{ entry.accountName }}
                    </span>
                  </div>
                </template>

                <div
                  class="article-publish-status__platform-chip"
                  :class="`article-publish-status__platform-chip--${section.tone}`"
                >
                  <span
                    class="article-publish-status__platform-mark"
                    :style="{ background: entry.accent }"
                  >
                    {{ entry.shortName }}
                  </span>
                  <span class="article-publish-status__platform-name">{{ entry.name }}</span>
                </div>
              </a-popover>
            </div>
          </section>
        </div>

        <span v-else class="article-publish-status__empty">
          {{ t('media.records.empty') }}
        </span>
      </div>
    </template>

    <span class="article-publish-status__trigger">
      <span
        class="article-publish-status__badge"
        :class="`article-publish-status__badge--${statusTone}`"
      >
        <span class="article-publish-status__badge-dot" />
        <span>{{ statusMeta.label }}</span>
        <QuestionCircleOutlined class="article-publish-status__icon" />
      </span>
    </span>
  </a-popover>

  <span
    v-else
    class="article-publish-status__badge"
    :class="`article-publish-status__badge--${statusTone}`"
  >
    <span class="article-publish-status__badge-dot" />
    <span>{{ statusMeta.label }}</span>
  </span>
</template>

<style scoped>
.article-publish-status__trigger {
  display: inline-flex;
}

.article-publish-status__badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 3px 12px;
  border: 1px solid transparent;
  border-radius: 10px;
  font-size: 12px;
  font-weight: 600;
  line-height: 22px;
  white-space: nowrap;
  transition:
    border-color 0.2s ease,
    box-shadow 0.2s ease,
    transform 0.2s ease;
}

.article-publish-status__badge--success {
  background: #f4fbec;
  border-color: #b7eb8f;
  color: #4d6b18;
}

.article-publish-status__badge--failed {
  background: #fff3f0;
  border-color: #ffccc7;
  color: #cf1322;
}

.article-publish-status__badge--processing {
  background: #eff6ff;
  border-color: #bfdbfe;
  color: #1d4ed8;
}

.article-publish-status__badge--warning {
  background: #fff8e6;
  border-color: #ffd591;
  color: #ad6800;
}

.article-publish-status__badge--default {
  background: #f7f8fa;
  border-color: #d9d9d9;
  color: #595959;
}

.article-publish-status__badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  flex: 0 0 auto;
}

.article-publish-status__badge--success .article-publish-status__badge-dot,
.article-publish-status__section-title--success .article-publish-status__section-dot {
  background: #52c41a;
}

.article-publish-status__badge--failed .article-publish-status__badge-dot,
.article-publish-status__section-title--failed .article-publish-status__section-dot {
  background: #ff4d4f;
}

.article-publish-status__badge--processing .article-publish-status__badge-dot,
.article-publish-status__section-title--pending .article-publish-status__section-dot {
  background: #1677ff;
}

.article-publish-status__badge--warning .article-publish-status__badge-dot {
  background: #faad14;
}

.article-publish-status__badge--default .article-publish-status__badge-dot {
  background: #98a2b3;
}

.article-publish-status__icon {
  font-size: 13px;
  opacity: 0.72;
}

.article-publish-status__popover {
  min-width: 360px;
}

.article-publish-status__loading {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #667085;
  font-size: 13px;
}

.article-publish-status__sections {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.article-publish-status__section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.article-publish-status__section-title {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: #344054;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
}

.article-publish-status__section-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  flex: 0 0 auto;
}

.article-publish-status__platforms {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
}

.article-publish-status__platform-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 4px 12px 4px 4px;
  border-radius: 6px;
  background: #f9f9f9;
  border: 1px solid transparent;
  color: #141414;
  font-size: 14px;
  font-weight: 400;
  cursor: pointer;
  transition: all 0.2s ease;
}

.article-publish-status__platform-chip:hover {
  transform: translateY(-1px);
  background: #f0f0f0;
}

.article-publish-status__platform-chip--success:hover {
  background: #f0f0f0;
}

.article-publish-status__platform-chip--failed {
  background: #fffafa;
  border-color: #ffccc7;
}

.article-publish-status__platform-chip--failed:hover {
  border-color: rgba(255, 77, 79, 0.24);
}

.article-publish-status__platform-chip--pending {
  background: #f0f5ff;
  border-color: #d6e4ff;
}

.article-publish-status__platform-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 24px;
  padding: 0 4px;
  border-radius: 4px;
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  box-shadow: none;
}

.article-publish-status__platform-name {
  letter-spacing: 0.01em;
}

.article-publish-status__empty {
  color: #98a2b3;
  font-size: 13px;
}

.article-publish-status__account-card {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: auto;
  height: 30px;
  padding: 0 10px;
  background: #f8f9fa;
  border-radius: 4px;
}

.article-publish-status__account-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 4px;
  background: #f0f2f5;
  color: #1f2937;
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
}

.article-publish-status__account-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.article-publish-status__account-name {
  color: #344054;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.2;
}

:deep(.article-publish-status__popover-overlay .ant-popover-inner) {
  border-radius: 12px;
  padding: 16px 20px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
}

:deep(.article-publish-status__popover-overlay .ant-popover-inner-content) {
  padding: 0;
}

:deep(.article-publish-status__popover-overlay .ant-popover-arrow:before) {
  background: #fff;
}

:deep(.article-publish-status__account-popover .ant-popover-inner) {
  border-radius: 6px;
  padding: 6px 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

:deep(.article-publish-status__account-popover .ant-popover-inner-content) {
  color: #344054;
}

:deep(.article-publish-status__account-popover .ant-popover-arrow:before) {
  background: #fff;
}
</style>
