<template>
  <el-drawer
    v-model="visible"
    :title="`节点执行详情: ${nodeLabel}`"
    size="600px"
    :close-on-click-modal="false"
  >
    <div v-if="loading" class="loading-container">
      <el-skeleton :rows="5" animated />
    </div>
    
    <div v-else-if="error" class="error-container">
      <el-alert
        type="error"
        :title="error"
        :closable="false"
        show-icon
      />
    </div>
    
    <div v-else-if="nodeLogs.length === 0" class="empty-container">
      <el-empty description="暂无执行日志" />
    </div>
    
    <div v-else class="execution-detail">
      <!-- 节点基本信息 -->
      <el-card class="info-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>节点信息</span>
            <el-tag :type="statusType" size="small">{{ statusText }}</el-tag>
          </div>
        </template>
        <el-descriptions :column="2" border>
          <el-descriptions-item label="节点ID">{{ nodeId }}</el-descriptions-item>
          <el-descriptions-item label="节点类型">{{ nodeType }}</el-descriptions-item>
          <el-descriptions-item label="执行时间" v-if="executionTime">
            {{ executionTime }}ms
          </el-descriptions-item>
          <el-descriptions-item label="执行状态">
            <el-tag :type="statusType" size="small">{{ statusText }}</el-tag>
          </el-descriptions-item>
        </el-descriptions>
      </el-card>
      
      <!-- 输入数据 -->
      <el-card v-if="inputData" class="data-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>输入数据</span>
            <el-button
              text
              size="small"
              @click="copyToClipboard(inputData)"
              title="复制"
            >
              <el-icon><DocumentCopy /></el-icon>
            </el-button>
          </div>
        </template>
        <pre class="json-viewer">{{ formatJSON(inputData) }}</pre>
      </el-card>
      
      <!-- 输出数据 -->
      <el-card v-if="outputData" class="data-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>输出数据</span>
            <el-button
              text
              size="small"
              @click="copyToClipboard(outputData)"
              title="复制"
            >
              <el-icon><DocumentCopy /></el-icon>
            </el-button>
          </div>
        </template>
        <pre class="json-viewer">{{ formatJSON(outputData) }}</pre>
      </el-card>
      
      <!-- 错误信息 -->
      <el-card v-if="errorInfo" class="error-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>错误信息</span>
            <el-tag type="danger" size="small">失败</el-tag>
          </div>
        </template>
        <div class="error-content">
          <div v-if="errorInfo.error_type" class="error-type">
            <strong>错误类型：</strong>{{ errorInfo.error_type }}
          </div>
          <div class="error-message">
            <strong>错误消息：</strong>
            <pre>{{ errorInfo.error_message || errorInfo.error }}</pre>
          </div>
        </div>
      </el-card>
      
      <!-- 执行时间线 -->
      <el-card class="timeline-card" shadow="never">
        <template #header>
          <span>执行时间线</span>
        </template>
        <el-timeline>
          <el-timeline-item
            v-for="(log, index) in nodeLogs"
            :key="index"
            :timestamp="formatTime(log.timestamp)"
            :type="getLogType(log.level)"
            :icon="getLogIcon(log.level)"
          >
            <div class="timeline-content">
              <div class="log-message">{{ log.message }}</div>
              <div v-if="log.duration" class="log-duration">
                耗时: {{ log.duration }}ms
              </div>
              <div v-if="log.data && Object.keys(log.data).length > 0" class="log-data">
                <el-collapse>
                  <el-collapse-item title="查看详情" :name="index">
                    <pre class="json-viewer-small">{{ formatJSON(log.data) }}</pre>
                  </el-collapse-item>
                </el-collapse>
              </div>
            </div>
          </el-timeline-item>
        </el-timeline>
      </el-card>
    </div>
  </el-drawer>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { DocumentCopy } from '@element-plus/icons-vue'
import api from '@/api'

interface ExecutionLog {
  id: string
  node_id: string
  node_type: string
  level: string
  message: string
  data?: any
  timestamp: string
  duration?: number
}

const props = defineProps<{
  visible: boolean
  nodeId?: string
  nodeLabel?: string
  nodeType?: string
  executionId?: string
}>()

const emit = defineEmits<{
  'update:visible': [value: boolean]
}>()

const loading = ref(false)
const error = ref<string | null>(null)
const nodeLogs = ref<ExecutionLog[]>([])

// 计算属性
const visible = computed({
  get: () => props.visible,
  set: (value) => emit('update:visible', value)
})

const inputData = computed(() => {
  // 从日志中提取输入数据
  const startLog = nodeLogs.value.find(log => 
    log.message && (log.message.includes('开始执行') || log.message.includes('开始'))
  )
  if (startLog?.data?.input) {
    return startLog.data.input
  }
  return null
})

const outputData = computed(() => {
  // 从日志中提取输出数据
  const completeLog = nodeLogs.value.find(log => 
    log.message && (log.message.includes('执行完成') || log.message.includes('完成'))
  )
  if (completeLog?.data?.output) {
    return completeLog.data.output
  }
  return null
})

const errorInfo = computed(() => {
  // 从日志中提取错误信息
  const errorLog = nodeLogs.value.find(log => 
    log.level === 'ERROR' || (log.message && (log.message.includes('失败') || log.message.includes('错误')))
  )
  if (errorLog?.data) {
    return {
      error_type: errorLog.data.error_type,
      error_message: errorLog.data.error || errorLog.data.error_message || errorLog.message
    }
  }
  return null
})

const executionTime = computed(() => {
  // 从日志中提取执行时间
  const completeLog = nodeLogs.value.find(log => 
    log.message && (log.message.includes('执行完成') || log.message.includes('完成'))
  )
  return completeLog?.duration || null
})

const statusText = computed(() => {
  if (errorInfo.value) return '失败'
  if (outputData.value) return '已完成'
  if (inputData.value) return '执行中'
  return '未知'
})

const statusType = computed(() => {
  if (errorInfo.value) return 'danger'
  if (outputData.value) return 'success'
  if (inputData.value) return 'warning'
  return 'info'
})

// 监听props变化，加载日志
watch([() => props.visible, () => props.executionId, () => props.nodeId], 
  ([newVisible, newExecutionId, newNodeId]) => {
    if (newVisible && newExecutionId && newNodeId) {
      loadNodeLogs()
    }
  },
  { immediate: true }
)

// 加载节点日志
const loadNodeLogs = async () => {
  if (!props.executionId || !props.nodeId) {
    return
  }
  
  loading.value = true
  error.value = null
  nodeLogs.value = []
  
  try {
    const response = await api.get(`/api/v1/execution-logs/executions/${props.executionId}`, {
      params: {
        node_id: props.nodeId,
        limit: 100
      }
    })
    
    nodeLogs.value = response.data || []
    
    // 按时间排序
    nodeLogs.value.sort((a, b) => {
      return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
    })
  } catch (err: any) {
    console.error('加载节点日志失败:', err)
    const errorDetail = err.response?.data?.detail || err.message || '加载日志失败'
    error.value = errorDetail
    
    // 如果是404错误，显示更友好的提示
    if (err.response?.status === 404) {
      ElMessage.warning('执行记录不存在或已过期，无法查看执行详情')
    } else {
      ElMessage.error('加载节点日志失败: ' + errorDetail)
    }
  } finally {
    loading.value = false
  }
}

// 格式化JSON
const formatJSON = (data: any) => {
  if (!data) return ''
  try {
    if (typeof data === 'string') {
      // 尝试解析为JSON
      const parsed = JSON.parse(data)
      return JSON.stringify(parsed, null, 2)
    }
    return JSON.stringify(data, null, 2)
  } catch {
    return String(data)
  }
}

// 格式化时间
const formatTime = (timestamp: string) => {
  if (!timestamp) return ''
  const date = new Date(timestamp)
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
  })
}

// 获取日志类型
const getLogType = (level: string) => {
  switch (level) {
    case 'ERROR':
      return 'danger'
    case 'WARN':
      return 'warning'
    case 'INFO':
      return 'primary'
    default:
      return 'info'
  }
}

// 获取日志图标
const getLogIcon = (level: string) => {
  switch (level) {
    case 'ERROR':
      return 'CircleClose'
    case 'WARN':
      return 'Warning'
    case 'INFO':
      return 'CircleCheck'
    default:
      return 'InfoFilled'
  }
}

// 复制到剪贴板
const copyToClipboard = async (data: any) => {
  try {
    const text = formatJSON(data)
    await navigator.clipboard.writeText(text)
    ElMessage.success('已复制到剪贴板')
  } catch (err) {
    ElMessage.error('复制失败')
  }
}
</script>

<style scoped>
.loading-container,
.error-container,
.empty-container {
  padding: 20px;
  text-align: center;
}

.execution-detail {
  padding: 0;
}

.info-card,
.data-card,
.error-card,
.timeline-card {
  margin-bottom: 16px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.json-viewer {
  background: #f5f7fa;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 12px;
  margin: 0;
  font-size: 12px;
  line-height: 1.6;
  overflow-x: auto;
  max-height: 400px;
  overflow-y: auto;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
}

.json-viewer-small {
  background: #f5f7fa;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 8px;
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  overflow-x: auto;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
}

.error-content {
  padding: 8px 0;
}

.error-type {
  margin-bottom: 12px;
  color: #f56c6c;
}

.error-message {
  color: #f56c6c;
}

.error-message pre {
  background: #fef0f0;
  border: 1px solid #fde2e2;
  border-radius: 4px;
  padding: 12px;
  margin-top: 8px;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-size: 12px;
  line-height: 1.6;
}

.timeline-content {
  padding-left: 8px;
}

.log-message {
  font-weight: 500;
  margin-bottom: 4px;
}

.log-duration {
  color: #909399;
  font-size: 12px;
  margin-top: 4px;
}

.log-data {
  margin-top: 8px;
}
</style>
