<template>
  <view class="page">
    <NavBar title="公告中心" :showBack="true" @back="goBack" />

    <!-- 顶部分类区 -->
    <view class="hero">
      <view class="hero-row">
        <view class="bell-icon"></view>
        <view class="hero-text">
          <text class="hero-title">公告中心</text>
          <text class="hero-count">共 {{ total }} 条</text>
        </view>
      </view>

      <scroll-view scroll-x class="filter-scroll" :show-scrollbar="false">
        <view class="filter-row">
          <view
            class="filter-chip"
            :class="{ on: currentType === 0 }"
            @click="changeType(0)"
          >
            <text>全部</text>
          </view>
          <view
            class="filter-chip"
            :class="{ on: currentType === 1 }"
            @click="changeType(1)"
          >
            <text>系统</text>
          </view>
          <view
            class="filter-chip"
            :class="{ on: currentType === 2 }"
            @click="changeType(2)"
          >
            <text>活动</text>
          </view>
          <view
            class="filter-chip"
            :class="{ on: currentType === 3 }"
            @click="changeType(3)"
          >
            <text>维护</text>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 列表 -->
    <scroll-view
      class="list-scroll"
      scroll-y
      @scrolltolower="loadMore"
    >
      <!-- 骨架屏 -->
      <view class="skeleton-set" v-if="loading && list.length === 0">
        <view class="sk-card" v-for="i in 4" :key="i">
          <view class="sk-top">
            <view class="sk-title"></view>
            <view class="sk-chevron"></view>
          </view>
          <view class="sk-meta"></view>
        </view>
      </view>

      <view class="card-set" v-else>
        <view
          class="card"
          v-for="item in filteredList"
          :key="item.id"
          @click="toggleExpand(item)"
        >
          <!-- 头部 -->
          <view class="card-top">
            <view class="card-left">
              <view class="pin" v-if="item.isTop === 1">
                <text>置顶</text>
              </view>
              <text class="card-title">{{ item.title }}</text>
            </view>
            <view class="chevron" :class="{ open: expandedId === item.id }">
              <view class="chevron-inner"></view>
            </view>
          </view>

          <!-- 元信息 -->
          <view class="card-meta">
            <view class="dot" :class="'dot-' + item.type"></view>
            <view class="badge" :class="'badge-' + item.type">
              <text>{{ typeMap[item.type] || '公告' }}</text>
            </view>
            <text class="meta-time">{{ formatTime(item.publishTime) }}</text>
            <text class="meta-read">{{ item.readCount || 0 }} 次阅读</text>
          </view>

          <!-- 展开内容 -->
          <view class="card-body" v-if="expandedId === item.id">
            <view class="body-rule"></view>
            <text class="body-text">{{ item.content || '暂无内容' }}</text>
            <image
              v-if="item.coverImage"
              :src="item.coverImage"
              mode="widthFix"
              class="body-image"
            />
          </view>
        </view>
      </view>

      <!-- 加载更多 -->
      <view class="load-tip" v-if="loading && list.length > 0">
        <view class="dot-row">
          <view class="pulse-dot"></view>
          <view class="pulse-dot"></view>
          <view class="pulse-dot"></view>
        </view>
      </view>

      <!-- 没有更多 -->
      <view class="end-tip" v-if="!hasMore && list.length > 0">
        <view class="end-line"></view>
        <text class="end-text">没有更多了</text>
        <view class="end-line"></view>
      </view>

      <!-- 空状态 -->
      <view class="empty" v-if="!loading && list.length === 0">
        <view class="empty-icon">
          <view class="doc">
            <view class="doc-body">
              <view class="doc-line" v-for="j in 3" :key="j"></view>
            </view>
            <view class="doc-fold"></view>
          </view>
        </view>
        <text class="empty-title">暂无公告</text>
        <text class="empty-desc">运营团队发布公告后将在这里展示</text>
      </view>
    </scroll-view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import NavBar from '@/components/NavBar.vue';
import { get } from '@/utils/request';

interface AnnouncementItem {
  id: string;
  title: string;
  content: string;
  type: number;
  coverImage?: string;
  isTop: number;
  status: number;
  publishTime: string;
  readCount: number;
}

const list = ref<AnnouncementItem[]>([]);
const loading = ref(false);
const expandedId = ref('');
const page = ref(1);
const total = ref(0);
const currentType = ref(0);
const pageSize = 10;
const hasMore = ref(true);

const typeMap: Record<number, string> = {
  1: '系统公告',
  2: '活动公告',
  3: '维护公告',
  4: '其他'
};

const filteredList = computed(() => {
  if (currentType.value === 0) return list.value;
  return list.value.filter(item => item.type === currentType.value);
});

const formatTime = (time: string) => {
  if (!time) return '';
  return time.substring(0, 16);
};

const goBack = () => {
  uni.navigateBack();
};

const toggleExpand = (item: AnnouncementItem) => {
  expandedId.value = expandedId.value === item.id ? '' : item.id;
};

const changeType = (type: number) => {
  if (currentType.value === type) return;
  currentType.value = type;
  page.value = 1;
  expandedId.value = '';
  hasMore.value = true;
  list.value = [];
  fetchList();
};

const fetchList = async (isLoadMore = false) => {
  if (loading.value) return;
  loading.value = true;

  try {
    const params: any = { status: 1, page: page.value, pageSize };
    if (currentType.value !== 0) {
      params.type = currentType.value;
    }
    const data: any = await get('/announcement/list', params);

    const newList = data?.list || [];
    total.value = data?.total || 0;

    if (isLoadMore) {
      list.value = [...list.value, ...newList];
    } else {
      list.value = newList;
    }
    hasMore.value = list.value.length < total.value;
  } catch (e) {
    // ignore
  } finally {
    loading.value = false;
  }
};

const loadMore = () => {
  if (!hasMore.value || loading.value) return;
  page.value++;
  fetchList(true);
};

onMounted(() => {
  fetchList();
});
</script>

<style lang="scss" scoped>
// ====== Design tokens (from DESIGN.md) ======
$ink: #2C2C2C;
$ash: #8C8C8C;
$cloud: #BDBDBD;
$white: #FFFFFF;
$cream: #FAFAFA;
$mist: #F5F5F5;
$border: #EEEEEE;

$yellow: #FFC107;
$yellow-light: #FFE082;
$yellow-dark: #FFA000;
$yellow-bg: #FFF8E1;

$green: #4CAF50;
$green-bg: #F1F8E9;
$orange: #FF9800;
$orange-bg: #FFF3E0;
$blue: #2196F3;
$blue-bg: #E3F2FD;
$gray: #9E9E9E;
$gray-bg: #FAFAFA;

$font-stack: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', system-ui, sans-serif;

// ====== Page ======
.page {
  min-height: 100vh;
  background: $cream;
  font-family: $font-stack;
  width: 100vw;
  overflow-x: hidden;
}

// ====== Hero ======
.hero {
  padding: 32rpx 32rpx 0;
}

.hero-row {
  display: flex;
  align-items: center;
  gap: 20rpx;
  margin-bottom: 24rpx;
}

.bell-icon {
  width: 48rpx;
  height: 48rpx;
  border-radius: 50%;
  background: $yellow-bg;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;

  &::before {
    content: '';
    width: 18rpx;
    height: 14rpx;
    background: $yellow;
    border-radius: 9rpx 9rpx 2rpx 2rpx;
  }
  &::after {
    content: '';
    position: absolute;
    width: 6rpx;
    height: 6rpx;
    background: $yellow;
    border-radius: 50%;
    top: 28rpx;
  }
}

.hero-text {
  display: flex;
  flex-direction: column;
  gap: 2rpx;
}

.hero-title {
  font-size: 40rpx;
  font-weight: 700;
  color: $ink;
  line-height: 1.2;
  letter-spacing: -0.3px;
}

.hero-count {
  font-size: 26rpx;
  color: $ash;
  letter-spacing: 0.2px;
}

// ====== Filter ======
.filter-scroll {
  white-space: nowrap;
  width: 100%;
}

.filter-row {
  display: flex;
  gap: 12rpx;
  padding-bottom: 8rpx;
  padding-right: 32rpx;
}

.filter-chip {
  padding: 12rpx 28rpx;
  border-radius: 40rpx;
  background: $white;
  border: 1rpx solid $border;
  display: inline-block;
  flex-shrink: 0;
  transition: background 0.2s ease, border-color 0.2s ease;

  text {
    font-size: 26rpx;
    font-weight: 500;
    color: $ash;
    transition: color 0.2s ease;
  }

  &.on {
    background: $yellow;
    border-color: $yellow;

    text {
      color: $ink;
      font-weight: 600;
    }
  }
}

// ====== List ======
.list-scroll {
  height: calc(100vh - 260rpx);
  padding: 16rpx 28rpx 48rpx;
  width: 100%;
  box-sizing: border-box;
}

// ====== Skeleton ======
.skeleton-set {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.sk-card {
  background: $white;
  border-radius: 24rpx;
  padding: 32rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
  animation: shimmer 1.5s infinite;
}

.sk-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16rpx;
}

.sk-title {
  flex: 1;
  height: 34rpx;
  background: linear-gradient(90deg, $mist 25%, #E8E8E8 50%, $mist 75%);
  background-size: 200% 100%;
  border-radius: 6rpx;
  animation: shimmer-bar 1.5s infinite;
}

.sk-chevron {
  width: 40rpx;
  height: 40rpx;
  border-radius: 50%;
  background: linear-gradient(90deg, $mist 25%, #E8E8E8 50%, $mist 75%);
  background-size: 200% 100%;
  animation: shimmer-bar 1.5s infinite;
  flex-shrink: 0;
}

.sk-meta {
  width: 45%;
  height: 26rpx;
  margin-top: 20rpx;
  background: linear-gradient(90deg, $mist 25%, #E8E8E8 50%, $mist 75%);
  background-size: 200% 100%;
  border-radius: 5rpx;
  animation: shimmer-bar 1.5s infinite;
}

@keyframes shimmer-bar {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

// ====== Cards ======
.card-set {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.card {
  background: $white;
  border-radius: 24rpx;
  padding: 32rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
  transition: opacity 0.15s ease;
  overflow: hidden;

  &:active {
    opacity: 0.7;
  }
}

// Card header
.card-top {
  display: flex;
  align-items: flex-start;
  gap: 16rpx;
}

.card-left {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 12rpx;
}

.pin {
  padding: 4rpx 12rpx;
  background: $yellow-bg;
  border-radius: 6rpx;
  margin-top: 2rpx;
  flex-shrink: 0;

  text {
    font-size: 20rpx;
    font-weight: 700;
    color: $yellow-dark;
    letter-spacing: 0.3px;
  }
}

.card-title {
  font-size: 30rpx;
  font-weight: 600;
  color: $ink;
  line-height: 1.5;
  letter-spacing: -0.1px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

// Chevron
.chevron {
  width: 40rpx;
  height: 40rpx;
  border-radius: 50%;
  background: $mist;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 2rpx;
  transition: background 0.2s ease;
}

.chevron-inner {
  width: 12rpx;
  height: 12rpx;
  border-right: 2rpx solid $cloud;
  border-bottom: 2rpx solid $cloud;
  transform: rotate(45deg);
  margin-top: -4rpx;
  transition: transform 0.2s ease, margin-top 0.2s ease;
}

.chevron.open .chevron-inner {
  transform: rotate(-135deg);
  margin-top: 4rpx;
}

// Meta row
.card-meta {
  display: flex;
  align-items: center;
  margin-top: 20rpx;
  gap: 10rpx;
}

.dot {
  width: 10rpx;
  height: 10rpx;
  border-radius: 50%;
  flex-shrink: 0;

  &.dot-1 { background: $blue; }
  &.dot-2 { background: $green; }
  &.dot-3 { background: $orange; }
  &.dot-4 { background: $gray; }
}

.badge {
  padding: 4rpx 14rpx;
  border-radius: 6rpx;
  flex-shrink: 0;

  text {
    font-size: 22rpx;
    font-weight: 500;
  }

  &.badge-1 { background: $blue-bg; text { color: $blue; } }
  &.badge-2 { background: $green-bg; text { color: $green; } }
  &.badge-3 { background: $orange-bg; text { color: $orange; } }
  &.badge-4 { background: $gray-bg; text { color: $gray; } }
}

.meta-time {
  font-size: 24rpx;
  color: $cloud;
  letter-spacing: 0.1px;
  flex-shrink: 0;
}

.meta-read {
  font-size: 24rpx;
  color: #C0C0C0;
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
}

// Expanded body
.card-body {
  margin-top: 24rpx;
  animation: reveal 0.2s ease-out;
}

@keyframes reveal {
  from {
    opacity: 0;
    transform: translateY(-8rpx);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.body-rule {
  height: 1rpx;
  background: $border;
  margin-bottom: 20rpx;
}

.body-text {
  font-size: 28rpx;
  color: #555;
  line-height: 1.75;
  letter-spacing: 0.1px;
  white-space: pre-wrap;
}

.body-image {
  margin-top: 16rpx;
  width: 100%;
  border-radius: 16rpx;
}

// ====== Load more ======
.load-tip {
  display: flex;
  justify-content: center;
  padding: 40rpx 0 24rpx;
}

.dot-row {
  display: flex;
  gap: 8rpx;
}

.pulse-dot {
  width: 10rpx;
  height: 10rpx;
  background: $cloud;
  border-radius: 50%;
  animation: pulse 1.2s ease-in-out infinite;

  &:nth-child(2) { animation-delay: 0.2s; }
  &:nth-child(3) { animation-delay: 0.4s; }
}

@keyframes pulse {
  0%, 80%, 100% { transform: scale(0.5); opacity: 0.4; }
  40% { transform: scale(1); opacity: 1; }
}

// ====== End ======
.end-tip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16rpx;
  padding: 40rpx 0 24rpx;
}

.end-line {
  width: 48rpx;
  height: 1rpx;
  background: $border;
}

.end-text {
  font-size: 24rpx;
  color: $cloud;
}

// ====== Empty ======
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 120rpx 0 80rpx;
  gap: 24rpx;
}

.empty-icon {
  width: 120rpx;
  height: 120rpx;
  border-radius: 50%;
  background: $mist;
  display: flex;
  align-items: center;
  justify-content: center;
}

.doc {
  position: relative;
  width: 48rpx;
  height: 56rpx;
}

.doc-body {
  position: absolute;
  left: 0;
  top: 0;
  width: 42rpx;
  height: 54rpx;
  background: $cloud;
  border-radius: 5rpx;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6rpx;
  padding: 10rpx 8rpx;
}

.doc-line {
  width: 20rpx;
  height: 3rpx;
  background: $cream;
  border-radius: 2rpx;

  &:first-child { width: 14rpx; }
  &:last-child { width: 10rpx; }
}

.doc-fold {
  position: absolute;
  right: 0;
  top: 0;
  width: 0;
  height: 0;
  border-left: 10rpx solid #D0D0D0;
  border-bottom: 10rpx solid transparent;
}

.empty-title {
  font-size: 30rpx;
  font-weight: 600;
  color: $ash;
}

.empty-desc {
  font-size: 26rpx;
  color: $cloud;
  letter-spacing: 0.2px;
}
</style>
