<template>
  <div class="audit-log">
    <h3 class="page-title">📜 操作日志</h3>

    <!-- Action Type Filters -->
    <div class="filter-row">
      <span class="filter-label">操作:</span>
      <button
        v-for="action in actionTypes"
        :key="action.value"
        class="filter-btn"
        :class="{ active: selectedAction === action.value }"
        @click="selectedAction = selectedAction === action.value ? '' : action.value"
      >{{ action.label }}</button>
    </div>

    <!-- User Filters -->
    <div class="filter-row" v-if="uniqueUsers.length > 1">
      <span class="filter-label">用户:</span>
      <button
        v-for="u in uniqueUsers"
        :key="u"
        class="filter-btn"
        :class="{ active: selectedUser === u }"
        @click="selectedUser = selectedUser === u ? '' : u"
      >{{ u }}</button>
    </div>

    <!-- Target Type Filters -->
    <div class="filter-row">
      <span class="filter-label">对象:</span>
      <button
        v-for="t in targetTypes"
        :key="t.value"
        class="filter-btn"
        :class="{ active: selectedTarget === t.value }"
        @click="selectedTarget = selectedTarget === t.value ? '' : t.value"
      >{{ t.label }}</button>
    </div>

    <!-- Log List -->
    <div class="log-list">
      <div v-for="log in filteredLogs" :key="log.id" class="log-item">
        <div class="log-header">
          <span class="log-action" :class="actionColorClass(log.action)">{{ actionLabel(log.action) }}</span>
          <span class="log-user">{{ log.user_name || log.username || '系统' }}</span>
          <span class="log-time">{{ formatTime(log.created_at) }}</span>
        </div>
        <div class="log-detail">
          <span v-if="log.target_name" class="log-target-name">{{ log.target_name }}</span>
          <span v-if="parsedDetail(log)" class="log-extra">{{ parsedDetail(log) }}</span>
          <button v-if="canUndo(log)" class="undo-btn" @click="undoAction(log)">↩ 撤销</button>
        </div>
      </div>
      <div v-if="filteredLogs.length === 0" class="empty-hint">暂无日志记录</div>
    </div>

    <!-- Load More -->
    <div v-if="hasMore" class="load-more">
      <button class="btn-outline" @click="loadMore" :disabled="loading">
        {{ loading ? '加载中...' : '加载更多' }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { api } from '../composables/useApi'
import { showConfirm } from '../composables/useDialog'
import { useUiStore } from '../stores/ui'

const ui = useUiStore()

const logs = ref([])
const loading = ref(false)
const hasMore = ref(true)
const page = ref(0)
const pageSize = 100
const selectedAction = ref('')
const selectedUser = ref('')
const selectedTarget = ref('')

const ACTION_MAP = {
  share_recipe: '共享配方',
  adopt_recipe: '共享配方',
  update_recipe: '编辑配方',
  delete_recipe: '删除配方',
  reject_recipe: '拒绝配方',
  undo_delete_recipe: '恢复配方',
  upsert_oil: '编辑精油',
  delete_oil: '删除精油',
  create_tag: '新增标签',
  delete_tag: '删除标签',
  create_user: '创建用户',
  update_user: '修改用户',
  delete_user: '删除用户',
  undo_delete_user: '恢复用户',
  business_apply: '申请商业认证',
  approve_business: '通过商业认证',
  reject_business: '拒绝商业认证',
  grant_business: '开通商业认证',
  revoke_business: '撤销商业认证',
  register: '用户注册',
}

const actionGroups = {
  '配方': ['share_recipe', 'adopt_recipe', 'update_recipe', 'delete_recipe', 'undo_delete_recipe'],
  '审核': ['reject_recipe'],
  '精油': ['upsert_oil', 'delete_oil', 'undo_delete_oil'],
  '标签': ['create_tag', 'delete_tag'],
  '用户': ['create_user', 'update_user', 'delete_user', 'undo_delete_user', 'register'],
  '商业认证': ['business_apply', 'approve_business', 'reject_business', 'grant_business', 'revoke_business'],
}

const actionTypes = Object.keys(actionGroups).map(label => ({ value: label, label }))

const targetTypes = [
  { value: 'recipe', label: '配方' },
  { value: 'oil', label: '精油' },
  { value: 'user', label: '用户' },
]

const uniqueUsers = computed(() => {
  const names = new Set()
  for (const log of logs.value) {
    const name = log.user_name || log.username
    if (name) names.add(name)
  }
  return [...names].sort()
})

const filteredLogs = computed(() => {
  let result = logs.value
  if (selectedAction.value) {
    const group = actionGroups[selectedAction.value]
    if (group) result = result.filter(l => group.includes(l.action))
  }
  if (selectedUser.value) {
    result = result.filter(l => (l.user_name || l.username) === selectedUser.value)
  }
  if (selectedTarget.value) {
    result = result.filter(l => l.target_type === selectedTarget.value)
  }
  return result
})

function actionLabel(action) {
  return ACTION_MAP[action] || action
}

function actionColorClass(action) {
  if (action.includes('create') || action.includes('upsert')) return 'color-create'
  if (action.includes('update')) return 'color-update'
  if (action.includes('delete') || action.includes('reject')) return 'color-delete'
  if (action.includes('adopt') || action.includes('undo') || action.includes('share')) return 'color-approve'
  return ''
}

function parsedDetail(log) {
  if (!log.detail) return ''
  try {
    const d = JSON.parse(log.detail)
    const parts = []
    if (d.from_role && d.to_role) parts.push(`${d.from_role} → ${d.to_role}`)
    if (d.from_user) parts.push(`来自: ${d.from_user}`)
    if (d.reason) parts.push(`原因: ${d.reason}`)
    if (d.business_name) parts.push(`商户: ${d.business_name}`)
    if (d.changed) parts.push(`修改: ${d.changed}`)
    if (d.display_name) parts.push(`显示名: ${d.display_name}`)
    if (d.original_log_id) parts.push(`恢复自 #${d.original_log_id}`)
    if (parts.length) return parts.join(' · ')
    // For deleted users, show username
    if (d.username) return `用户名: ${d.username}`
    return ''
  } catch {
    return log.detail.length > 100 ? log.detail.substring(0, 100) + '...' : log.detail
  }
}

function canUndo(log) {
  return ['delete_recipe', 'delete_oil'].includes(log.action)
}

async function undoAction(log) {
  const ok = await showConfirm(`确定撤销此操作？将恢复「${log.target_name}」`)
  if (!ok) return
  try {
    const res = await api(`/api/audit-log/${log.id}/undo`, { method: 'POST' })
    if (res.ok) {
      ui.showToast('已撤销')
      logs.value = []
      page.value = 0
      hasMore.value = true
      await fetchLogs()
    } else {
      const err = await res.json().catch(() => ({}))
      ui.showToast('撤销失败: ' + (err.detail || err.message || ''))
    }
  } catch {
    ui.showToast('撤销失败')
  }
}

function formatTime(t) {
  if (!t) return ''
  return new Date(t + 'Z').toLocaleString('zh-CN', {
    month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit',
  })
}

async function fetchLogs() {
  loading.value = true
  try {
    const res = await api(`/api/audit-log?offset=${page.value * pageSize}&limit=${pageSize}`)
    if (res.ok) {
      const data = await res.json()
      const items = Array.isArray(data) ? data : data.logs || data.items || []
      if (items.length < pageSize) hasMore.value = false
      logs.value.push(...items)
    }
  } catch {
    hasMore.value = false
  }
  loading.value = false
}

function loadMore() {
  page.value++
  fetchLogs()
}

onMounted(() => fetchLogs())
</script>

<style scoped>
.audit-log { padding: 0 12px 24px; }
.page-title { margin: 0 0 16px; font-size: 16px; color: #3e3a44; }

.filter-row {
  display: flex; align-items: center; gap: 6px; margin-bottom: 8px; flex-wrap: wrap;
}
.filter-label { font-size: 13px; color: #6b6375; font-weight: 500; white-space: nowrap; }
.filter-btn {
  padding: 4px 12px; border-radius: 16px; border: 1.5px solid #e5e4e7;
  background: #fff; font-size: 12px; cursor: pointer; font-family: inherit; color: #6b6375;
}
.filter-btn.active { background: #e8f5e9; border-color: #7ec6a4; color: #2e7d5a; font-weight: 600; }
.filter-btn:hover { border-color: #d4cfc7; }

.log-list { display: flex; flex-direction: column; gap: 4px; }
.log-item {
  padding: 10px 14px; background: #fff; border: 1.5px solid #e5e4e7; border-radius: 10px;
}
.log-item:hover { border-color: #d4cfc7; }

.log-header { display: flex; align-items: center; gap: 8px; }
.log-action {
  padding: 2px 10px; border-radius: 10px; font-size: 11px; font-weight: 600;
  background: #f0eeeb; color: #6b6375; white-space: nowrap;
}
.color-create { background: #e8f5e9; color: #2e7d5a; }
.color-update { background: #e3f2fd; color: #1565c0; }
.color-delete { background: #ffebee; color: #c62828; }
.color-approve { background: #f3e5f5; color: #7b1fa2; }

.log-user { font-size: 13px; font-weight: 500; color: #3e3a44; }
.log-time { font-size: 11px; color: #b0aab5; margin-left: auto; white-space: nowrap; }
.log-detail { font-size: 13px; color: #6b6375; margin-top: 2px; }
.log-target-name { font-weight: 500; color: #3e3a44; margin-right: 8px; }
.log-extra { color: #999; font-size: 12px; }
.undo-btn {
  margin-left: 8px; padding: 2px 8px; border: 1px solid #d4cfc7; border-radius: 6px;
  background: #fff; font-size: 11px; cursor: pointer; color: #6b6375; font-family: inherit;
}
.undo-btn:hover { border-color: #7ec6a4; color: #4a9d7e; }

.load-more { text-align: center; margin-top: 16px; }
.btn-outline {
  background: #fff; color: #6b6375; border: 1.5px solid #d4cfc7; border-radius: 10px;
  padding: 9px 28px; font-size: 13px; cursor: pointer; font-family: inherit;
}
.btn-outline:hover { background: #f8f7f5; }
.btn-outline:disabled { opacity: 0.5; cursor: default; }
.empty-hint { text-align: center; color: #b0aab5; font-size: 13px; padding: 32px 0; }
</style>
