<template>
  <div class="operation-log">
    <el-card>
      <template #header>
        <div class="card-header">
          <div class="search-section">
            <el-input
              v-model="searchKeyword"
              placeholder="搜索操作人或操作模块"
              clearable
              style="width: 300px"
              @clear="handleSearch"
              @keyup.enter="handleSearch"
            >
              <template #prefix>
                <el-icon><Search /></el-icon>
              </template>
            </el-input>
            <el-button
              type="primary"
              @click="handleSearch"
            >
              搜索
            </el-button>
            <el-button
              type="success"
              @click="handleExport"
            >
              <el-icon><Download /></el-icon>
              导出
            </el-button>
          </div>
        </div>
      </template>
      <el-table
        v-loading="loading"
        :data="dataSource"
        style="width: 100%"
        @sort-change="handleSortChange"
      >
        <el-table-column
          prop="id"
          label="ID"
          sortable="custom"
        />
        <el-table-column
          prop="username"
          label="操作人"
          sortable="custom"
        />
        <el-table-column
          prop="operation"
          label="操作模块"
          sortable="custom"
        >
          <template #default="{ row }">
            <div class="operation-cell">
              <el-icon class="operation-icon">
                <component :is="getOperationIcon(row.operation)" />
              </el-icon>
              <span>{{ row.operation }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          prop="method"
          label="请求方法"
          sortable="custom"
        />
        <el-table-column
          prop="params"
          label="请求参数"
          :show-overflow-tooltip="true"
        >
          <template #default="{ row }">
            <div
              v-if="row.params"
              class="params-content"
            >
              <el-popover
                placement="top"
                :width="500"
                trigger="hover"
              >
                <template #reference>
                  <div class="params-preview">
                    {{ formatParams(row.params) }}
                  </div>
                </template>
                <pre class="params-detail">{{ formatParams(row.params) }}</pre>
              </el-popover>
            </div>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="状态">
          <template #default="{ row }">
            <el-tag 
              :type="row.status === '0' ? 'success' : 'danger'"
              effect="dark"
              style="font-weight: 500; font-size: 14px;"
            >
              {{ row.status === '0' ? '成功' : '失败' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          prop="duration"
          label="耗时(ms)"
          sortable="custom"
        />
        <el-table-column
          prop="createdAt"
          label="操作时间"
          sortable="custom"
        >
          <template #default="{ row }">
            {{ formatDateTime(row.createdAt) }}
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        v-model:current-page="pagination.current"
        v-model:page-size="pagination.pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="pagination.total"
        layout="total, sizes, prev, pager, next, jumper"
        style="margin-top: 16px; justify-content: flex-end"
        @current-change="handleTableChange"
        @size-change="handleSizeChange"
      />
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { Search, User, Document, Setting, Lock, View, Edit, Delete, Plus, Download } from '@element-plus/icons-vue'
import { operationLogApi, OperationLog } from '@/api/operationLog'
import { formatDateTime } from '@/utils/dateFormat'

const loading = ref(false)
const dataSource = ref<OperationLog[]>([])
const searchKeyword = ref('')
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0
})

const sortInfo = reactive({
  sort: 'id',
  order: 'asc'
})

const fetchData = async () => {
  loading.value = true
  try {
    const res = await operationLogApi.getPage({
      page: pagination.current - 1,
      size: pagination.pageSize,
      sort: sortInfo.sort,
      order: sortInfo.order,
      keyword: searchKeyword.value || undefined
    })
    dataSource.value = res.content
    pagination.total = res.totalElements
  } finally {
    loading.value = false
  }
}

const handleTableChange = () => {
  fetchData()
}

const handleSizeChange = () => {
  pagination.current = 1
  fetchData()
}

const handleSearch = () => {
  pagination.current = 1
  fetchData()
}

const handleExport = async () => {
  try {
    loading.value = true
    const params = new URLSearchParams()
    if (searchKeyword.value) {
      params.append('keyword', searchKeyword.value)
    }
    
    const response = await fetch(`/api/logs/operation/export?${params.toString()}`, {
      method: 'GET',
      headers: {
        'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      }
    })
    
    if (!response.ok) {
      throw new Error('导出失败')
    }
    
    const blob = await response.blob()
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `operation_logs_${new Date().toISOString().slice(0, 19).replace(/[:-]/g, '')}.xlsx`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
  } catch (error) {
    console.error('导出失败:', error)
  } finally {
    loading.value = false
  }
}

const handleSortChange = ({ prop, order }: any) => {
  sortInfo.sort = prop
  sortInfo.order = order === 'ascending' ? 'asc' : 'desc'
  fetchData()
}

const formatParams = (params: string) => {
  if (!params) return ''
  try {
    const parsed = JSON.parse(params)
    return JSON.stringify(parsed, null, 2)
  } catch {
    return params
  }
}

const getOperationIcon = (operation: string) => {
  if (!operation) return Document
  const op = operation.toLowerCase()
  if (op.includes('登录') || op.includes('login')) return User
  if (op.includes('删除') || op.includes('delete')) return Delete
  if (op.includes('编辑') || op.includes('修改') || op.includes('update') || op.includes('edit')) return Edit
  if (op.includes('查看') || op.includes('查询') || op.includes('view') || op.includes('get')) return View
  if (op.includes('新增') || op.includes('创建') || op.includes('add') || op.includes('create')) return Plus
  if (op.includes('下载') || op.includes('download')) return Download
  if (op.includes('设置') || op.includes('配置') || op.includes('setting') || op.includes('config')) return Setting
  if (op.includes('密码') || op.includes('password')) return Lock
  return Document
}

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

<style scoped lang="css">
.operation-log {
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;

    .search-section {
      display: flex;
      gap: 8px;
      align-items: center;
    }
  }

  .operation-cell {
    display: flex;
    align-items: center;
    gap: 8px;

    .operation-icon {
      font-size: 16px;
      color: #409eff;
    }
  }

  .params-content {
    .params-preview {
      max-width: 200px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      color: #606266;
      font-size: 13px;
      cursor: pointer;
      transition: color 0.2s;

      &:hover {
        color: #409eff;
      }
    }

    .params-detail {
      max-height: 300px;
      overflow-y: auto;
      background: #f5f7fa;
      padding: 12px;
      border-radius: 4px;
      font-size: 12px;
      color: #303133;
      margin: 0;
      line-height: 1.5;
      font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    }
  }
}
</style>
