<template>
  <div class="app-container">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>后台日志管理</span>
        </div>
      </template>

      <el-tabs v-model="activeTab" @tab-click="handleTabClick">
        <!-- Tab 1: Real-time Logs -->
        <el-tab-pane label="实时日志" name="realtime">
          <div class="log-controls">
            <el-tag :type="isConnected ? 'success' : 'danger'">
              {{ isConnected ? '已连接' : '未连接' }}
            </el-tag>
            <el-button 
              type="primary" 
              size="small" 
              @click="toggleConnection" 
              :loading="connecting"
            >
              {{ isConnected ? '停止监控' : '开始监控' }}
            </el-button>
            <el-button size="small" @click="clearRealtimeLogs">清空屏幕</el-button>
            <el-checkbox v-model="autoScroll" style="margin-left: 10px">自动滚动</el-checkbox>
          </div>
          
          <div class="log-viewer" ref="logViewerRef">
            <div v-for="(line, index) in realtimeLogs" :key="index" class="log-line">
              {{ line }}
            </div>
            <div v-if="realtimeLogs.length === 0" class="no-logs">
              暂无日志数据，点击"开始监控"接收实时日志...
            </div>
          </div>
        </el-tab-pane>

        <!-- Tab 2: Search Logs -->
        <el-tab-pane label="日志检索" name="search">
          <div class="search-form">
            <el-form :inline="true" :model="searchForm">
              <el-form-item label="日期">
                <el-date-picker
                  v-model="searchForm.date"
                  type="date"
                  placeholder="选择日期"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD"
                  :disabled-date="disabledDate"
                />
              </el-form-item>
              <el-form-item label="关键词">
                <el-input v-model="searchForm.keyword" placeholder="输入关键词过滤" clearable />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" @click="handleSearch" :loading="searching">查询</el-button>
              </el-form-item>
            </el-form>
          </div>
          
          <div class="log-viewer search-viewer">
            <div v-for="(line, index) in searchLogs" :key="index" class="log-line">
              {{ line }}
            </div>
            <div v-if="searchLogs.length === 0 && !searching" class="no-logs">
              {{ searchError || '无数据' }}
            </div>
          </div>
        </el-tab-pane>

        <!-- Tab 3: File Management -->
        <el-tab-pane label="日志文件" name="files">
          <el-table :data="fileList" style="width: 100%" v-loading="loadingFiles">
            <el-table-column prop="name" label="文件名" width="250" />
            <el-table-column prop="date" label="日志日期" width="150" />
            <el-table-column prop="size" label="大小" width="150">
              <template #default="scope">
                {{ formatSize(scope.row.size) }}
              </template>
            </el-table-column>
            <el-table-column prop="mtime" label="最后修改时间" />
            <el-table-column label="操作" width="150">
              <template #default="scope">
                <el-button type="primary" link @click="downloadFile(scope.row.name)">
                  下载
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onUnmounted, nextTick, watch } from 'vue'
import { ElMessage } from 'element-plus'
import api from '../../../utils/request'

// --- State ---
const activeTab = ref('realtime')

// Realtime
const realtimeLogs = ref<string[]>([])
const isConnected = ref(false)
const connecting = ref(false)
const autoScroll = ref(true)
const logViewerRef = ref<HTMLElement | null>(null)
let socket: WebSocket | null = null

// Search
const searchForm = reactive({
  date: new Date().toISOString().split('T')[0],
  keyword: ''
})
const searchLogs = ref<string[]>([])
const searching = ref(false)
const searchError = ref('')

// Files
const fileList = ref([])
const loadingFiles = ref(false)

// --- Methods: Realtime ---

const getWsUrl = () => {
  // Construct WS URL from VITE_API_BASE_URL
  const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1'
  const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
  const token = localStorage.getItem('token')
  
  // If baseUrl is relative (starts with /), prepend current host
  if (baseUrl.startsWith('/')) {
    return `${wsProtocol}//${window.location.host}${baseUrl}/system-logs/stream?token=${token}`
  }
  
  // If baseUrl is absolute (starts with http), replace protocol
  const urlBody = baseUrl.replace(/^https?:/, '')
  return `${wsProtocol}${urlBody}/system-logs/stream?token=${token}`
}

const toggleConnection = () => {
  if (isConnected.value) {
    closeConnection()
  } else {
    startConnection()
  }
}

const startConnection = () => {
  connecting.value = true
  try {
    const url = getWsUrl()
    socket = new WebSocket(url)
    
    socket.onopen = () => {
      isConnected.value = true
      connecting.value = false
      realtimeLogs.value.push('--- 连接成功 ---')
    }
    
    socket.onmessage = (event) => {
      realtimeLogs.value.push(event.data)
      // Limit memory usage
      if (realtimeLogs.value.length > 2000) {
        realtimeLogs.value.shift()
      }
      if (autoScroll.value) {
        scrollToBottom()
      }
    }
    
    socket.onclose = () => {
      isConnected.value = false
      connecting.value = false
      realtimeLogs.value.push('--- 连接断开 ---')
    }
    
    socket.onerror = (error) => {
      console.error('WebSocket Error', error)
      isConnected.value = false
      connecting.value = false
      realtimeLogs.value.push('--- 连接错误 ---')
    }
  } catch (e) {
    console.error(e)
    connecting.value = false
  }
}

const closeConnection = () => {
  if (socket) {
    socket.close()
    socket = null
  }
  isConnected.value = false
}

const clearRealtimeLogs = () => {
  realtimeLogs.value = []
}

const scrollToBottom = () => {
  nextTick(() => {
    if (logViewerRef.value) {
      logViewerRef.value.scrollTop = logViewerRef.value.scrollHeight
    }
  })
}

// --- Methods: Search ---

const handleSearch = async () => {
  searching.value = true
  searchError.value = ''
  searchLogs.value = []
  
  try {
    const res = await api.get('/system-logs/search', {
      params: {
        date: searchForm.date,
        keyword: searchForm.keyword,
        lines: 2000
      }
    })
    
    if (res.data.error) {
      searchError.value = res.data.error
    } else {
      searchLogs.value = res.data.lines
    }
  } catch (e) {
    searchError.value = '查询失败'
  } finally {
    searching.value = false
  }
}

const disabledDate = (time: Date) => {
  return time.getTime() > Date.now()
}

// --- Methods: Files ---

const loadFileList = async () => {
  loadingFiles.value = true
  try {
    const res = await api.get('/system-logs/files')
    fileList.value = res.data
  } catch (e) {
    ElMessage.error('加载文件列表失败')
  } finally {
    loadingFiles.value = false
  }
}

const downloadFile = async (filename: string) => {
  try {
    // We can't use standard api.get for download easily because of blob handling
    // Just window.open or create link
    const token = localStorage.getItem('token')
    const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1'
    const url = `${baseUrl}/system-logs/download/${filename}?token=${token}` // Note: passing token in query is not ideal for standard APIs but easiest for direct link
    // However, for better security, we should fetch blob and download.
    
    // Using fetch with auth header
    const response = await fetch(`${baseUrl}/system-logs/download/${filename}`, {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    })
    
    if (!response.ok) throw new Error('Download failed')
    
    const blob = await response.blob()
    const downloadUrl = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = downloadUrl
    a.download = filename
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    window.URL.revokeObjectURL(downloadUrl)
    
  } catch (e) {
    ElMessage.error('下载失败')
  }
}

const formatSize = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// --- Lifecycle ---

const handleTabClick = (tab: any) => {
  if (tab.props.name === 'files') {
    loadFileList()
  }
}

onUnmounted(() => {
  closeConnection()
})
</script>

<style scoped>
.app-container {
  padding: 20px;
  height: calc(100vh - 100px);
  display: flex;
  flex-direction: column;
}

:deep(.el-card) {
  flex: 1;
  display: flex;
  flex-direction: column;
}
:deep(.el-card__body) {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
:deep(.el-tabs) {
  flex: 1;
  display: flex;
  flex-direction: column;
  height: 100%;
}
:deep(.el-tabs__content) {
  flex: 1;
  overflow: hidden;
  padding: 10px 0;
}
:deep(.el-tab-pane) {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.log-controls {
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.log-viewer {
  flex: 1;
  background-color: #1e1e1e;
  color: #d4d4d4;
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 13px;
  padding: 10px;
  overflow-y: auto;
  border-radius: 4px;
  line-height: 1.4;
}

.log-line {
  white-space: pre-wrap;
  word-break: break-all;
}

.log-line:hover {
  background-color: #2d2d2d;
}

.search-form {
  margin-bottom: 15px;
}

.no-logs {
  color: #666;
  text-align: center;
  margin-top: 50px;
}
</style>

