<template>
  <div class="container">
    <section class="hero fade-up">
      <div class="hero-badge">PUBLISH HISTORY</div>
      <h1 class="hero-title">个人发布历史</h1>
      <p class="hero-sub">查看公开/私有/私信发布结果，被拦截内容可在线提交申诉。</p>
    </section>

    <section class="card fade-up fade-up-delay-1">
      <div class="card-title">筛选条件</div>
      <div class="grid-2">
        <div class="field">
          <label class="field-label">发布状态</label>
          <select class="select" v-model="statusFilter" @change="fetchList()">
            <option v-for="opt in statusOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
          </select>
        </div>
        <div class="field">
          <label class="field-label">发布类型</label>
          <select class="select" v-model="visibilityFilter" @change="fetchList()">
            <option v-for="opt in visibilityOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
          </select>
        </div>
      </div>
    </section>

    <section class="card fade-up fade-up-delay-2" v-if="list.length">
      <div class="card-title">历史记录</div>

      <div class="list-item" v-for="item in list" :key="item.id">
        <div class="item-title">{{ item.text }}</div>
        <div class="item-sub">类型：{{ item.visibility_text }} · 时间：{{ item.created_text }}</div>

        <div class="row">
          <span class="label">发布状态</span>
          <span :class="item.status === 'blocked' ? 'status-spam' : 'status-ham'">
            {{ item.status === 'blocked' ? '已拦截' : '已发布' }}
          </span>
        </div>

        <div class="row" v-if="item.category_label">
          <span class="label">分类标签</span>
          <span class="status-spam">{{ item.category_label }}</span>
        </div>

        <div class="row">
          <span class="label">垃圾概率</span>
          <span class="value">{{ item.spam_probability_text }}</span>
        </div>
        <div class="progress-track">
          <div class="progress-fill" :style="{ width: item.spam_probability_text }"></div>
        </div>

        <div class="row">
          <span class="label">申诉状态</span>
          <span class="value">{{ item.appeal_status_text }}</span>
        </div>

        <div class="field" v-if="item.reason_tokens && item.reason_tokens.length">
          <span class="field-label">风险关键词</span>
          <div class="chip-group">
            <span
              v-for="(tk, i) in item.reason_tokens"
              :key="i"
              class="tag tag-danger"
              @click="showTokenWeight(tk)"
            >{{ tk.token }}</span>
          </div>
        </div>

        <div
          v-if="item.status === 'blocked' && item.appeal_status !== 'pending' && appealPostId !== item.id"
        >
          <button class="btn btn-accent" @click="startAppeal(item.id)">发起申诉</button>
        </div>

        <div v-if="appealPostId === item.id" style="margin-top: 12px;">
          <div class="field">
            <label class="field-label">申诉理由类型</label>
            <select class="select" v-model="appealReasonTypeValue" @change="onReasonTypeChange">
              <option v-for="opt in appealReasonTypeOptions" :key="opt.label" :value="opt.value">{{ opt.label }}</option>
            </select>
          </div>
          <textarea
            class="textarea"
            v-model="appealReason"
            placeholder="可补充申诉理由（选择快捷理由后可省略）"
          ></textarea>
          <div class="field">
            <label class="field-label">证据截图（最多 3 张）</label>
            <div class="evidence-grid">
              <div class="evidence-item" v-for="(file, idx) in appealEvidenceFiles" :key="idx">
                <img class="evidence-thumb" :src="file.preview" alt="evidence" />
                <div class="evidence-remove" @click="removeEvidence(idx)">×</div>
              </div>
              <label class="evidence-add" v-if="appealEvidenceFiles.length < 3">
                <span class="evidence-add-icon">+</span>
                <input type="file" accept="image/*" @change="onPickEvidence" />
              </label>
            </div>
          </div>
          <div class="btn-row">
            <button class="btn btn-primary" :disabled="appealSubmitting" @click="submitAppeal">
              {{ appealSubmitting ? '提交中...' : '提交申诉' }}
            </button>
            <button class="btn btn-ghost" @click="cancelAppeal">取消</button>
          </div>
        </div>

        <button class="btn btn-ghost btn-sm" style="margin-top: 12px;" @click="removeItem(item.id)">删除记录</button>
      </div>
    </section>

    <section class="card fade-up fade-up-delay-2" v-else>
      <div class="empty">{{ loading ? '加载中...' : '暂无发布记录，先去「发布」页面提交文本。' }}</div>
    </section>
  </div>
</template>

<script>
import { request, uploadFile } from '@/utils/request'
import { toast, confirm } from '@/utils/feedback'

const STATUS_OPTIONS = [
  { value: '', label: '全部状态' },
  { value: 'published', label: '发布成功' },
  { value: 'blocked', label: '已拦截' }
]

const VISIBILITY_OPTIONS = [
  { value: '', label: '全部类型' },
  { value: 'public', label: '公开' },
  { value: 'private', label: '私有' },
  { value: 'direct', label: '私信' }
]

const VIS_LABEL = { public: '公开信息', private: '私有信息', direct: '用户私信' }
const APPEAL_STATUS_TEXT = { none: '未发起', pending: '处理中', approved: '已通过', rejected: '已驳回' }
const CATEGORY_LABELS = { fraud: '疑似诈骗', harassment: '疑似骚扰', advertisement: '疑似广告', spam: '疑似垃圾' }

const REASON_TYPE_OPTIONS = [
  { value: '', label: '请选择申诉理由类型' },
  { value: '正常活动文案', label: '正常活动文案' },
  { value: '正常社区通知', label: '正常社区通知' },
  { value: '私信沟通内容', label: '私信沟通内容' },
  { value: '__other__', label: '其他（需手动填写）' }
]

export default {
  name: 'HistoryView',
  data() {
    return {
      loading: false,
      list: [],
      statusOptions: STATUS_OPTIONS,
      visibilityOptions: VISIBILITY_OPTIONS,
      appealReasonTypeOptions: REASON_TYPE_OPTIONS,
      statusFilter: '',
      visibilityFilter: '',
      appealPostId: null,
      appealReasonTypeValue: '',
      appealReason: '',
      appealEvidenceFiles: [],
      appealSubmitting: false
    }
  },
  mounted() {
    this.fetchList()
  },
  beforeDestroy() {
    this.appealEvidenceFiles.forEach((f) => f.preview && URL.revokeObjectURL(f.preview))
  },
  methods: {
    formatPercent(value, digits = 2) {
      return `${(Number(value || 0) * 100).toFixed(digits)}%`
    },
    async fetchList() {
      this.loading = true
      try {
        const data = await request({
          url: '/content/posts/history',
          params: {
            status: this.statusFilter,
            visibility: this.visibilityFilter,
            page: 1,
            page_size: 80
          }
        })
        this.list = (data.items || []).map((item) => ({
          ...item,
          created_text: (item.created_at || '').replace('T', ' ').slice(0, 19),
          spam_probability_text: this.formatPercent(item.spam_probability, 2),
          visibility_text: VIS_LABEL[item.visibility] || item.visibility,
          appeal_status_text: APPEAL_STATUS_TEXT[item.appeal_status] || item.appeal_status,
          category_label: CATEGORY_LABELS[item.category] || ''
        }))
      } finally {
        this.loading = false
      }
    },
    startAppeal(postId) {
      this.cleanEvidencePreviews()
      this.appealPostId = postId
      this.appealReasonTypeValue = ''
      this.appealReason = ''
      this.appealEvidenceFiles = []
    },
    cancelAppeal() {
      this.cleanEvidencePreviews()
      this.appealPostId = null
      this.appealReasonTypeValue = ''
      this.appealReason = ''
      this.appealEvidenceFiles = []
    },
    onReasonTypeChange() {
      // "其他" 不写入 reason_type 字段，让用户手动填写理由
    },
    cleanEvidencePreviews() {
      this.appealEvidenceFiles.forEach((f) => f.preview && URL.revokeObjectURL(f.preview))
    },
    onPickEvidence(e) {
      const files = Array.from(e.target.files || [])
      const remaining = 3 - this.appealEvidenceFiles.length
      const toAdd = files.slice(0, remaining).map((file) => ({
        file,
        preview: URL.createObjectURL(file)
      }))
      this.appealEvidenceFiles = [...this.appealEvidenceFiles, ...toAdd]
      e.target.value = ''
    },
    removeEvidence(idx) {
      const item = this.appealEvidenceFiles[idx]
      if (item && item.preview) URL.revokeObjectURL(item.preview)
      this.appealEvidenceFiles.splice(idx, 1)
    },
    async uploadAllEvidence() {
      const urls = []
      for (const item of this.appealEvidenceFiles) {
        try {
          const res = await uploadFile(item.file)
          if (res && res.url) urls.push(res.url)
        } catch (err) {
          // toast already shown by uploadFile
        }
      }
      return urls
    },
    async submitAppeal() {
      const postId = this.appealPostId
      if (!postId) return
      const rt = this.appealReasonTypeValue
      const reasonType = rt && rt !== '__other__' ? rt : ''
      const reason = (this.appealReason || '').trim()
      if (!reasonType && reason.length < 2) {
        toast('申诉理由至少 2 个字符', 'error')
        return
      }
      this.appealSubmitting = true
      try {
        const evidenceUrls = await this.uploadAllEvidence()
        await request({
          url: `/content/posts/${postId}/appeal`,
          method: 'POST',
          data: { reason_type: reasonType, reason, evidence_urls: evidenceUrls }
        })
        toast('申诉提交成功', 'success')
        this.cancelAppeal()
        this.fetchList()
      } finally {
        this.appealSubmitting = false
      }
    },
    showTokenWeight(tk) {
      const w = Number(tk.weight || 0)
      const direction = w >= 0 ? '倾向垃圾判定' : '倾向正常判定'
      confirm({
        title: '关键词权重',
        content: `关键词「${tk.token}」\n权重贡献：${w >= 0 ? '+' : ''}${w.toFixed(4)}\n（${direction}）`,
        showCancel: false,
        confirmText: '关闭'
      })
    },
    async removeItem(id) {
      const { confirm: ok } = await confirm({
        title: '删除确认',
        content: '确定删除这条发布记录吗？',
        confirmText: '删除',
        cancelText: '取消'
      })
      if (!ok) return
      await request({ url: `/content/posts/${id}`, method: 'DELETE' })
      toast('删除成功', 'success')
      this.fetchList()
    }
  }
}
</script>
