<!--
  组件名称：ReportLog.vue
  组件描述：上报记录查看组件，支持筛选、分页、JSON 内容展示

  @author czj
  @date 2026-07-29
-->

<template>
  <div class="report-log">
    <div class="log-header">
      <h4>上报记录</h4>
      <div class="log-actions">
        <el-select
          v-model="directionFilter"
          placeholder="方向"
          size="small"
          style="width: 100px"
          @change="onFilterChange"
        >
          <el-option label="全部" value="" />
          <el-option label="上报" value="publish" />
          <el-option label="接收" value="subscribe" />
        </el-select>
        <el-date-picker
          v-model="timeRange"
          type="datetimerange"
          range-separator="至"
          start-placeholder="开始时间"
          end-placeholder="结束时间"
          value-format="YYYY-MM-DD HH:mm:ss"
          style="width: 320px"
          @change="loadLogs"
        />
        <el-button size="small" :loading="cleaning" @click="handleCleanup">清理旧记录</el-button>
        <el-button size="small" @click="loadLogs">刷新</el-button>
      </div>
    </div>

    <el-table :data="logs" v-loading="loading" stripe size="small" style="width: 100%">
      <el-table-column label="时间" width="160">
        <template #default="{ row }">
          {{ formatTime(row.createdAt) }}
        </template>
      </el-table-column>
      <el-table-column label="方向" width="80">
        <template #default="{ row }">
          <el-tag :type="row.direction === 'publish' ? 'primary' : 'success'" size="small">
            {{ row.direction === 'publish' ? '上报' : '接收' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" width="80">
        <template #default="{ row }">
          <el-tag :type="row.status === 'success' ? 'success' : 'danger'" size="small">
            {{ row.status === 'success' ? '成功' : '失败' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="topic" label="主题" min-width="250" show-overflow-tooltip />
      <el-table-column label="内容" min-width="300">
        <template #default="{ row }">
          <el-tooltip placement="top" :hide-after="0">
            <template #content>
              <pre class="json-preview">{{ formatJson(row.payload) }}</pre>
            </template>
            <span class="json-truncate">{{ formatJson(row.payload) }}</span>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column v-if="showDeviceColumn" label="设备 ID" min-width="160">
        <template #default="{ row }">
          {{ row.deviceId }}
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <div class="pagination-wrapper" v-if="total > pageSize">
      <el-pagination
        v-model:current-page="currentPage"
        :page-size="pageSize"
        :total="total"
        layout="prev, pager, next, total"
        small
        @change="loadLogs"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { listReportLogs, cleanupReportLogs } from '@/api/deviceSim'
import type { ReportLog } from '@/types/device'

const props = defineProps<{
  deviceId?: string
  showDeviceColumn?: boolean
}>()

const loading = ref(false)
const logs = ref<ReportLog[]>([])
const total = ref(0)
const currentPage = ref(1)
const pageSize = 20
const timeRange = ref<any>(null)
const directionFilter = ref('')
const cleaning = ref(false)

/** 加载上报记录 */
async function loadLogs() {
  loading.value = true
  try {
    const params: any = {
      skip: (currentPage.value - 1) * pageSize,
      limit: pageSize,
    }
    if (props.deviceId) params.deviceId = props.deviceId
    if (directionFilter.value) params.direction = directionFilter.value
    if (timeRange.value) {
      params.startTime = timeRange.value[0]
      params.endTime = timeRange.value[1]
    }

    const res = await listReportLogs(params)
    logs.value = res.items
    total.value = res.total
  } catch (e: any) {
    ElMessage.error('加载上报记录失败: ' + (e.message || ''))
  } finally {
    loading.value = false
  }
}

/** 方向筛选变更：回到第 1 页并重新加载 */
function onFilterChange() {
  currentPage.value = 1
  loadLogs()
}

/** 清理旧记录 */
async function handleCleanup() {
  cleaning.value = true
  try {
    const res = await cleanupReportLogs(7)
    ElMessage.success(`已清理 ${res.cleanedCount} 条记录`)
    await loadLogs()
  } catch (e: any) {
    ElMessage.error('清理失败: ' + (e.message || ''))
  } finally {
    cleaning.value = false
  }
}

/** 格式化 JSON */
function formatJson(data: any) {
  if (!data) return '{}'
  try {
    return JSON.stringify(data, null, 2)
  } catch (_) {
    return String(data)
  }
}

/** 格式化时间 */
function formatTime(t: string) {
  return t?.replace('T', ' ').substring(0, 19) || '-'
}

onMounted(() => {
  loadLogs()
})
</script>

<style scoped>
.report-log {
  width: 100%;
}

.log-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.log-header h4 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: #303133;
}

.log-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.json-truncate {
  display: block;
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  color: #666;
}

.json-preview {
  margin: 0;
  max-height: 300px;
  overflow: auto;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  white-space: pre;
}

.pagination-wrapper {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}
</style>