<template>
  <div class="work-detail-page">
    <a-spin :spinning="loading">
      <template v-if="work">
        <!-- 顶部 -->
        <div class="detail-header">
          <button class="back-btn" @click="$router.back()">
            <left-outlined />
          </button>
          <h1>{{ work.title }}</h1>
          <span :class="['status-tag', work.status]">{{ statusTextMap[work.status] }}</span>
        </div>

        <!-- 审核拒绝原因（仅作者 + rejected，置于内容区顶部便于阅读）-->
        <div v-if="isOwner && work.status === 'rejected'" class="reject-card">
          <warning-filled class="reject-icon" />
          <div class="reject-body">
            <div class="reject-title">审核拒绝原因</div>
            <div class="reject-content" :class="{ 'is-placeholder': !rejectReasonText }">
              {{ rejectReasonText || '审核方未填写具体原因，如有疑问请联系客服。' }}
            </div>
          </div>
        </div>

        <!-- 草稿提示（仅作者 + draft）-->
        <div v-else-if="isOwner && work.status === 'draft'" class="info-card draft-card">
          <info-circle-outlined class="info-icon" />
          <div class="info-body">
            <div class="info-title">这是一个未完成的草稿</div>
            <div class="info-desc">继续完成创作后才能公开发布</div>
          </div>
        </div>

        <!-- 未发布提示（仅作者 + unpublished）-->
        <div v-else-if="isOwner && work.status === 'unpublished'" class="info-card unpublished-card">
          <info-circle-outlined class="info-icon" />
          <div class="info-body">
            <div class="info-title">作品仅你自己可见</div>
            <div class="info-desc">点击下方「公开发布」提交审核，通过后将在「发现」页展示</div>
          </div>
        </div>

        <!-- 绘本阅读器 -->
        <div class="book-reader" v-if="work.pages && work.pages.length > 0">
          <div class="page-display">
            <img v-if="currentPageData?.imageUrl" :src="currentPageData.imageUrl" :alt="`第${currentPageIndex + 1}页`"
              class="page-image" />
            <div v-else class="page-placeholder">
              <picture-outlined />
            </div>
          </div>
          <div class="page-text" v-if="currentPageData?.text">
            {{ currentPageData.text }}
          </div>
          <div class="page-audio" v-if="currentPageData?.audioUrl">
            <audio :src="currentPageData.audioUrl" controls class="audio-player"></audio>
          </div>
          <div class="page-nav">
            <button class="nav-btn" :disabled="currentPageIndex === 0" @click="prevPage">
              <left-outlined />
            </button>
            <span class="page-indicator">{{ currentPageIndex + 1 }} / {{ work.pages.length }}</span>
            <button class="nav-btn" :disabled="currentPageIndex === work.pages.length - 1" @click="nextPage">
              <right-outlined />
            </button>
          </div>
        </div>

        <!-- 画作原图 -->
        <div v-if="work.originalImageUrl" class="original-card">
          <div class="original-thumb" @click="previewOriginal = work.originalImageUrl || ''">
            <img :src="work.originalImageUrl" alt="画作原图" />
            <div class="zoom-hint"><zoom-in-outlined /></div>
          </div>
          <div class="original-text">
            <div class="original-title">画作原图</div>
            <div class="original-desc">AI 根据这张画作生成的绘本</div>
          </div>
        </div>

        <!-- 作品信息 -->
        <div class="info-section">
          <div class="author-row">
            <a-avatar :size="36" :src="work.creator?.avatar">
              {{ work.creator?.nickname?.charAt(0) }}
            </a-avatar>
            <div class="author-info">
              <span class="author-name">{{ work.creator?.nickname }}</span>
              <span class="create-time">{{ formatDate(work.createTime) }}</span>
            </div>
          </div>
          <div v-if="work.description" class="description">{{ work.description }}</div>
          <div v-if="work.tags?.length" class="tags-row">
            <span v-for="t in work.tags" :key="t.tag.id" class="info-tag">{{ t.tag.name }}</span>
          </div>
        </div>

        <!-- 互动栏：仅在已发布作品上显示 -->
        <div v-if="work.status === 'published'" class="interaction-bar">
          <div :class="['action-btn', { active: interaction.liked }]" @click="handleLike">
            <heart-filled v-if="interaction.liked" />
            <heart-outlined v-else />
            <span>{{ displayLikeCount }}</span>
          </div>
          <div :class="['action-btn', { active: interaction.favorited }]" @click="handleFavorite">
            <star-filled v-if="interaction.favorited" />
            <star-outlined v-else />
            <span>{{ displayFavoriteCount }}</span>
          </div>
          <div class="action-btn">
            <eye-outlined />
            <span>{{ work.viewCount || 0 }}</span>
          </div>
        </div>

        <!-- 作者私有操作 -->
        <div v-if="isOwner" class="owner-actions">
          <!-- 主操作：根据 status 切换 -->
          <button v-if="work.status === 'unpublished'" class="op-btn primary" :disabled="actionLoading"
            @click="handlePublish">
            <send-outlined />
            <span>提交审核</span>
          </button>

          <button v-else-if="work.status === 'rejected'" class="op-btn primary" :disabled="actionLoading"
            @click="handleResubmit">
            <send-outlined />
            <span>修改后重交</span>
          </button>

          <button v-else-if="work.status === 'draft'" class="op-btn primary" :disabled="actionLoading"
            @click="handleContinue">
            <edit-outlined />
            <span>编辑</span>
          </button>

          <button v-else-if="work.status === 'pending_review'" class="op-btn outline" :disabled="actionLoading"
            @click="handleWithdraw">
            <undo-outlined />
            <span>撤回审核</span>
          </button>

          <button v-else-if="work.status === 'published'" class="op-btn outline" :disabled="actionLoading"
            @click="handleUnpublish">
            <inbox-outlined />
            <span>下架</span>
          </button>

          <!-- 删除（审核中、已发布不可删）-->
          <button
            v-if="canDeleteWork"
            class="op-btn ghost-danger"
            :disabled="actionLoading"
            @click="handleDelete"
          >
            <delete-outlined />
            <span>删除</span>
          </button>
        </div>
      </template>

      <a-empty v-else-if="!loading" description="作品不存在" style="padding: 80px 0" />
    </a-spin>

    <!-- 二次确认弹窗 -->
    <a-modal v-model:open="confirmVisible" :title="confirmTitle" :ok-text="confirmOkText" cancel-text="取消"
      :confirm-loading="actionLoading" @ok="handleConfirmOk" @cancel="handleConfirmCancel">
      <p>{{ confirmContent }}</p>
    </a-modal>

    <!-- 原图全屏预览 -->
    <Transition name="fade">
      <div v-if="previewOriginal" class="preview-overlay" @click="previewOriginal = ''">
        <img :src="previewOriginal" class="preview-full-img" alt="画作原图" />
      </div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { message } from 'ant-design-vue'
import {
  LeftOutlined, RightOutlined,
  HeartOutlined, HeartFilled,
  StarOutlined, StarFilled,
  EyeOutlined,
  PictureOutlined,
  WarningFilled,
  InfoCircleOutlined,
  SendOutlined,
  EditOutlined,
  UndoOutlined,
  InboxOutlined,
  DeleteOutlined,
  ZoomInOutlined,
} from '@ant-design/icons-vue'
import {
  publicUserWorksApi,
  publicGalleryApi,
  publicInteractionApi,
  publicCreationApi,
  type UserWork,
} from '@/api/public'
import dayjs from 'dayjs'

const route = useRoute()
const router = useRouter()
const workId = Number(route.params.id)

const work = ref<UserWork | null>(null)
const loading = ref(true)
const currentPageIndex = ref(0)
const interaction = ref({ liked: false, favorited: false })
const actionLoading = ref(false)
const previewOriginal = ref('')

const currentPageData = computed(() => work.value?.pages?.[currentPageIndex.value] || null)

const isLoggedIn = computed(() => !!localStorage.getItem('public_token'))

/** 当前登录公众用户 ID（与 Login 写入的 public_user 一致） */
function getPublicUserId(): number | null {
  const raw = localStorage.getItem('public_user')
  if (!raw || raw === 'undefined' || raw === 'null') return null
  try {
    const id = (JSON.parse(raw) as { id?: unknown }).id
    if (id == null) return null
    const n = Number(id)
    return Number.isFinite(n) ? n : null
  } catch {
    return null
  }
}

/**
 * 作品作者 sys_user id。
 * 「我的作品库」详情经 normalize 后有顶层 userId；广场 GET /public/gallery/{id} 仅返回 creator/user，无 userId 字段。
 */
function resolveWorkOwnerUserId(w: UserWork): number | null {
  if (typeof w.userId === 'number' && !Number.isNaN(w.userId)) return w.userId
  const c = w.creator?.id
  if (typeof c === 'number' && !Number.isNaN(c)) return c
  return null
}

const isOwner = computed(() => {
  const uid = getPublicUserId()
  const oid = work.value ? resolveWorkOwnerUserId(work.value) : null
  if (uid == null || oid == null) return false
  return uid === oid
})

/** 审核中、已发布（上架）不可删除，需先撤回审核或下架 */
const canDeleteWork = computed(() => {
  const s = work.value?.status
  if (!s) return false
  return s !== 'pending_review' && s !== 'published'
})

/** 与 POST /content-review/works/{id}/reject 的 `reason`（+ 可选 `note`）写入的 review_note 一致 */
const rejectReasonText = computed(() => {
  const w = work.value
  if (!w || w.status !== 'rejected') return ''
  const raw = w.reviewNote ?? (w as unknown as { review_note?: string }).review_note
  return typeof raw === 'string' ? raw.trim() : ''
})

const displayLikeCount = computed(() => work.value?.likeCount || 0)
const displayFavoriteCount = computed(() => work.value?.favoriteCount || 0)

const statusTextMap: Record<string, string> = {
  draft: '草稿',
  unpublished: '未发布',
  pending_review: '审核中',
  published: '已发布',
  rejected: '被拒绝',
  taken_down: '已下架',
}

const formatDate = (d: string) => dayjs(d).format('YYYY-MM-DD')

/** 从接口对象上解析乐读派 remoteWorkId（兼容 camelCase / snake_case） */
function pickRemoteWorkId(obj: Record<string, unknown> | null | undefined): string | null {
  if (!obj) return null
  const v = obj.remoteWorkId ?? obj.remote_work_id
  if (v == null || v === '') return null
  const s = String(v).trim()
  return s || null
}

/** 从 ai_meta 中解析乐读派作品 ID（与创作流程落库字段对齐） */
function pickRemoteWorkIdFromAiMeta(aiMeta: unknown): string | null {
  if (aiMeta == null) return null
  let o: Record<string, unknown>
  if (typeof aiMeta === 'string') {
    try {
      o = JSON.parse(aiMeta) as Record<string, unknown>
    } catch {
      return null
    }
  } else if (typeof aiMeta === 'object') {
    o = aiMeta as Record<string, unknown>
  } else {
    return null
  }
  const v =
    o.remoteWorkId ??
    o.remote_work_id ??
    o.workId ??
    o.work_id ??
    o.leaiWorkId
  if (v == null || v === '') return null
  const s = String(v).trim()
  return s || null
}

/**
 * 解析乐读派 remoteWorkId（与创作页 resume 一致：必须为乐读派 workId，不能误用本地数字 id）。
 * 顺序：详情字段 → aiMeta → GET /public/creation/{本地id}/status
 */
async function resolveLeaiRemoteWorkId(w: UserWork): Promise<string | null> {
  const fromRow = pickRemoteWorkId(w as unknown as Record<string, unknown>)
  if (fromRow) return fromRow
  const fromMeta = pickRemoteWorkIdFromAiMeta(w.aiMeta)
  if (fromMeta) return fromMeta
  const localId = typeof w.id === 'number' && !Number.isNaN(w.id) ? w.id : null
  if (localId == null) return null
  try {
    const st = await publicCreationApi.getStatus(localId)
    const rw = st?.remoteWorkId
    if (rw != null && String(rw).trim()) return String(rw).trim()
  } catch {
    /* 忽略，由调用方提示 */
  }
  return null
}

/** 作品库详情接口可能返回 { work, pages }，与广场扁平结构统一 */
function normalizeMyWorkDetail(raw: unknown): UserWork | null {
  if (!raw || typeof raw !== 'object') return null
  const o = raw as Record<string, unknown>
  if (o.work && typeof o.work === 'object') {
    const w = o.work as Record<string, unknown>
    const pages = (Array.isArray(o.pages) ? o.pages : []).map((p: unknown) => {
      const row = p as Record<string, unknown>
      return {
        id: row.id as number,
        workId: (row.workId ?? w.id) as number,
        pageNo: row.pageNo as number,
        imageUrl: (row.imageUrl ?? null) as string | null,
        text: (row.text ?? null) as string | null,
        audioUrl: (row.audioUrl ?? null) as string | null,
      }
    })
    const rw = pickRemoteWorkId(w)
    const base = { ...(w as unknown as UserWork), pages }
    if (rw && !base.remoteWorkId) base.remoteWorkId = rw
    const rn = w.reviewNote ?? w.review_note
    if (typeof rn === 'string' && rn) base.reviewNote = rn
    return base
  }
  return raw as UserWork
}

/** 详情接口扁平或嵌套返回时，统一补齐 remoteWorkId */
function ensureRemoteWorkIdOnWork(raw: unknown, w: UserWork | null) {
  if (!w || !raw || typeof raw !== 'object') return
  if (w.remoteWorkId) return
  const o = raw as Record<string, unknown>
  const nested = o.work && typeof o.work === 'object' ? (o.work as Record<string, unknown>) : null
  const rw = pickRemoteWorkId(nested) || pickRemoteWorkId(o)
  if (rw) w.remoteWorkId = rw
}

const prevPage = () => { if (currentPageIndex.value > 0) currentPageIndex.value-- }
const nextPage = () => { if (work.value?.pages && currentPageIndex.value < work.value.pages.length - 1) currentPageIndex.value++ }

// ─── 互动 ───
const handleLike = async () => {
  if (!isLoggedIn.value) { router.push('/p/login'); return }
  if (actionLoading.value) return
  actionLoading.value = true
  const wasLiked = interaction.value.liked
  interaction.value.liked = !wasLiked
  if (work.value) work.value.likeCount = (work.value.likeCount || 0) + (wasLiked ? -1 : 1)
  try {
    const res = await publicInteractionApi.like(workId)
    interaction.value.liked = res.liked
    if (work.value) work.value.likeCount = res.likeCount
  } catch {
    interaction.value.liked = wasLiked
    if (work.value) work.value.likeCount = (work.value.likeCount || 0) + (wasLiked ? 1 : -1)
    message.error('操作失败')
  } finally {
    actionLoading.value = false
  }
}

const handleFavorite = async () => {
  if (!isLoggedIn.value) { router.push('/p/login'); return }
  if (actionLoading.value) return
  actionLoading.value = true
  const wasFavorited = interaction.value.favorited
  interaction.value.favorited = !wasFavorited
  if (work.value) work.value.favoriteCount = (work.value.favoriteCount || 0) + (wasFavorited ? -1 : 1)
  try {
    const res = await publicInteractionApi.favorite(workId)
    interaction.value.favorited = res.favorited
    if (work.value) work.value.favoriteCount = res.favoriteCount
  } catch {
    interaction.value.favorited = wasFavorited
    if (work.value) work.value.favoriteCount = (work.value.favoriteCount || 0) + (wasFavorited ? 1 : -1)
    message.error('操作失败')
  } finally {
    actionLoading.value = false
  }
}

// ─── 作者操作 ───

/** 提交审核：unpublished → pending_review */
async function handlePublish() {
  if (!work.value) return
  actionLoading.value = true
  try {
    await publicUserWorksApi.publish(workId)
    work.value.status = 'pending_review'
    message.success('已提交审核，等待超管确认')
  } catch (e: any) {
    message.error(e.message || '提交审核失败')
  } finally {
    actionLoading.value = false
  }
}

/** 修改后重交：rejected → 编辑信息页 */
async function handleResubmit() {
  if (!work.value) return
  actionLoading.value = true
  try {
    const rw = await resolveLeaiRemoteWorkId(work.value)
    if (!rw) {
      message.warning('暂无乐读派作品信息，请从创作流程进入')
      return
    }
    work.value.remoteWorkId = rw
    router.push(`/p/create/edit-info/${encodeURIComponent(rw)}`)
  } finally {
    actionLoading.value = false
  }
}

/** 草稿编辑：带乐读派 resumeWorkId 进入欢迎页，与 resumeLeaiWorkFromApi 对齐（先解析再跳转，避免把本地 id 当乐读派 id） */
async function handleContinue() {
  if (!work.value) return
  actionLoading.value = true
  try {
    const rw = await resolveLeaiRemoteWorkId(work.value)
    if (rw) {
      work.value.remoteWorkId = rw
      router.push({ name: 'PublicCreateWelcome', query: { resumeWorkId: rw } })
      return
    }
    message.warning('暂无乐读派作品信息，将打开创作首页')
    router.push({ name: 'PublicCreateWelcome' })
  } finally {
    actionLoading.value = false
  }
}

/** 撤回审核：pending_review → unpublished */
function handleWithdraw() {
  showConfirm(
    '撤回审核',
    '撤回后作品将回到「未发布」状态，可继续编辑或重新提交审核',
    '确认撤回',
    async () => {
      if (!work.value) return
      actionLoading.value = true
      try {
        await publicUserWorksApi.withdraw(workId)
        work.value.status = 'unpublished'
        message.success('已撤回审核')
      } catch (e: any) {
        message.error(e.message || '撤回失败')
      } finally {
        actionLoading.value = false
      }
    },
  )
}

/** 下架作品：published → unpublished */
function handleUnpublish() {
  showConfirm(
    '下架作品',
    '下架后作品将从「发现」页移除，回到「未发布」状态。下架后仍可重新提交审核',
    '确认下架',
    async () => {
      if (!work.value) return
      actionLoading.value = true
      try {
        await publicUserWorksApi.unpublish(workId)
        work.value.status = 'unpublished'
        work.value.publishTime = null
        message.success('已下架')
      } catch (e: any) {
        message.error(e.message || '下架失败')
      } finally {
        actionLoading.value = false
      }
    },
  )
}

/** 删除作品 */
function handleDelete() {
  if (!work.value || !canDeleteWork.value) {
    message.warning('审核中或已上架的作品不可删除，请先撤回审核或下架后再试')
    return
  }
  showConfirm(
    '删除作品',
    '删除后无法恢复，确认要删除这个作品吗？',
    '确认删除',
    async () => {
      actionLoading.value = true
      try {
        await publicUserWorksApi.delete(workId)
        message.success('已删除')
        router.push('/p/works')
      } catch (e: any) {
        message.error(e.message || '删除失败')
      } finally {
        actionLoading.value = false
      }
    },
  )
}

// ─── 二次确认弹窗 ───
const confirmVisible = ref(false)
const confirmTitle = ref('')
const confirmContent = ref('')
const confirmOkText = ref('确认')
let confirmHandler: (() => Promise<void>) | null = null

function showConfirm(title: string, content: string, okText: string, handler: () => Promise<void>) {
  confirmTitle.value = title
  confirmContent.value = content
  confirmOkText.value = okText
  confirmHandler = handler
  confirmVisible.value = true
}
async function handleConfirmOk() {
  if (confirmHandler) {
    await confirmHandler()
    confirmHandler = null
  }
  confirmVisible.value = false
}
function handleConfirmCancel() {
  confirmVisible.value = false
  confirmHandler = null
}

// ─── 加载作品 ───
const fetchWork = async () => {
  loading.value = true

  try {
    // 优先尝试广场接口（公开作品），失败再尝试自己作品库
    try {
      const rawGallery = await publicGalleryApi.detail(workId)
      work.value = rawGallery as UserWork
      ensureRemoteWorkIdOnWork(rawGallery, work.value)
    } catch {
      const raw = await publicUserWorksApi.detail(workId)
      work.value = normalizeMyWorkDetail(raw) ?? (raw as UserWork)
      ensureRemoteWorkIdOnWork(raw, work.value)
    }
    if (isLoggedIn.value) {
      try {
        interaction.value = await publicInteractionApi.getInteraction(workId)
      } catch { /* 忽略 */ }
    }
  } catch {
    message.error('获取作品详情失败')
  } finally {
    loading.value = false
  }
}

onMounted(fetchWork)
</script>

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

.work-detail-page {
  max-width: 600px;
  margin: 0 auto;
  padding-bottom: 24px;
}

/* ---------- 顶部 ---------- */
.detail-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;

  h1 {
    font-size: 17px;
    font-weight: 700;
    color: #1e1b4b;
    margin: 0;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.back-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba($primary, 0.08);
  color: $primary;
  border: none;
  cursor: pointer;
  transition: all 0.2s;
  flex-shrink: 0;

  :deep(.anticon) {
    font-size: 15px;
  }

  &:hover {
    background: rgba($primary, 0.14);
  }
}

.status-tag {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.3px;

  &.draft {
    background: rgba(107, 114, 128, 0.85);
  }

  &.unpublished {
    background: rgba(99, 102, 241, 0.9);
  }

  &.pending_review {
    background: rgba(245, 158, 11, 0.92);
  }

  &.published {
    background: rgba(16, 185, 129, 0.92);
  }

  &.rejected {
    background: rgba(239, 68, 68, 0.92);
  }

  &.taken_down {
    background: rgba(107, 114, 128, 0.85);
  }
}

/* ---------- 拒绝原因 / 信息提示卡片 ---------- */
.reject-card,
.info-card {
  display: flex;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 14px;
  margin-bottom: 14px;
}

.reject-card {
  background: rgba(239, 68, 68, 0.06);
  border: 1px solid rgba(239, 68, 68, 0.2);
}

.reject-icon {
  font-size: 18px;
  color: #ef4444;
  flex-shrink: 0;
  margin-top: 2px;
}

.reject-body {
  flex: 1;
}

.reject-title {
  font-size: 13px;
  font-weight: 700;
  color: #b91c1c;
  margin-bottom: 4px;
}

.reject-content {
  font-size: 13px;
  color: #4b5563;
  line-height: 1.6;

  &.is-placeholder {
    color: #9ca3af;
    font-style: italic;
  }
}

.info-card {
  background: linear-gradient(135deg, rgba($primary, 0.08), rgba($accent, 0.05));
  border: 1px solid rgba($primary, 0.15);
}

.info-icon {
  font-size: 18px;
  color: $primary;
  flex-shrink: 0;
  margin-top: 2px;
}

.info-body {
  flex: 1;
}

.info-title {
  font-size: 13px;
  font-weight: 700;
  color: #1e1b4b;
  margin-bottom: 3px;
}

.info-desc {
  font-size: 12px;
  color: #6b7280;
  line-height: 1.6;
}

/* ---------- 画作原图卡片 ---------- */
.original-card {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #fff;
  border: 1px solid rgba($primary, 0.06);
  border-radius: 16px;
  padding: 14px;
  margin-bottom: 14px;
  box-shadow: 0 2px 12px rgba($primary, 0.05);
}

.original-thumb {
  position: relative;
  width: 84px;
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  overflow: hidden;
  border: 2px solid rgba($primary, 0.18);
  cursor: zoom-in;
  flex-shrink: 0;
  background: #f5f3ff;
  transition: all 0.2s;

  &:hover {
    border-color: $primary;
    transform: scale(1.03);

    .zoom-hint {
      opacity: 1;
    }
  }

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .zoom-hint {
    position: absolute;
    inset: 0;
    background: rgba(15, 12, 41, 0.4);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    opacity: 0;
    transition: opacity 0.2s;
  }
}

.original-text {
  flex: 1;
  min-width: 0;
}

.original-title {
  font-size: 14px;
  font-weight: 700;
  color: #1e1b4b;
  margin-bottom: 4px;
}

.original-desc {
  font-size: 12px;
  color: #6b7280;
  line-height: 1.5;
}

/* ---------- 全屏原图预览 ---------- */
.preview-overlay {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: rgba(15, 12, 41, 0.88);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}

.preview-full-img {
  max-width: 90%;
  max-height: 80vh;
  object-fit: contain;
  border-radius: 16px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* ---------- 绘本阅读器 ---------- */
.book-reader {
  background: #fff;
  border-radius: 16px;
  overflow: hidden;
  margin-bottom: 14px;
  border: 1px solid rgba($primary, 0.06);
  box-shadow: 0 2px 12px rgba($primary, 0.05);

  .page-display {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 200px;
    background: #1e1b4b;

    .page-image {
      display: block;
      max-width: 100%;
      width: auto;
      height: auto;
      max-height: min(72vh, 85vw);
      object-fit: contain;
    }

    .page-placeholder {
      display: flex;
      align-items: center;
      justify-content: center;
      min-height: 200px;
      width: 100%;
      color: rgba(255, 255, 255, 0.3);
      font-size: 36px;
    }
  }

  .page-text {
    padding: 16px 20px;
    font-size: 14px;
    line-height: 1.8;
    color: #374151;
    border-top: 1px solid rgba($primary, 0.06);
  }

  .page-audio {
    padding: 0 20px 12px;

    .audio-player {
      width: 100%;
      height: 36px;
    }
  }

  .page-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 20px;
    border-top: 1px solid rgba($primary, 0.06);

    .nav-btn {
      width: 34px;
      height: 34px;
      border-radius: 50%;
      border: 1px solid rgba($primary, 0.2);
      background: #fff;
      color: $primary;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      transition: all 0.2s;

      :deep(.anticon) {
        font-size: 14px;
      }

      &:hover:not(:disabled) {
        border-color: $primary;
        background: rgba($primary, 0.04);
      }

      &:disabled {
        opacity: 0.35;
        cursor: not-allowed;
      }
    }

    .page-indicator {
      font-size: 13px;
      color: #6b7280;
      font-weight: 600;
      letter-spacing: 0.5px;
    }
  }
}

/* ---------- 作品信息 ---------- */
.info-section {
  background: #fff;
  border-radius: 16px;
  padding: 16px 18px;
  border: 1px solid rgba($primary, 0.06);
  box-shadow: 0 2px 12px rgba($primary, 0.05);
  margin-bottom: 14px;

  .author-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;

    .author-info {
      display: flex;
      flex-direction: column;
    }

    .author-name {
      font-size: 14px;
      font-weight: 600;
      color: #1e1b4b;
    }

    .create-time {
      font-size: 11px;
      color: #9ca3af;
    }
  }

  .description {
    font-size: 13px;
    color: #4b5563;
    line-height: 1.7;
    margin-bottom: 10px;
  }

  .tags-row {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
  }

  .info-tag {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 10px;
    background: rgba($primary, 0.08);
    color: $primary;
    font-size: 11px;
    font-weight: 600;
    border: 1px solid rgba($primary, 0.15);
  }
}

/* ---------- 互动栏 ---------- */
.interaction-bar {
  display: flex;
  justify-content: space-around;
  margin-bottom: 14px;
  background: #fff;
  border-radius: 16px;
  padding: 12px 0;
  border: 1px solid rgba($primary, 0.06);
  box-shadow: 0 2px 12px rgba($primary, 0.05);

  .action-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 18px;
    border-radius: 22px;
    font-size: 18px;
    color: #9ca3af;
    cursor: pointer;
    transition: all 0.2s;
    user-select: none;

    span {
      font-size: 13px;
      font-weight: 500;
    }

    &:hover {
      background: rgba($primary, 0.04);
      color: #6b7280;
    }

    &.active {
      color: $accent;

      &:hover {
        background: rgba($accent, 0.06);
      }
    }

    &.active :deep(.anticon) {
      animation: pop 0.3s ease;
    }
  }
}

@keyframes pop {
  0% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.3);
  }

  100% {
    transform: scale(1);
  }
}

/* ---------- 作者私有操作区 ---------- */
.owner-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  background: #fff;
  border-radius: 16px;
  padding: 14px 16px;
  border: 1px solid rgba($primary, 0.06);
  box-shadow: 0 2px 12px rgba($primary, 0.05);
}

.op-btn {
  flex: 1;
  min-width: 100px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 11px 12px;
  border-radius: 20px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;

  :deep(.anticon) {
    font-size: 13px;
  }

  &:active {
    transform: scale(0.97);
  }

  &:disabled {
    opacity: 0.4;
    pointer-events: none;
  }
}

.op-btn.primary {
  background: linear-gradient(135deg, $primary 0%, $accent 100%);
  color: #fff;
  border: none;
  box-shadow: 0 4px 14px rgba($primary, 0.32);

  &:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba($primary, 0.4);
  }
}

.op-btn.outline {
  background: #fff;
  color: $primary;
  border: 1.5px solid rgba($primary, 0.4);

  &:hover {
    border-color: $primary;
    background: rgba($primary, 0.04);
  }
}

.op-btn.outline-soft {
  background: rgba($primary, 0.04);
  color: $primary;
  border: 1px solid rgba($primary, 0.2);

  &:hover {
    background: rgba($primary, 0.08);
    border-color: rgba($primary, 0.4);
  }
}

.op-btn.ghost-danger {
  flex: 0 0 auto;
  min-width: 0;
  padding: 11px 16px;
  background: transparent;
  color: #ef4444;
  border: 1px solid rgba(239, 68, 68, 0.2);

  &:hover {
    background: rgba(239, 68, 68, 0.04);
    border-color: rgba(239, 68, 68, 0.4);
  }
}
</style>
