<template>
  <div style="max-width: 1400px">
    <n-space justify="space-between" align="center" style="margin-bottom: 20px">
      <div>
        <h1 style="margin: 0 0 4px; font-size: 20px; font-weight: 600; color: #111827">客户评价</h1>
        <p style="margin: 0; font-size: 13px; color: #9ca3af">管理客户评价 · 对应官网「客户评价」页面</p>
      </div>
      <n-space>
        <n-button tag="a" href="/reviews" target="_blank" secondary>查看前台</n-button>
        <n-button type="primary" @click="navigateTo('/admin/reviews/new')">新增评价</n-button>
      </n-space>
    </n-space>

    <n-card>
      <!-- 筛选栏 -->
      <div class="filter-row">
        <n-input
          v-model:value="search"
          placeholder="搜索客户、内容..."
          clearable
          style="width: 220px"
          @keyup.enter="resetAndLoad"
        >
          <template #prefix><span style="color: #9ca3af">&#128269;</span></template>
        </n-input>
        <n-select
          v-model:value="filters.published"
          :options="publishedFilterOptions"
          placeholder="发布状态"
          clearable
          style="width: 130px"
          @update:value="resetAndLoad"
        />
        <n-select
          v-model:value="filters.hasScreenshot"
          :options="screenshotFilterOptions"
          placeholder="截图"
          clearable
          style="width: 130px"
          @update:value="resetAndLoad"
        />
        <n-select
          v-model:value="filters.scene"
          :options="sceneOptions"
          placeholder="场景"
          clearable
          style="width: 150px"
          @update:value="resetAndLoad"
        />
        <n-select
          v-model:value="filters.concern"
          :options="concernOptions"
          placeholder="关心维度"
          clearable
          style="width: 150px"
          @update:value="resetAndLoad"
        />
        <n-button @click="resetAndLoad">搜索</n-button>
        <n-button quaternary @click="clearFilters">重置</n-button>
      </div>

      <!-- 批量操作工具栏 -->
      <div v-if="checkedIds.length" class="bulk-toolbar">
        <span class="bulk-count">已选 {{ checkedIds.length }} 条</span>
        <n-button size="small" @click="bulk('publish')">批量发布</n-button>
        <n-button size="small" @click="bulk('unpublish')">批量下线</n-button>
        <n-popconfirm @positive-click="bulk('delete')">
          <template #trigger>
            <n-button size="small" type="error">批量删除</n-button>
          </template>
          确定删除选中的 {{ checkedIds.length }} 条评价？
        </n-popconfirm>
        <n-button size="tiny" quaternary @click="checkedIds = []">清空选择</n-button>
      </div>

      <n-data-table
        :columns="columns"
        :data="list"
        :loading="loading"
        :row-key="(row) => row.id"
        v-model:checked-row-keys="checkedIds"
        :pagination="false"
        size="small"
        striped
      />

      <n-space justify="space-between" align="center" style="margin-top: 16px" v-if="total">
        <span style="color: #9ca3af; font-size: 12px;">共 {{ total }} 条</span>
        <n-pagination v-if="totalPages > 1" v-model:page="page" :page-count="totalPages" @update:page="loadData" />
      </n-space>
    </n-card>
  </div>
</template>

<script setup>
import { h } from 'vue'
import {
  NButton, NCard, NSpace, NInput, NDataTable, NTag, NPagination, NPopconfirm,
  NRate, NSelect, NInputNumber, useMessage,
} from 'naive-ui'

definePageMeta({ layout: 'admin', middleware: 'admin' })

const { adminFetch } = useAdmin()
const message = useMessage()
const { moveUp, moveDown } = useAdminSort('/api/admin/reviews')
const list = ref([])
const total = ref(0)
const page = ref(1)
const totalPages = ref(1)
const loading = ref(false)
const search = ref('')
const checkedIds = ref([])

const filters = reactive({
  published: null,
  hasScreenshot: null,
  scene: null,
  concern: null,
})

const publishedFilterOptions = [
  { label: '已发布', value: 'true' },
  { label: '草稿', value: 'false' },
]
const screenshotFilterOptions = [
  { label: '有截图', value: 'true' },
  { label: '无截图', value: 'false' },
]
const sceneOptions = [
  '家庭出游', '亲子', '带老人', '摄影', '蜜月', '毕业游', '多家庭',
].map(v => ({ label: v, value: v }))
const concernOptions = [
  '领队服务', '行程安排', '住宿体验', '摄影旅拍', '错峰不排队',
  '性价比', '安全放心', '特色体验', '饮食',
].map(v => ({ label: v, value: v }))

function clearFilters() {
  search.value = ''
  filters.published = null
  filters.hasScreenshot = null
  filters.scene = null
  filters.concern = null
  resetAndLoad()
}

function resetAndLoad() {
  page.value = 1
  loadData()
}

const columns = [
  { type: 'selection', width: 40 },
  { title: 'ID', key: 'id', width: 50, render: (row) => h('span', { style: 'color: #9ca3af; font-size: 12px' }, row.id) },
  {
    title: '截图', key: 'screenshot', width: 72,
    render: (row) => row.screenshot
      ? h('img', {
          src: row.screenshot,
          style: 'width: 48px; height: 48px; object-fit: cover; border-radius: 4px; cursor: pointer; border: 1px solid #e5e7eb;',
          referrerpolicy: 'no-referrer',
          onClick: () => window.open(row.screenshot, '_blank'),
        })
      : h('span', { style: 'color: #d1d5db; font-size: 11px;' }, '无图'),
  },
  {
    title: '客户', key: 'author', width: 100,
    render: (row) => h('a', {
      style: 'color: #111827; text-decoration: none; font-weight: 500; cursor: pointer',
      onClick: () => navigateTo(`/admin/reviews/${row.id}`),
    }, row.author),
  },
  {
    title: '评分', key: 'rating', width: 110,
    render: (row) => h(NRate, { value: row.rating || 5, readonly: true, size: 'small' }),
  },
  { title: '产品版本', key: 'title', width: 160, ellipsis: { tooltip: true } },
  {
    title: '内容摘要', key: 'content', minWidth: 200,
    render: (row) => h('span', { style: 'color: #6b7280; font-size: 12px' }, row.content?.slice(0, 60)),
  },
  {
    title: '标签', key: 'tags', width: 220,
    render: (row) => h('div', { style: 'display: flex; flex-wrap: wrap; gap: 4px;' }, [
      ...(row.scenes || []).map(s => h(NTag, { size: 'small', type: 'info', bordered: false }, () => s)),
      ...(row.concerns || []).map(c => h(NTag, { size: 'small', type: 'success', bordered: false }, () => c)),
    ]),
  },
  { title: '出行日期', key: 'date', width: 90, render: (row) => h('span', { style: 'color: #9ca3af; font-size: 12px' }, row.date) },
  {
    title: '排序', key: 'sortOrder', width: 140,
    render: (row, idx) => h(NSpace, { size: 4, align: 'center' }, () => [
      h(NInputNumber, {
        value: row.sortOrder || 0, size: 'tiny', min: 0, showButton: false,
        style: 'width: 52px;',
        'onUpdate:value': (v) => updateSortOrder(row, v),
      }),
      h(NButton, { size: 'tiny', disabled: idx === 0, onClick: async () => { await moveUp(list.value, idx); message.success('已上移') } }, () => '↑'),
      h(NButton, { size: 'tiny', disabled: idx === list.value.length - 1, onClick: async () => { await moveDown(list.value, idx); message.success('已下移') } }, () => '↓'),
    ]),
  },
  {
    title: '状态', key: 'published', width: 70,
    render: (row) => h(NTag, {
      size: 'small', type: row.published ? 'success' : 'default', bordered: false,
      style: 'cursor: pointer',
      onClick: () => togglePublish(row),
    }, () => row.published ? '已发布' : '草稿'),
  },
  {
    title: '操作', key: 'actions', width: 110, fixed: 'right',
    render: (row) => h(NSpace, { size: 'small' }, () => [
      h(NButton, { size: 'tiny', text: true, type: 'primary', onClick: () => navigateTo(`/admin/reviews/${row.id}`) }, () => '编辑'),
      h(NPopconfirm, { onPositiveClick: () => handleDelete(row) }, {
        trigger: () => h(NButton, { size: 'tiny', text: true, type: 'error' }, () => '删除'),
        default: () => `确定删除「${row.author}」的评价？`,
      }),
    ]),
  },
]

async function loadData() {
  loading.value = true
  try {
    const params = new URLSearchParams({
      page: page.value,
      limit: 20,
      search: search.value,
    })
    if (filters.published) params.set('published', filters.published)
    if (filters.hasScreenshot) params.set('hasScreenshot', filters.hasScreenshot)
    if (filters.scene) params.set('scene', filters.scene)
    if (filters.concern) params.set('concern', filters.concern)
    const d = await adminFetch(`/api/admin/reviews?${params}`)
    list.value = d.items
    total.value = d.total
    totalPages.value = d.totalPages
  } catch { message.error('加载失败') } finally { loading.value = false }
}

async function togglePublish(item) {
  try {
    await adminFetch(`/api/admin/reviews/${item.id}`, { method: 'PUT', body: { published: !item.published } })
    item.published = !item.published
  } catch { message.error('操作失败') }
}

async function updateSortOrder(item, value) {
  const v = Number(value) || 0
  item.sortOrder = v
  try {
    await adminFetch(`/api/admin/reviews/${item.id}`, { method: 'PUT', body: { sortOrder: v } })
  } catch { message.error('排序更新失败') }
}

async function handleDelete(item) {
  try {
    await adminFetch(`/api/admin/reviews/${item.id}`, { method: 'DELETE' })
    message.success('已删除')
    loadData()
  } catch { message.error('删除失败') }
}

async function bulk(action) {
  if (!checkedIds.value.length) return
  try {
    const res = await adminFetch('/api/admin/reviews/bulk', {
      method: 'POST',
      body: { action, ids: checkedIds.value },
    })
    message.success(`已${ {publish:'发布',unpublish:'下线',delete:'删除'}[action] } ${res.affected} 条`)
    checkedIds.value = []
    loadData()
  } catch { message.error('操作失败') }
}

onMounted(loadData)
</script>

<style scoped>
.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 16px;
}
.bulk-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  margin-bottom: 12px;
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  border-radius: 6px;
}
.bulk-count {
  font-size: 13px;
  font-weight: 500;
  color: #065f46;
  margin-right: 4px;
}
</style>
