<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { showToast } from 'vant'
import MobileBottomNav from '@/components/MobileBottomNav.vue'
import { fetchAnnouncements, type Announcement } from '@/features/announcement'
import { formatDateTime } from '@/shared/utils/time'

const router = useRouter()
const loading = ref(false)
const refreshing = ref(false)
const finished = ref(false)
const announcements = ref<Announcement[]>([])
const activeCategory = ref('')
const page = ref(1)
const pageSize = 12
const total = ref(0)
let announcementRequestSeq = 0

const categories = [
  { value: '', label: '全部', icon: 'apps-o' },
  { value: 'notice', label: '通知', icon: 'volume-o' },
  { value: 'tutorial', label: '教程', icon: 'description' },
  { value: 'rule', label: '规则', icon: 'warning-o' },
  { value: 'faq', label: '问答', icon: 'question-o' },
]

onMounted(() => {
  onRefresh()
})

async function loadAnnouncements(reset = false) {
  if ((loading.value && !reset) || (finished.value && !reset)) return
  const requestSeq = ++announcementRequestSeq
  if (reset) {
    page.value = 1
    finished.value = false
  }

  loading.value = true
  try {
    const result = await fetchAnnouncements({
      category: activeCategory.value || undefined,
      page: page.value,
      page_size: pageSize,
    })
    if (requestSeq !== announcementRequestSeq) return
    announcements.value = reset ? result.items : [...announcements.value, ...result.items]
    total.value = result.total
    if (announcements.value.length >= result.total || result.items.length === 0) {
      finished.value = true
    } else {
      page.value += 1
    }
  } catch {
    if (requestSeq !== announcementRequestSeq) return
    showToast({ message: '公告加载失败，请稍后重试', icon: 'cross' })
    finished.value = true
  } finally {
    if (requestSeq === announcementRequestSeq) {
      loading.value = false
      refreshing.value = false
    }
  }
}

function onRefresh() {
  refreshing.value = true
  loadAnnouncements(true)
}

function onLoad() {
  loadAnnouncements(false)
}

function selectCategory(category: string) {
  if (activeCategory.value === category) return
  activeCategory.value = category
  onRefresh()
}

function openDetail(id: number) {
  router.push(`/m/announcements/${id}`)
}

function getCategoryLabel(category: string) {
  return categories.find(item => item.value === category)?.label || '公告'
}

function previewText(content: string) {
  const text = content
    .replace(/[#>*_`[\]()!-]/g, '')
    .replace(/\s+/g, ' ')
    .trim()
  return text.length > 76 ? `${text.slice(0, 76)}...` : text
}
</script>

<template>
  <main class="mobile-announcements">
    <header class="page-header">
      <button class="back-btn" type="button" @click="router.back()">
        <van-icon name="arrow-left" :size="20" />
      </button>
      <h1>公告中心</h1>
      <span class="header-count">{{ total ? `${total}条` : '' }}</span>
    </header>

    <van-pull-refresh v-model="refreshing" class="scroll-container" @refresh="onRefresh">
      <section class="announcement-content">
        <div class="announcement-summary">
          <strong>平台公告</strong>
          <span>通知、教程、规则和常见问题</span>
        </div>

        <div class="category-strip" aria-label="公告分类">
          <button
            v-for="item in categories"
            :key="item.value"
            type="button"
            class="category-pill"
            :class="{ active: activeCategory === item.value }"
            @click="selectCategory(item.value)"
          >
            <van-icon :name="item.icon" :size="15" />
            <span>{{ item.label }}</span>
          </button>
        </div>

        <van-list
          v-model:loading="loading"
          :finished="finished"
          finished-text="没有更多公告了"
          :immediate-check="false"
          @load="onLoad"
        >
          <van-empty
            v-if="!loading && announcements.length === 0"
            class="empty-state"
            image="search"
            description="暂无公告"
          />

          <div v-else class="announcement-list">
            <button
              v-for="item in announcements"
              :key="item.id"
              class="announcement-card"
              type="button"
              @click="openDetail(item.id)"
            >
              <div class="card-top">
                <span class="category-tag">{{ getCategoryLabel(item.category) }}</span>
                <span v-if="item.is_pinned" class="state-tag pinned">置顶</span>
                <span v-if="item.is_important" class="state-tag important">重要</span>
                <van-icon class="card-arrow" name="arrow" :size="15" />
              </div>
              <h2>{{ item.title }}</h2>
              <p>{{ previewText(item.content) }}</p>
              <div class="card-footer">
                <span>{{ formatDateTime(item.published_at || item.created_at) }}</span>
                <span>浏览 {{ item.view_count }}</span>
              </div>
            </button>
          </div>
        </van-list>
      </section>
    </van-pull-refresh>

    <MobileBottomNav />
  </main>
</template>

<style scoped>
.mobile-announcements {
  min-height: 100dvh;
  padding-bottom: calc(62px + env(safe-area-inset-bottom));
  background: #f6f8fb;
  color: #17233d;
}

.page-header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: grid;
  grid-template-columns: 44px 1fr 72px;
  align-items: center;
  height: 48px;
  padding: 0 8px;
  border-bottom: 1px solid #edf0f5;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(10px);
}

.page-header h1 {
  margin: 0;
  color: #111827;
  font-size: 17px;
  font-weight: 800;
  text-align: center;
}

.back-btn {
  display: grid;
  width: 40px;
  height: 40px;
  place-items: center;
  border: 0;
  background: transparent;
  color: #374151;
}

.header-count {
  color: #ff6a00;
  font-size: 12px;
  font-weight: 800;
  text-align: right;
}

.scroll-container {
  min-height: calc(100dvh - 48px - 62px);
}

.announcement-content {
  display: grid;
  gap: 10px;
  padding: 12px;
}

.announcement-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px;
  border: 1px solid #fed7aa;
  border-radius: 8px;
  background: #fff7ed;
}

.announcement-summary strong {
  color: #9a3412;
  font-size: 16px;
}

.announcement-summary span {
  overflow: hidden;
  color: #c2410c;
  font-size: 12px;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.category-strip {
  display: flex;
  gap: 8px;
  margin: 0 -12px;
  padding: 0 12px 2px;
  overflow-x: auto;
  scrollbar-width: none;
}

.category-strip::-webkit-scrollbar {
  display: none;
}

.category-pill {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 12px;
  border: 1px solid #e2e8f0;
  border-radius: 999px;
  background: #fff;
  color: #64748b;
  font-size: 13px;
  font-weight: 800;
}

.category-pill.active {
  border-color: #ff6a00;
  background: #fff7ed;
  color: #c2410c;
}

.announcement-list {
  display: grid;
  gap: 10px;
}

.announcement-card {
  display: grid;
  width: 100%;
  gap: 8px;
  padding: 12px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
  color: inherit;
  text-align: left;
}

.card-top,
.card-footer {
  display: flex;
  align-items: center;
  gap: 6px;
}

.card-top {
  min-width: 0;
}

.category-tag,
.state-tag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
}

.category-tag {
  background: #fff7ed;
  color: #c2410c;
}

.state-tag.pinned {
  background: #fffbeb;
  color: #b45309;
}

.state-tag.important {
  background: #fef2f2;
  color: #dc2626;
}

.card-arrow {
  margin-left: auto;
  color: #cbd5e1;
}

.announcement-card h2 {
  margin: 0;
  overflow: hidden;
  color: #0f172a;
  font-size: 15px;
  font-weight: 900;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.announcement-card p {
  display: -webkit-box;
  min-height: 36px;
  margin: 0;
  overflow: hidden;
  color: #64748b;
  font-size: 12px;
  line-height: 1.5;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.card-footer {
  justify-content: space-between;
  color: #94a3b8;
  font-size: 11px;
  font-weight: 700;
}

.empty-state {
  padding-top: 54px;
}
</style>
