<template>
  <div class="logs-page">
    <div class="page-header">
      <div class="log-info">
        <span v-if="logInfo" class="info-item">
          <el-icon><Document /></el-icon>
          {{ formatSize(logInfo.size) }}
        </span>
        <span v-if="logInfo" class="info-item">
          <el-icon><Clock /></el-icon>
          {{ formatTime(logInfo.mod_time) }}
        </span>
      </div>
      <div class="header-actions">
        <el-select v-model="lines" style="width: 120px" @change="fetchLogs">
          <el-option :value="100" label="100 行" />
          <el-option :value="500" label="500 行" />
          <el-option :value="1000" label="1000 行" />
          <el-option :value="2000" label="2000 行" />
        </el-select>
        <el-button @click="fetchLogs" :loading="loading">
          <el-icon><Refresh /></el-icon>
          刷新
        </el-button>
        <el-popconfirm title="确定清空所有日志？" confirm-button-text="确定" cancel-button-text="取消" @confirm="clearAllLogs">
          <template #reference>
            <el-button type="danger" :loading="clearing">
              <el-icon><Delete /></el-icon>
              清空
            </el-button>
          </template>
        </el-popconfirm>
      </div>
    </div>
    <div class="log-card">
      <div class="log-content-wrapper">
        <pre ref="logContainer" class="log-content" v-html="highlightedContent"></pre>
        <div v-if="loading" class="log-loading">
          <el-icon class="is-loading"><Loading /></el-icon>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { Document, Clock, Refresh, Delete, Loading } from '@element-plus/icons-vue'
import { adminApi } from '../../api'

const lines = ref(500)
const content = ref('')
const logInfo = ref<{ size: number; mod_time: string } | null>(null)
const loading = ref(false)
const clearing = ref(false)
const logContainer = ref<HTMLPreElement | null>(null)
let timer: ReturnType<typeof setInterval> | null = null

function highlightLine(line: string): string {
  const escaped = line.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
  if (/\bERROR\b/i.test(line)) {
    return `<span class="log-error">${escaped}</span>`
  }
  if (/\bWARN\b/i.test(line)) {
    return `<span class="log-warn">${escaped}</span>`
  }
  if (/BepUsdt/i.test(line)) {
    return `<span class="log-bepusdt">${escaped}</span>`
  }
  return escaped
}

const highlightedContent = computed(() => {
  if (!content.value) return ''
  return content.value.split('\n').map(highlightLine).join('\n')
})

function formatSize(bytes: number): string {
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / (1024 * 1024)).toFixed(2) + ' MB'
}

function formatTime(t: string): string {
  if (!t) return '-'
  const d = new Date(t)
  return d.toLocaleString('zh-CN')
}

async function fetchLogs() {
  loading.value = true
  try {
    const res: any = await adminApi.getLogs(lines.value)
    content.value = res.data?.content || ''
    await nextTick()
    scrollToBottom()
  } catch (e: any) {
    ElMessage.error(e.response?.data?.error || '获取日志失败')
  } finally {
    loading.value = false
  }
}

async function fetchLogInfo() {
  try {
    const res: any = await adminApi.getLogInfo()
    logInfo.value = res.data || null
  } catch {}
}

async function clearAllLogs() {
  clearing.value = true
  try {
    await adminApi.clearLogs()
    ElMessage.success('日志已清空')
    content.value = ''
    await fetchLogInfo()
  } catch (e: any) {
    ElMessage.error(e.response?.data?.error || '清空失败')
  } finally {
    clearing.value = false
  }
}

function scrollToBottom() {
  if (logContainer.value) {
    logContainer.value.scrollTop = logContainer.value.scrollHeight
  }
}

onMounted(() => {
  fetchLogs()
  fetchLogInfo()
  timer = setInterval(() => {
    fetchLogs()
    fetchLogInfo()
  }, 10000)
})

onUnmounted(() => {
  if (timer) {
    clearInterval(timer)
    timer = null
  }
})
</script>

<style scoped lang="scss">
.logs-page {
  padding: 0;
}

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

.log-info {
  display: flex;
  align-items: center;
  gap: 16px;
}

.info-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: rgba(255, 255, 255, 0.6);
  font-size: 13px;
}

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

.log-card {
  background: #2d2d44;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 12px;
  overflow: hidden;
}

.log-content-wrapper {
  position: relative;
}

.log-content {
  background: #1a1a2e;
  color: rgba(255, 255, 255, 0.85);
  font-family: Consolas, Monaco, monospace;
  font-size: 13px;
  line-height: 1.6;
  padding: 16px;
  margin: 0;
  max-height: calc(100vh - 200px);
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.15) transparent;

  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-track {
    background: transparent;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.25);
  }
}

.log-loading {
  position: absolute;
  top: 12px;
  right: 12px;
  color: rgba(255, 255, 255, 0.5);
  font-size: 18px;
}

.log-error {
  color: #f56c6c;
}

.log-warn {
  color: #e6a23c;
}

.log-bepusdt {
  color: #409eff;
}

:deep(.el-select .el-input__wrapper) {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: none;

  &:hover,
  &:focus {
    border-color: #4e6ef2;
  }
}

:deep(.el-select .el-input__inner) {
  color: #fff;
}
</style>
