<template>
  <div class="gallery-page">
    <!-- 搜索栏 -->
    <div class="search-bar">
      <a-input
        v-model:value="keyword"
        placeholder="搜索作品..."
        allow-clear
        @press-enter="handleSearch"
      >
        <template #prefix><search-outlined /></template>
      </a-input>
    </div>

    <!-- 推荐作品 -->
    <div class="recommend-section" v-if="recommendedWorks.length > 0">
      <div class="section-header">
        <span class="section-title"><fire-outlined /> 编辑推荐</span>
      </div>
      <div class="recommend-scroll">
        <div
          v-for="rw in recommendedWorks"
          :key="rw.id"
          class="recommend-card"
          @click="$router.push(`/p/works/${rw.id}`)"
        >
          <div class="recommend-cover">
            <img v-if="rw.coverUrl" :src="rw.coverUrl" :alt="rw.title" />
            <div v-else class="recommend-cover-empty"><picture-outlined /></div>
          </div>
          <div class="recommend-info">
            <span class="recommend-title">{{ rw.title }}</span>
            <span class="recommend-author">{{ rw.creator?.nickname }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 热门标签 -->
    <div class="tags-scroll" v-if="hotTags.length > 0">
      <span
        v-for="tag in hotTags"
        :key="tag.id"
        :class="['tag-chip', { active: selectedTagId === tag.id }]"
        @click="selectTag(tag.id)"
      >
        {{ tag.name }}
      </span>
    </div>

    <!-- 排序 -->
    <div class="sort-bar">
      <span
        :class="['sort-item', { active: sortBy === 'latest' }]"
        @click="changeSort('latest')"
      >最新</span>
      <span
        :class="['sort-item', { active: sortBy === 'hot' }]"
        @click="changeSort('hot')"
      >最热</span>
    </div>

    <!-- 作品网格 -->
    <div v-if="loading && works.length === 0" class="loading-wrap"><a-spin /></div>

    <div v-else-if="works.length === 0" class="empty-wrap">
      <a-empty description="还没有作品，快来创作吧">
        <a-button type="primary" shape="round" @click="$router.push('/p/create')">开始创作</a-button>
      </a-empty>
    </div>

    <div v-else class="works-grid">
      <div
        v-for="work in works"
        :key="work.id"
        class="work-card"
        @click="$router.push(`/p/works/${work.id}`)"
      >
        <div class="card-cover">
          <img v-if="work.coverUrl" :src="work.coverUrl" :alt="work.title" />
          <div v-else class="cover-placeholder">
            <picture-outlined />
          </div>
        </div>
        <div class="card-body">
          <h3>{{ work.title }}</h3>
          <div class="card-author">
            <a-avatar :size="20" :src="work.creator?.avatar">
              {{ work.creator?.nickname?.charAt(0) }}
            </a-avatar>
            <span>{{ work.creator?.nickname }}</span>
          </div>
          <div class="card-stats">
            <span
              :class="['like-btn', { liked: likedSet.has(work.id) }]"
              @click.stop="handleLike(work)"
            >
              <heart-filled v-if="likedSet.has(work.id)" />
              <heart-outlined v-else />
              {{ work.likeCount || 0 }}
            </span>
            <span><eye-outlined /> {{ work.viewCount || 0 }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 加载更多 -->
    <div v-if="hasMore" class="load-more">
      <a-button :loading="loading" shape="round" @click="loadMore">加载更多</a-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { message } from 'ant-design-vue'
import { SearchOutlined, PictureOutlined, HeartOutlined, HeartFilled, EyeOutlined, FireOutlined } from '@ant-design/icons-vue'
import { publicGalleryApi, publicTagsApi, publicInteractionApi, type UserWork, type WorkTag } from '@/api/public'

const router = useRouter()
const works = ref<UserWork[]>([])
const hotTags = ref<WorkTag[]>([])
const recommendedWorks = ref<UserWork[]>([])
const loading = ref(false)
const keyword = ref('')
const selectedTagId = ref<number | null>(null)
const sortBy = ref('latest')
const page = ref(1)
const total = ref(0)
const pageSize = 12
const likedSet = reactive(new Set<number>())

const isLoggedIn = computed(() => !!localStorage.getItem('public_token'))
const hasMore = computed(() => works.value.length < total.value)

const fetchTags = async () => {
  try { hotTags.value = await publicTagsApi.hot() } catch { /* */ }
}

const fetchRecommended = async () => {
  try { recommendedWorks.value = await publicGalleryApi.recommended() } catch { /* */ }
}

const fetchWorks = async (reset = false) => {
  if (reset) { page.value = 1; works.value = []; likedSet.clear() }
  loading.value = true
  try {
    const res = await publicGalleryApi.list({
      page: page.value,
      pageSize,
      sortBy: sortBy.value,
      tagId: selectedTagId.value || undefined,
      keyword: keyword.value || undefined,
    })
    if (reset) {
      works.value = res.list
    } else {
      works.value.push(...res.list)
    }
    total.value = res.total
    // 已登录时批量查询点赞状态
    if (isLoggedIn.value && res.list.length > 0) {
      try {
        const ids = res.list.map((w: any) => w.id)
        const statuses = await publicInteractionApi.batchStatus(ids)
        for (const [id, status] of Object.entries(statuses)) {
          if ((status as any).liked) likedSet.add(Number(id))
        }
      } catch { /* 忽略 */ }
    }
  } catch { /* */ }
  finally { loading.value = false }
}

const handleLike = async (work: any) => {
  if (!isLoggedIn.value) { router.push('/p/login'); return }
  const wasLiked = likedSet.has(work.id)
  // 乐观更新
  if (wasLiked) { likedSet.delete(work.id) } else { likedSet.add(work.id) }
  work.likeCount = (work.likeCount || 0) + (wasLiked ? -1 : 1)
  try {
    const res = await publicInteractionApi.like(work.id)
    if (res.liked) { likedSet.add(work.id) } else { likedSet.delete(work.id) }
    work.likeCount = res.likeCount
  } catch {
    // 回滚
    if (wasLiked) { likedSet.add(work.id) } else { likedSet.delete(work.id) }
    work.likeCount = (work.likeCount || 0) + (wasLiked ? 1 : -1)
    message.error('操作失败')
  }
}

const handleSearch = () => fetchWorks(true)
const selectTag = (tagId: number) => {
  selectedTagId.value = selectedTagId.value === tagId ? null : tagId
  fetchWorks(true)
}
const changeSort = (s: string) => { sortBy.value = s; fetchWorks(true) }
const loadMore = () => { page.value++; fetchWorks() }

onMounted(() => {
  fetchRecommended()
  fetchTags()
  fetchWorks()
})
</script>

<style scoped lang="scss">
$primary: #6366f1;

.gallery-page {
  max-width: 700px;
  margin: 0 auto;
}

.search-bar {
  margin-bottom: 14px;
  :deep(.ant-input-affix-wrapper) {
    border-radius: 24px;
    padding: 8px 16px;
    border-color: rgba($primary, 0.15);
    &:focus, &:hover { border-color: $primary; }
  }
}

// 推荐作品
.recommend-section {
  margin-bottom: 16px;

  .section-header {
    margin-bottom: 10px;
    .section-title {
      font-size: 15px;
      font-weight: 700;
      color: #1e1b4b;
      display: flex;
      align-items: center;
      gap: 6px;

      :deep(.anticon) { color: #f59e0b; }
    }
  }
}

.recommend-scroll {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 8px;
  -webkit-overflow-scrolling: touch;
  &::-webkit-scrollbar { display: none; }
}

.recommend-card {
  flex-shrink: 0;
  width: 120px;
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.2s;
  border: 1px solid rgba($primary, 0.06);

  &:hover { box-shadow: 0 4px 16px rgba($primary, 0.12); transform: translateY(-2px); }

  .recommend-cover {
    width: 120px; height: 160px; background: #f5f3ff;
    img { width: 100%; height: 100%; object-fit: cover; }
    .recommend-cover-empty { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 24px; color: #d1d5db; }
  }

  .recommend-info {
    padding: 8px 10px;
    display: flex; flex-direction: column; gap: 2px;

    .recommend-title { font-size: 12px; font-weight: 600; color: #1e1b4b; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .recommend-author { font-size: 10px; color: #9ca3af; }
  }
}

.tags-scroll {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 12px;
  margin-bottom: 8px;
  -webkit-overflow-scrolling: touch;

  &::-webkit-scrollbar { display: none; }

  .tag-chip {
    padding: 4px 14px;
    border-radius: 16px;
    font-size: 12px;
    background: #f3f4f6;
    color: #6b7280;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.2s;
    flex-shrink: 0;

    &.active { background: $primary; color: #fff; }
    &:hover:not(.active) { background: #e5e7eb; }
  }
}

.sort-bar {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;

  .sort-item {
    font-size: 13px;
    color: #9ca3af;
    cursor: pointer;
    padding-bottom: 4px;
    transition: all 0.2s;

    &.active {
      color: $primary;
      font-weight: 600;
      border-bottom: 2px solid $primary;
    }
  }
}

.loading-wrap, .empty-wrap {
  padding: 60px 0;
  display: flex;
  justify-content: center;
}

.works-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;

  @media (min-width: 640px) { grid-template-columns: repeat(3, 1fr); }
}

.work-card {
  background: #fff;
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.2s;
  border: 1px solid rgba($primary, 0.04);

  &:hover { box-shadow: 0 4px 20px rgba($primary, 0.1); transform: translateY(-2px); }

  .card-cover {
    aspect-ratio: 3/4;
    background: #f5f3ff;
    img { width: 100%; height: 100%; object-fit: cover; }
    .cover-placeholder { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 28px; color: #d1d5db; }
  }

  .card-body {
    padding: 10px 12px;

    h3 { font-size: 13px; font-weight: 600; color: #1e1b4b; margin: 0 0 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    .card-author {
      display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
      span { font-size: 11px; color: #6b7280; }
    }

    .card-stats {
      display: flex; gap: 12px;
      span { font-size: 11px; color: #9ca3af; display: flex; align-items: center; gap: 3px; }

      .like-btn {
        cursor: pointer;
        transition: color 0.2s;
        &:hover { color: #ec4899; }
        &.liked {
          color: #ec4899;
          :deep(.anticon) { animation: pop 0.3s ease; }
        }
      }
    }
  }
}

.load-more {
  text-align: center;
  padding: 20px 0;
}

@keyframes pop {
  0% { transform: scale(1); }
  50% { transform: scale(1.3); }
  100% { transform: scale(1); }
}
</style>
