<template>
  <div class="app-container">
    <CommonPage
        :operationBtnList="operationBtnList"
        :visibleDefaultButtons="visibleDefaultButtons"
        :showSearchForm="true"
        :show-pagination="true"
        :total="pageTotal"
        :current-page="currentPage"
        :page-size="pageSize"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
    >
      <template #searchForm>
        <SearchForm ref="searchFormRef" :config="searchConfig"/>
      </template>
      <template #table>
        <el-table :data="tableData" v-loading="loading" border>
          <el-table-column prop="operTime" label="操作时间" width="170">
            <template #default="scope">
              <span>{{ parseTime(scope.row.operTime) }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="module" label="业务模块" width="120" :show-overflow-tooltip="true"/>
          <el-table-column prop="businessType" label="业务类型" width="100">
            <template #default="scope">
              <span>{{ BUSINESS_TYPE_MAP[scope.row.businessType] || scope.row.businessType }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="content" label="日志内容" min-width="180" :show-overflow-tooltip="true"/>
          <el-table-column prop="operName" label="操作人" width="100"/>
          <el-table-column prop="deptName" label="部门" width="120" :show-overflow-tooltip="true"/>
          <el-table-column prop="status" label="状态" width="80">
            <template #default="scope">
              <el-tag :type="scope.row.status === 0 ? 'success' : 'danger'" size="small">
                {{ scope.row.status === 0 ? '成功' : '失败' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="operIp" label="操作IP" width="140"/>
          <el-table-column label="操作" width="100" fixed="right">
            <template #default="scope">
              <el-button link type="primary" icon="View" @click="handleView(scope.row)">详情</el-button>
            </template>
          </el-table-column>
        </el-table>
      </template>
    </CommonPage>

    <!-- 审计详情弹窗 -->
    <el-dialog
        title="审计详情"
        v-model="dialogVisible"
        width="1000px"
        append-to-body
        :close-on-click-modal="false"
    >
      <div v-loading="detailLoading">
        <!-- 操作日志基本信息 -->
        <el-descriptions v-if="detail.operLog" title="基本信息" :column="2" border style="margin-bottom: 20px">
          <el-descriptions-item label="业务模块">{{ detail.operLog.module }}</el-descriptions-item>
          <el-descriptions-item label="业务类型">
            {{ BUSINESS_TYPE_MAP[detail.operLog.businessType] || detail.operLog.businessType }}
          </el-descriptions-item>
          <el-descriptions-item label="操作人">{{ detail.operLog.operName }}</el-descriptions-item>
          <el-descriptions-item label="部门">{{ detail.operLog.deptName }}</el-descriptions-item>
          <el-descriptions-item label="操作时间">{{ parseTime(detail.operLog.operTime) }}</el-descriptions-item>
          <el-descriptions-item label="操作IP">{{ detail.operLog.operIp }}</el-descriptions-item>
          <el-descriptions-item label="请求URL" :span="2">{{ detail.operLog.operUrl }}</el-descriptions-item>
          <el-descriptions-item label="日志内容" :span="2">{{ detail.operLog.content }}</el-descriptions-item>
          <el-descriptions-item label="操作状态">
            <el-tag :type="detail.operLog.status === 0 ? 'success' : 'danger'" size="small">
              {{ detail.operLog.status === 0 ? '成功' : '失败' }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="请求ID">{{ detail.operLog.requestId }}</el-descriptions-item>
          <el-descriptions-item label="请求参数" :span="2">
            <div class="json-content">{{ detail.operLog.operParam || '-' }}</div>
          </el-descriptions-item>
          <el-descriptions-item label="返回结果" :span="2">
            <div class="json-content">{{ detail.operLog.jsonResult || '-' }}</div>
          </el-descriptions-item>
          <el-descriptions-item v-if="detail.operLog.status === 1" label="错误信息" :span="2">
            <span style="color: #f56c6c">{{ detail.operLog.errorMsg }}</span>
          </el-descriptions-item>
        </el-descriptions>

        <!-- 数据快照 -->
        <template v-if="detail.snapshots && detail.snapshots.length > 0">
          <h4 class="section-title">数据快照（共 {{ detail.snapshots.length }} 条）</h4>
          <el-table :data="detail.snapshots" border size="small" style="margin-bottom: 20px">
            <el-table-column prop="tableName" label="表名" width="150"/>
            <el-table-column prop="recordId" label="记录ID" width="120"/>
            <el-table-column label="变更前数据" min-width="280">
              <template #default="scope">
                <pre v-if="scope.row.beforeJson" class="json-pre">{{ formatJson(scope.row.beforeJson) }}</pre>
                <span v-else class="empty-hint">- (新增)</span>
              </template>
            </el-table-column>
            <el-table-column label="变更后数据" min-width="280">
              <template #default="scope">
                <pre v-if="scope.row.afterJson" class="json-pre">{{ formatJson(scope.row.afterJson) }}</pre>
                <span v-else class="empty-hint">- (删除)</span>
              </template>
            </el-table-column>
          </el-table>
        </template>

        <!-- 字段变更明细 -->
        <template v-if="detail.changes && detail.changes.length > 0">
          <h4 class="section-title">字段变更明细（共 {{ detail.changes.length }} 条）</h4>
          <el-table :data="detail.changes" border size="small">
            <el-table-column prop="tableName" label="表名" width="150"/>
            <el-table-column prop="fieldComment" label="字段名" width="140"/>
            <el-table-column label="变更类型" width="80">
              <template #default="scope">
                <el-tag
                    :type="changeTypeTag(scope.row.changeType)"
                    size="small"
                >{{ scope.row.changeType }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="oldValue" label="旧值" min-width="200" :show-overflow-tooltip="true"/>
            <el-table-column prop="newValue" label="新值" min-width="200" :show-overflow-tooltip="true"/>
          </el-table>
        </template>
      </div>

      <template #footer>
        <el-button @click="dialogVisible = false">关 闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {ref, reactive} from 'vue'
import CommonPage from '@/components/commonPage'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import {getAuditLogPage, getAuditLogDetail} from '@/api/monitor/auditlog'

const {proxy} = getCurrentInstance()

// 业务类型映射
const BUSINESS_TYPE_MAP = {
  0: '其它', 1: '新增', 2: '修改', 3: '删除',
  4: '授权', 5: '导出', 6: '导入', 7: '强退',
  8: '生成代码', 9: '清空数据'
}

// 搜索表单配置
const searchFormRef = ref(null)
const searchConfig = ref([
  {type: 'input', prop: 'module', label: '业务模块', placeholder: '请输入业务模块'},
  {type: 'input', prop: 'operName', label: '操作人', placeholder: '请输入操作人'},
  {
    type: 'select',
    prop: 'status',
    label: '操作状态',
    placeholder: '请选择',
    options: [
      {label: '成功', value: 0},
      {label: '失败', value: 1}
    ]
  },
  {
    type: 'daterange',
    prop: 'operTimeRange',
    label: '操作时间',
    startPlaceholder: '开始时间',
    endPlaceholder: '结束时间',
    valueFormat: 'YYYY-MM-DD HH:mm:ss'
  }
])

// 表格数据
const tableData = ref([])
const loading = ref(false)

// 分页
const currentPage = ref(1)
const pageSize = ref(10)
const pageTotal = ref(0)

const handleSizeChange = val => {
  pageSize.value = val
  getList()
}

const handleCurrentChange = val => {
  currentPage.value = val
  getList()
}

// 获取列表数据
const getList = async () => {
  loading.value = true
  try {
    const formData = searchFormRef.value?.getFormData() || {}
    const params = {
      ...formData,
      startTime: formData.operTimeRange ? formData.operTimeRange[0] : undefined,
      endTime: formData.operTimeRange ? formData.operTimeRange[1] : undefined,
      operTimeRange: undefined,
      pageNo: currentPage.value,
      pageSize: pageSize.value
    }
    const response = await getAuditLogPage(params)
    tableData.value = response.data.records || []
    pageTotal.value = response.data.total || 0
  } finally {
    loading.value = false
  }
}
getList()

// 查询
const handleQuery = () => {
  currentPage.value = 1
  getList()
}

// 重置
const handleReset = () => {
  searchFormRef.value?.resetForm()
  currentPage.value = 1
  getList()
}

const visibleDefaultButtons = ref(['reset', 'query'])
const operationBtnList = ref([
  {key: 'reset', direction: 'right', click: handleReset},
  {key: 'query', direction: 'right', click: handleQuery}
])

// ========== 详情弹窗 ==========
const dialogVisible = ref(false)
const detailLoading = ref(false)
const detail = reactive({
  operLog: null,
  snapshots: [],
  changes: []
})

const handleView = async (row) => {
  dialogVisible.value = true
  detail.operLog = null
  detail.snapshots = []
  detail.changes = []
  if (!row.requestId) return

  detailLoading.value = true
  try {
    const response = await getAuditLogDetail(row.requestId)
    if (response.data) {
      detail.operLog = response.data.operLog || null
      detail.snapshots = response.data.snapshots || []
      detail.changes = response.data.changes || []
    }
  } finally {
    detailLoading.value = false
  }
}

const formatJson = (jsonStr) => {
  try {
    return JSON.stringify(JSON.parse(jsonStr), null, 2)
  } catch {
    return jsonStr
  }
}

const changeTypeTag = (type) => {
  switch (type) {
    case 'ADD':
      return 'success'
    case 'MODIFY':
      return 'warning'
    case 'DELETE':
      return 'danger'
    default:
      return 'info'
  }
}
</script>

<style scoped>
.section-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
  margin: 0 0 12px 0;
  padding-left: 8px;
  border-left: 3px solid #409eff;
}

.json-content {
  max-height: 200px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
  font-size: 12px;
  color: #606266;
  background: #f5f7fa;
  padding: 8px;
  border-radius: 4px;
}

.json-pre {
  margin: 0;
  padding: 6px 8px;
  background: #f5f7fa;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.5;
  max-height: 200px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

.empty-hint {
  color: #c0c4cc;
  font-size: 12px;
}
</style>
