<template>
  <t-card title="💡 反馈运营看板" :bordered="false">
    <!-- 筛选栏 -->
    <div class="toolbar">
      <t-select v-model="filterFeedbackType" :options="feedbackTypeOptions" placeholder="全部类型" clearable size="small" style="width:140px;" />
      <t-select v-model="filterReasonCategory" :options="reasonCategoryOptions" placeholder="全部原因" clearable size="small" style="width:120px;" />
      <t-select v-model="filterProcessed" :options="processedOptions" placeholder="全部状态" clearable size="small" style="width:120px;" />
      <t-date-picker v-model="filterDate" size="small" style="width:240px;" placeholder="选择日期范围" />
      <t-button size="small" @click="loadList(1)">搜索</t-button>
      <t-button variant="outline" size="small" @click="loadList(1)">刷新</t-button>
    </div>

    <!-- 反馈列表 -->
    <t-table :data="feedbacks" :columns="columns" row-key="conversationId" :loading="loading"
      :pagination="{ current: page, total: total, pageSize: pageSize, showJumper: true }" @page-change="onPageChange"
      empty="暂无反馈数据，用户在 SDK 端对 AI 回复点赞或点踩后将在此展示。">
      <template #feedbackType="{ row }">
        <t-tag :theme="row.feedbackType === 'THUMBS_UP' ? 'success' : 'danger'" variant="light">
          {{ row.feedbackType === 'THUMBS_UP' ? '👍 有帮助' : '👎 没帮助' }}
        </t-tag>
      </template>
      <template #reasonCategory="{ row }">
        <t-tag v-if="row.reasonCategory" theme="warning" variant="light">{{ reasonLabel(row.reasonCategory) }}</t-tag>
        <span v-else>-</span>
      </template>
      <template #reasonComment="{ row }">
        <span v-if="row.reasonComment" :title="row.reasonComment" style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;">{{ truncate(row.reasonComment, 40) }}</span>
        <span v-else>-</span>
      </template>
      <template #processed="{ row }">
        <t-tag :theme="row.processed ? 'success' : 'default'" variant="light">{{ row.processed ? '已处理' : '待处理' }}</t-tag>
      </template>
      <template #userQuestion="{ row }">
        <span :title="row.userQuestion" style="max-width:250px;overflow:hidden;text-overflow:ellipsis;display:inline-block;">{{ truncate(row.userQuestion, 60) }}</span>
      </template>
      <template #assistantAnswer="{ row }">
        <span :title="row.assistantAnswer" style="max-width:250px;overflow:hidden;text-overflow:ellipsis;display:inline-block;">{{ truncate(row.assistantAnswer, 60) }}</span>
      </template>
      <template #op="{ row }">
        <t-space :size="4">
          <t-button size="small" variant="text" @click="viewDetail(row)">查看</t-button>
          <t-button size="small" variant="text" theme="primary" @click="createFaqFromRow(row)" v-if="row.feedbackType === 'THUMBS_UP'">生成 FAQ</t-button>
          <t-button size="small" variant="text" theme="warning" @click="openFaqAction(row)" v-if="row.feedbackType === 'THUMBS_DOWN'">关联 FAQ</t-button>
          <t-button size="small" variant="text" v-if="!row.processed" @click="markHandled(row)">标记已处理</t-button>
          <t-button size="small" variant="text" theme="danger" @click="removeFeedback(row)">删除</t-button>
        </t-space>
      </template>
    </t-table>

    <!-- 消息详情弹窗 -->
    <t-dialog v-model:visible="detailModal.visible" header="会话消息详情" width="800px" :footer="false">
      <div v-if="!detailModal.messages?.length"><t-empty /></div>
      <div v-else class="msg-list" style="max-height:400px;overflow-y:auto;">
        <div v-for="(msg, i) in detailModal.messages" :key="i" :class="['msg-item', msg.messageType === 'USER' ? 'msg-user' : msg.messageType === 'ASSISTANT' ? 'msg-assistant' : 'msg-system']">
          <div class="msg-meta">
            <t-tag size="small" :theme="msg.messageType === 'USER' ? 'primary' : msg.messageType === 'ASSISTANT' ? 'success' : 'default'" variant="light">
              {{ msg.messageType === 'USER' ? '用户' : msg.messageType === 'ASSISTANT' ? 'AI助手' : '系统' }}
            </t-tag>
            <t-tag v-if="msg.feedback" size="small" :theme="msg.feedback.feedbackType === 'THUMBS_UP' ? 'success' : 'danger'" variant="light">
              {{ msg.feedback.feedbackType === 'THUMBS_UP' ? '👍 有帮助' : '👎 没帮助' }}
              <span v-if="msg.feedback.reasonCategory"> · {{ reasonLabel(msg.feedback.reasonCategory) }}</span>
            </t-tag>
          </div>
          <div v-if="msg.feedback && msg.feedback.reasonComment" class="msg-comment">
            💬 补充说明：{{ msg.feedback.reasonComment }}
          </div>
          <div class="msg-body" v-html="msg.messageType === 'ASSISTANT' ? renderMarkdown(msg.content) : msg.content"></div>
        </div>
      </div>
    </t-dialog>

    <!-- FAQ 操作弹窗（复用） -->
    <t-dialog v-model:visible="faqModal.visible" :header="faqModal.title" width="600px" :footer="false">
      <t-form label-align="top">
        <t-form-item v-if="faqModal.mode === 'create'" label="标准问题 *"><t-input v-model="faqModal.question" /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'create'" label="标准答案 *"><t-textarea v-model="faqModal.answer" :autosize="{ minRows: 3, maxRows: 6 }" /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'append'" label="选择目标 FAQ"><t-select v-model="faqModal.targetFaqId" :options="faqOptions" placeholder="搜索并选择" filterable /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'append'" label="相似问法"><t-input v-model="faqModal.similarQuestion" /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'edit'" label="选择目标 FAQ"><t-select v-model="faqModal.targetFaqId" :options="faqOptions" placeholder="搜索并选择" filterable /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'edit'" label="修正后的答案"><t-textarea v-model="faqModal.answer" :autosize="{ minRows: 3, maxRows: 6 }" /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'create'" label="分类"><t-select v-model="faqModal.categoryId" :options="categorySelectOptions" placeholder="不分类" clearable /></t-form-item>
        <t-form-item v-if="faqModal.mode === 'create'" label="优先级"><t-input-number v-model="faqModal.priority" :min="0" style="width:100%;" /></t-form-item>
      </t-form>
      <div class="dialog-footer">
        <t-button variant="outline" @click="faqModal.visible = false">取消</t-button>
        <t-button theme="primary" @click="submitFaqAction" :disabled="!canSubmit">确定</t-button>
      </div>
    </t-dialog>
  </t-card>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { listFeedbackConversations, getFeedbackMessages, markFeedbackProcessed, deleteFeedback } from '@/api/feedback'
import { listFaqs, createFaqFromFeedback, appendFaqFromFeedback, editFaqFromFeedback } from '@/api/faq'
import { getCategoryTree } from '@/api/category'
import { useConfirm } from '@/composables/useConfirm'
import { toast } from '@/utils/toast'
import { renderMarkdown } from '@/utils/markdown'
import { formatDate } from '@/utils/format'

const { confirm } = useConfirm()

const filterFeedbackType = ref(''); const filterReasonCategory = ref(''); const filterProcessed = ref(''); const filterDate = ref('')
const feedbacks = ref<any[]>([]); const loading = ref(false)
const page = ref(1); const pageSize = ref(20); const total = ref(0)

const detailModal = ref({ visible: false, messages: [] as any[] })
const faqModal = ref<{
  visible: boolean; title: string; mode: 'create' | 'append' | 'edit';
  question: string; answer: string; similarQuestion: string;
  targetFaqId: string; categoryId: any; priority: number;
  sourceRow: any;
}>({ visible: false, title: '', mode: 'create', question: '', answer: '', similarQuestion: '', targetFaqId: '', categoryId: null, priority: 0, sourceRow: null })

const faqList = ref<any[]>([]); const flatCategories = ref<any[]>([])

const feedbackTypeOptions = [
  { label: '👍 有帮助', value: 'THUMBS_UP' },
  { label: '👎 没帮助', value: 'THUMBS_DOWN' },
]

const reasonCategoryOptions = [
  { label: '不准确', value: 'inaccurate' },
  { label: '不相关', value: 'irrelevant' },
  { label: '不完整', value: 'incomplete' },
  { label: '其他', value: 'other' },
]

const processedOptions = [
  { label: '待处理', value: 'false' },
  { label: '已处理', value: 'true' },
]

const columns = [
  { colKey: 'feedbackType', title: '反馈', width: 90, cell: 'feedbackType' },
  { colKey: 'reasonCategory', title: '原因', width: 80, cell: 'reasonCategory' },
  { colKey: 'reasonComment', title: '补充说明', width: 160, ellipsis: true, cell: 'reasonComment' },
  { colKey: 'userQuestion', title: '用户问题', width: 200, ellipsis: true, cell: 'userQuestion' },
  { colKey: 'assistantAnswer', title: 'AI 回复', width: 200, ellipsis: true, cell: 'assistantAnswer' },
  { colKey: 'processed', title: '状态', width: 70, cell: 'processed' },
  { colKey: 'feedbackTime', title: '时间', width: 150, cell: (_: any, { row }: any) => formatDate(row.feedbackTime) },
  { colKey: 'op', title: '操作', width: 240, cell: 'op' },
]

const canSubmit = computed(() => {
  const m = faqModal.value
  if (m.mode === 'create') return !!(m.question && m.answer)
  if (m.mode === 'append') return !!(m.targetFaqId && m.similarQuestion)
  if (m.mode === 'edit') return !!(m.targetFaqId && m.answer)
  return false
})

const categorySelectOptions = computed(() =>
  flatCategories.value.map((c: any) => ({ label: c.path || c.name, value: c.id }))
)

const faqOptions = computed(() =>
  faqList.value.map((f: any) => ({ label: f.question, value: String(f.id) }))
)

function reasonLabel(key: string): string {
  const map: Record<string, string> = { inaccurate: '不准确', irrelevant: '不相关', incomplete: '不完整', other: '其他' }
  return map[key] || key || '-'
}

function truncate(text: string, maxLen: number): string {
  if (!text) return ''
  return text.length > maxLen ? text.substring(0, maxLen) + '…' : text
}

/** 将后端返回的 snake_case 字段归一化为 camelCase，统一后续访问方式 */
function normalizeFeedbackRow(item: any): any {
  return {
    ...item,
    feedbackId: item.feedback_id || item.feedbackId,
    feedbackType: item.feedback_type || item.feedbackType,
    reasonCategory: item.reason_category || item.reasonCategory,
    reasonComment: item.reason_comment || item.reasonComment,
    feedbackTime: item.feedback_time || item.feedbackTime,
    userQuestion: item.user_question || item.userQuestion,
    assistantAnswer: item.assistant_answer || item.assistantAnswer,
    conversationId: item.conversation_id || item.conversationId,
  }
}

onMounted(() => { loadList(1); loadFaqList(); loadCategories() })

async function loadFaqList() { try { const r = await listFaqs(1, 100); if (r.success) faqList.value = r.data?.records || r.data || [] } catch {/* */} }

async function loadCategories() {
  try { const r = await getCategoryTree(); if (r.success) { flatCategories.value = flattenTree(r.data) } } catch {/* */}
}
function flattenTree(tree: any[], prefix = ''): any[] {
  const r: any[] = []
  for (const n of (tree || [])) { const p = prefix ? `${prefix}/${n.name}` : n.name; r.push({ id: n.id, name: n.name, path: p }); if (n.children?.length) r.push(...flattenTree(n.children, p)) }
  return r
}

async function loadList(p: number) {
  page.value = p; loading.value = true
  try {
    const params: Record<string, any> = { page: p, size: pageSize.value }
    if (filterFeedbackType.value) params.feedbackType = filterFeedbackType.value
    if (filterReasonCategory.value) params.reasonCategory = filterReasonCategory.value
    if (filterProcessed.value) params.processed = filterProcessed.value === 'true'
    if (filterDate.value) {
      // TDesign DatePicker 返回格式视配置而定，这里兼容数组和字符串
      if (Array.isArray(filterDate.value) && filterDate.value.length >= 2) {
        params.startDate = filterDate.value[0]
        params.endDate = filterDate.value[1]
      }
    }
    const r = await listFeedbackConversations(params)
    if (r.success) {
      feedbacks.value = (r.data?.records || []).map(normalizeFeedbackRow)
      total.value = r.data?.total || 0
    }
    else toast(r.message || '查询失败', 'error')
  } catch (e: any) { toast('加载失败：' + e.message, 'error') }
  finally { loading.value = false }
}

function onPageChange(i: { current: number; pageSize: number }) { pageSize.value = i.pageSize; loadList(i.current) }

async function viewDetail(row: any) {
  try {
    const r = await getFeedbackMessages(row.conversationId || row.conversation_id)
    detailModal.value.visible = true; detailModal.value.messages = r.data || []
  } catch (e: any) { toast('加载消息失败：' + e.message, 'error') }
}

async function markHandled(row: any) {
  const fbId = row.feedbackId || row.feedback_id
  if (!fbId) { toast('未找到反馈记录', 'error'); return }
  try {
    await markFeedbackProcessed(fbId, { remark: '手动标记已处理' })
    toast('已标记', 'success')
    loadList(page.value)
  } catch (e: any) { toast('操作失败：' + e.message, 'error') }
}

async function removeFeedback(row: any) {
  const fbId = row.feedbackId || row.feedback_id
  if (!fbId) { toast('未找到反馈记录', 'error'); return }
  if (!await confirm('确认删除该反馈记录？')) return
  try {
    const r = await deleteFeedback(fbId)
    if (r.success) { toast('删除成功', 'success'); loadList(page.value) }
    else toast(r.message || '删除失败', 'error')
  } catch (e: any) { toast('删除失败：' + e.message, 'error') }
}

function createFaqFromRow(row: any) {
  // 预填问题来自后端 SQL 中的 user_question / userQuestion 字段名
  faqModal.value = {
    visible: true, title: '从点赞反馈生成 FAQ', mode: 'create',
    question: truncate(row.userQuestion || row.user_question || '', 500),
    answer: row.assistantAnswer || row.assistant_answer || '',
    similarQuestion: '', targetFaqId: '', categoryId: null, priority: 0, sourceRow: row,
  }
}

function openFaqAction(row: any) {
  loadFaqList()
  const q = truncate(row.userQuestion || row.user_question || '', 500)
  if (row.reasonCategory === 'inaccurate' || row.reasonCategory === 'incomplete') {
    faqModal.value = {
      visible: true, title: '修正 FAQ 答案', mode: 'edit',
      question: '', answer: row.assistantAnswer || row.assistant_answer || '',
      similarQuestion: '', targetFaqId: '', categoryId: null, priority: 0, sourceRow: row,
    }
  } else {
    faqModal.value = {
      visible: true, title: '补充到已有 FAQ', mode: 'append',
      question: '', answer: '', similarQuestion: q,
      targetFaqId: '', categoryId: null, priority: 0, sourceRow: row,
    }
  }
}

async function submitFaqAction() {
  const m = faqModal.value
  const row = m.sourceRow
  const userQ = (row.userQuestion || row.user_question || '').substring(0, 500)
  const aiA = (row.assistantAnswer || row.assistant_answer || '').substring(0, 10000)
  const fbId = row.feedbackId || row.feedback_id
  try {
    if (m.mode === 'create') {
      const r = await createFaqFromFeedback({
        feedbackId: fbId,
        question: m.question, answer: m.answer,
        categoryId: m.categoryId, priority: m.priority,
        source: 'feedback_positive',
        originalQuestion: userQ, originalAnswer: aiA,
      })
      if (r.success) { toast('FAQ 创建成功', 'success'); faqModal.value.visible = false; loadList(page.value) }
      else toast(r.message || '创建失败', 'error')
    } else if (m.mode === 'append') {
      const r = await appendFaqFromFeedback(m.targetFaqId, {
        feedbackId: fbId, similarQuestion: m.similarQuestion, originalAnswer: aiA,
      })
      if (r.success) { toast('补充成功', 'success'); faqModal.value.visible = false; loadList(page.value) }
      else toast(r.message || '补充失败', 'error')
    } else if (m.mode === 'edit') {
      const r = await editFaqFromFeedback(m.targetFaqId, {
        feedbackId: fbId, answer: m.answer, originalQuestion: userQ,
      })
      if (r.success) { toast('修正成功', 'success'); faqModal.value.visible = false; loadList(page.value) }
      else toast(r.message || '修正失败', 'error')
    }
  } catch (e: any) { toast('操作失败：' + e.message, 'error') }
}
</script>
<style scoped>
.msg-item { padding: 12px; border-radius: 8px; margin-bottom: 12px; }
.msg-user { background: var(--color-info-bg); }
.msg-assistant { background: var(--color-bg-subtle); }
.msg-system { background: var(--color-warning-bg); }
.msg-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.msg-comment { font-size: 12px; color: var(--color-text-secondary, #666); background: var(--color-warning-bg); border-radius: 6px; padding: 6px 10px; margin-bottom: 6px; white-space: pre-wrap; word-break: break-word; }
.msg-body { font-size: 13px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
.dialog-footer { margin-top: 16px; display: flex; justify-content: flex-end; gap: 8px; }
</style>
