<template>
  <transition name="slide">
    <div class="side-panel">
      <button @click="handleClose" class="close-btn"></button>
      <el-button type="primary" @click="UpdateFileCOntent">保存修改</el-button>
      <div class="content">
        <h2>{{ fileName }}</h2>
        <div class="editor-container">
          <textarea
            ref="textareaRef"
            v-model="localContent"
            @input="handleInput"
            @scroll="handleScroll"
            spellcheck="false"
          ></textarea>
          <pre class="highlight-container" ref="highlightRef"><code v-html="highlightedCode"></code></pre>
        </div>
      </div>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from "vue";
import { UpdateFileContentService } from "@/api/file";
import { ElMessage } from "element-plus";
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';

const props = defineProps({
  content: {
    type: String,
    default: "",
  },
  show: {
    type: Boolean,
    default: false,
  },
  fileName: {
    type: String,
    default: "编辑代码",
  },
  fileID: {
    type: Number,
    default: 0,
  },
});

const emit = defineEmits<{
  (e: "close"): void;
}>();

const textareaRef = ref<HTMLTextAreaElement | null>(null);
const highlightRef = ref<HTMLElement | null>(null);
const localContent = ref(props.content);
const highlightedCode = ref('');

// 根据文件名判断语言
const detectLanguage = (fileName: string) => {
  const extension = fileName.split('.').pop()?.toLowerCase();
  
  const languageMap: Record<string, string> = {
    'js': 'javascript',
    'jsx': 'javascript',
    'ts': 'typescript',
    'tsx': 'typescript',
    'html': 'html',
    'css': 'css',
    'scss': 'scss',
    'less': 'less',
    'py': 'python',
    'java': 'java',
    'php': 'php',
    'go': 'go',
    'rb': 'ruby',
    'rs': 'rust',
    'c': 'c',
    'cpp': 'cpp',
    'cs': 'csharp',
    'json': 'json',
    'md': 'markdown',
    'xml': 'xml',
    'yaml': 'yaml',
    'yml': 'yaml',
    'sh': 'bash',
    'bash': 'bash',
    'sql': 'sql',
  };
  
  return extension && languageMap[extension] ? languageMap[extension] : 'plaintext';
};

// 高亮代码
const highlightCode = () => {
  if (!localContent.value) {
    highlightedCode.value = '';
    return;
  }
  
  const language = detectLanguage(props.fileName);
  
  try {
    if (language !== 'plaintext') {
      const highlighted = hljs.highlight(localContent.value, { language });
      highlightedCode.value = highlighted.value;
    } else {
      // 如果无法检测语言，尝试自动检测
      const highlighted = hljs.highlightAuto(localContent.value);
      highlightedCode.value = highlighted.value;
    }
  } catch (error) {
    console.error('Highlight error:', error);
    // 降级处理：转义HTML并保留换行
    highlightedCode.value = localContent.value
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#039;');
  }
};

// 处理输入事件
const handleInput = () => {
  highlightCode();
  nextTick(() => {
    if (textareaRef.value && highlightRef.value) {
      // 同步滚动位置
      highlightRef.value.scrollTop = textareaRef.value.scrollTop;
      highlightRef.value.scrollLeft = textareaRef.value.scrollLeft;
    }
  });
};

// 处理滚动事件
const handleScroll = () => {
  if (textareaRef.value && highlightRef.value) {
    highlightRef.value.scrollTop = textareaRef.value.scrollTop;
    highlightRef.value.scrollLeft = textareaRef.value.scrollLeft;
  }
};

// 当props.content变化时同步到本地
watch(
  () => props.content,
  (newVal) => {
    localContent.value = newVal;
    highlightCode();
  }
);

// 当面板显示时自动聚焦到textarea
watch(
  () => props.show,
  async (newVal) => {
    if (newVal) {
      await nextTick();
      textareaRef.value?.focus();
      highlightCode();
    }
  }
);

// 初始化
onMounted(() => {
  highlightCode();
});

const handleClose = () => {
  emit("close");
};

const UpdateFileCOntent = async () => {
  let req = {
    token: localStorage.getItem("token"),
    file_id: props.fileID,
    file_content: localContent.value,
  };
  try {
    let result = await UpdateFileContentService(req);
    if (result["code"] === 0) {
      ElMessage.success("修改成功");
    } else {
      ElMessage.error("修改失败");
    }
  } catch (e) {
    console.log(e);
  }
};
</script>

<style scoped lang="css">
.side-panel {
  position: fixed;
  top: 0;
  right: 0;
  width: 70%;
  height: 100%;
  background-color: #282c34;
  z-index: 1001;
  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.3);
  padding: 20px;
  display: flex;
  flex-direction: column;
  color: #abb2bf;
}

.close-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 30px;
  height: 30px;
  background: none;
  border: none;
  cursor: pointer;
  z-index: 1;
}

.close-btn::before,
.close-btn::after {
  content: '';
  position: absolute;
  width: 20px;
  height: 2px;
  background-color: #abb2bf;
  top: 50%;
  left: 50%;
  transition: background-color 0.2s;
}

.close-btn::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

.close-btn:hover::before,
.close-btn:hover::after {
  background-color: #61afef;
}

.content {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin-top: 20px;
}

.content h2 {
  color: #e5e5e5;
  margin-bottom: 15px;
}

.editor-container {
  position: relative;
  flex: 1;
  border-radius: 4px;
  background-color: #282c34;
  overflow: hidden;
}

.editor-container textarea {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 12px;
  border: 1px solid #3e4451;
  border-radius: 4px;
  resize: none;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  color: transparent;
  background-color: transparent;
  caret-color: #61afef;
  z-index: 2;
  white-space: pre;
  overflow: auto;
  tab-size: 2;
}

.editor-container textarea:focus {
  outline: none;
  border-color: #61afef;
}

.highlight-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 12px;
  margin: 0;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  pointer-events: none;
  overflow: auto;
  z-index: 1;
  white-space: pre;
  tab-size: 2;
  background-color: #282c34;
}

.highlight-container code {
  font-family: inherit;
}

/* 滚动条样式 */
.editor-container textarea::-webkit-scrollbar,
.highlight-container::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.editor-container textarea::-webkit-scrollbar-track,
.highlight-container::-webkit-scrollbar-track {
  background: #21252b;
}

.editor-container textarea::-webkit-scrollbar-thumb,
.highlight-container::-webkit-scrollbar-thumb {
  background: #3e4451;
  border-radius: 4px;
}

.editor-container textarea::-webkit-scrollbar-thumb:hover,
.highlight-container::-webkit-scrollbar-thumb:hover {
  background: #4b5363;
}

/* 保存按钮样式 */
:deep(.el-button--primary) {
  background-color: #61afef;
  border-color: #61afef;
}

:deep(.el-button--primary:hover) {
  background-color: #528bbc;
  border-color: #528bbc;
}

.slide-enter-active,
.slide-leave-active {
  transition: transform 0.3s ease;
}

.slide-enter-from,
.slide-leave-to {
  transform: translateX(100%);
}
</style>