<template>
  <div class="debugger-container">
    <div class="debugger-toolbar">
      <el-button-group>
        <el-button type="primary" size="small" @click="startDebug" :disabled="isDebugging">
          <el-icon><VideoPlay /></el-icon> 开始调试
        </el-button>
        <el-button type="primary" size="small" @click="continueExecution" :disabled="!isDebugging">
          <el-icon><Right /></el-icon> 继续
        </el-button>
        <el-button type="primary" size="small" @click="stepOver" :disabled="!isDebugging">
          <el-icon><Bottom /></el-icon> 单步跳过
        </el-button>
        <el-button type="primary" size="small" @click="stepInto" :disabled="!isDebugging">
          <el-icon><TopRight /></el-icon> 单步进入
        </el-button>
        <el-button type="primary" size="small" @click="stepOut" :disabled="!isDebugging">
          <el-icon><TopLeft /></el-icon> 单步跳出
        </el-button>
        <el-button type="danger" size="small" @click="stopDebug" :disabled="!isDebugging">
          <el-icon><VideoPause /></el-icon> 停止调试
        </el-button>
      </el-button-group>
    </div>

    <div class="debugger-content">
      <div class="debugger-code">
        <code-editor 
          v-model="code" 
          :language="language" 
          :readOnly="isDebugging"
          height="400px"
          @line-click="toggleBreakpoint"
        />
        <div 
          v-for="(bp, index) in breakpoints" 
          :key="index" 
          class="breakpoint" 
          :style="{ top: (bp.line * 18) + 'px' }"
        ></div>
        <div 
          v-if="currentLine" 
          class="current-line" 
          :style="{ top: (currentLine * 18) + 'px' }"
        ></div>
      </div>

      <div class="debugger-panels">
        <el-tabs v-model="activePanel">
          <el-tab-pane label="控制台" name="console">
            <div class="console-output" ref="consoleOutputEl">
              <div v-for="(line, index) in consoleOutput" :key="index" class="console-line">
                {{ line }}
              </div>
            </div>
            <div class="console-input">
              <el-input 
                v-model="consoleInput" 
                placeholder="输入GDB命令..." 
                @keyup.enter="executeCommand"
                :disabled="!isDebugging"
              >
                <template #append>
                  <el-button @click="executeCommand" :disabled="!isDebugging">执行</el-button>
                </template>
              </el-input>
            </div>
          </el-tab-pane>
          
          <el-tab-pane label="变量" name="variables">
            <el-table :data="variables" style="width: 100%">
              <el-table-column prop="name" label="名称" />
              <el-table-column prop="value" label="值" />
              <el-table-column prop="type" label="类型" />
            </el-table>
          </el-tab-pane>
          
          <el-tab-pane label="调用栈" name="callstack">
            <el-table :data="callstack" style="width: 100%">
              <el-table-column prop="level" label="层级" width="60" />
              <el-table-column prop="function" label="函数" />
              <el-table-column prop="location" label="位置" />
            </el-table>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { VideoPlay, VideoPause, Right, Bottom, TopRight, TopLeft } from '@element-plus/icons-vue'
import CodeEditor from '@/components/CodeEditor/index.vue'
import { startDebugSession, executeDebugCommand, getDebugStatus, endDebugSession } from '@/api/exam/exam'

export default {
  name: 'Debugger',
  components: {
    CodeEditor,
    VideoPlay, VideoPause, Right, Bottom, TopRight, TopLeft
  },
  props: {
    modelValue: {
      type: String,
      default: ''
    },
    language: {
      type: String,
      default: 'cpp'
    },
    problemId: {
      type: [String, Number],
      required: true
    }
  },
  setup(props, { emit }) {
    const code = ref(props.modelValue)
    const isDebugging = ref(false)
    const sessionId = ref(null)
    const breakpoints = ref([])
    const currentLine = ref(null)
    const consoleOutput = ref([])
    const consoleInput = ref('')
    const activePanel = ref('console')
    const variables = ref([])
    const callstack = ref([])
    const consoleOutputEl = ref(null)
    const statusInterval = ref(null)

    // 监听代码变化
    watch(() => props.modelValue, (newVal) => {
      if (code.value !== newVal) {
        code.value = newVal
      }
    })

    watch(() => code.value, (newVal) => {
      if (props.modelValue !== newVal) {
        emit('update:modelValue', newVal)
      }
    })

    // 开始调试
    const startDebug = async () => {
      try {
        const response = await startDebugSession({
          code: code.value,
          language: props.language,
          problemId: props.problemId,
          breakpoints: breakpoints.value.map(bp => bp.line)
        })
        
        if (response.code === 200) {
          sessionId.value = response.data.sessionId
          isDebugging.value = true
          consoleOutput.value = ['调试会话已启动...']
          
          // 开始定期获取调试状态
          statusInterval.value = setInterval(updateDebugStatus, 1000)
          
          ElMessage.success('调试会话已启动')
        } else {
          ElMessage.error(response.msg || '启动调试失败')
        }
      } catch (error) {
        console.error('启动调试出错:', error)
        ElMessage.error('启动调试出错')
      }
    }

    // 停止调试
    const stopDebug = async () => {
      if (!sessionId.value) return
      
      try {
        await endDebugSession(sessionId.value)
        clearInterval(statusInterval.value)
        isDebugging.value = false
        sessionId.value = null
        currentLine.value = null
        variables.value = []
        callstack.value = []
        consoleOutput.value.push('调试会话已结束')
        ElMessage.info('调试会话已结束')
      } catch (error) {
        console.error('结束调试出错:', error)
        ElMessage.error('结束调试出错')
      }
    }

    // 执行GDB命令
    const executeCommand = async () => {
      if (!sessionId.value || !consoleInput.value) return
      
      try {
        consoleOutput.value.push(`> ${consoleInput.value}`)
        
        const response = await executeDebugCommand(sessionId.value, consoleInput.value)
        
        if (response.code === 200) {
          if (response.data.output) {
            consoleOutput.value.push(response.data.output)
          }
          
          // 更新调试状态
          updateDebugStatus()
        } else {
          consoleOutput.value.push(`错误: ${response.msg || '命令执行失败'}`)
        }
        
        consoleInput.value = ''
        
        // 滚动到控制台底部
        scrollToBottom()
      } catch (error) {
        console.error('执行命令出错:', error)
        consoleOutput.value.push(`错误: ${error.message || '命令执行出错'}`)
      }
    }

    // 更新调试状态
    const updateDebugStatus = async () => {
      if (!sessionId.value) return
      
      try {
        const response = await getDebugStatus(sessionId.value)
        
        if (response.code === 200) {
          const { currentLine: line, variables: vars, callstack: stack } = response.data
          
          currentLine.value = line
          variables.value = vars || []
          callstack.value = stack || []
        }
      } catch (error) {
        console.error('获取调试状态出错:', error)
      }
    }

    // 切换断点
    const toggleBreakpoint = (line) => {
      const index = breakpoints.value.findIndex(bp => bp.line === line)
      
      if (index >= 0) {
        breakpoints.value.splice(index, 1)
      } else {
        breakpoints.value.push({ line })
      }
      
      // 如果正在调试，更新断点
      if (isDebugging.value) {
        executeCommand(`break ${line}`)
      }
    }

    // 继续执行
    const continueExecution = () => {
      executeCommand('continue')
    }

    // 单步跳过
    const stepOver = () => {
      executeCommand('next')
    }

    // 单步进入
    const stepInto = () => {
      executeCommand('step')
    }

    // 单步跳出
    const stepOut = () => {
      executeCommand('finish')
    }

    // 滚动到控制台底部
    const scrollToBottom = () => {
      if (consoleOutputEl.value) {
        consoleOutputEl.value.scrollTop = consoleOutputEl.value.scrollHeight
      }
    }

    // 组件卸载前清理
    onBeforeUnmount(() => {
      if (statusInterval.value) {
        clearInterval(statusInterval.value)
      }
      
      if (sessionId.value) {
        endDebugSession(sessionId.value).catch(console.error)
      }
    })

    return {
      code,
      isDebugging,
      breakpoints,
      currentLine,
      consoleOutput,
      consoleOutputEl,
      consoleInput,
      activePanel,
      variables,
      callstack,
      startDebug,
      stopDebug,
      executeCommand,
      toggleBreakpoint,
      continueExecution,
      stepOver,
      stepInto,
      stepOut
    }
  }
}
</script>

<style scoped>
.debugger-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.debugger-toolbar {
  padding: 8px;
  border-bottom: 1px solid #dcdfe6;
  background-color: #f5f7fa;
}

.debugger-content {
  display: flex;
  flex: 1;
  overflow: hidden;
}

.debugger-code {
  position: relative;
  flex: 1;
  overflow: hidden;
  border-right: 1px solid #dcdfe6;
}

.breakpoint {
  position: absolute;
  left: 3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #f56c6c;
  z-index: 10;
}

.current-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 18px;
  background-color: rgba(64, 158, 255, 0.1);
  border-left: 2px solid #409eff;
  z-index: 5;
}

.debugger-panels {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.console-output {
  height: calc(100% - 40px);
  overflow-y: auto;
  padding: 8px;
  background-color: #1e1e1e;
  color: #d4d4d4;
  font-family: monospace;
}

.console-line {
  white-space: pre-wrap;
  line-height: 1.5;
}

.console-input {
  padding: 8px;
  border-top: 1px solid #dcdfe6;
}
</style> 