<template>
  <div class="plugin-editor-wrapper" :style="{ height: height + 'px' }">
    <div class="editor-container">
      <div class="editor-toolbar" v-if="!readonly">
        <el-tooltip content="格式化代码" placement="top" v-if="['JavaScript', 'LUA'].includes(language)">
          <el-button type="primary" link @click="formatCode">
            <el-icon><Operation /></el-icon>
          </el-button>
        </el-tooltip>

        <el-dropdown @command="handleSnippetSelect" trigger="click" v-if="['JavaScript', 'LUA'].includes(language)">
          <el-button type="primary" link>
            <el-icon><Document /></el-icon>
            <span>插入代码片段</span>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item v-for="(snippet, index) in snippets"
                              :key="index"
                              :command="snippet.code">
                {{ snippet.name }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>

      <!-- 当Monaco编辑器加载失败时显示的备用文本区 -->
      <el-input
        v-if="useTextarea"
        v-model="codeValue"
        type="textarea"
        :autosize="{ minRows: 10, maxRows: 20 }"
        :readonly="readonly"
        :placeholder="getPlaceholder()"
        class="code-textarea"
        @input="handleTextareaInput"
      />

      <!-- Monaco编辑器容器 -->
      <div v-else ref="editorContainer" class="monaco-editor-container"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, computed, nextTick, markRaw } from 'vue';
import { ElMessage } from 'element-plus';
import { Operation, Document } from '@element-plus/icons-vue';

// 是否使用textarea作为降级方案
const useTextarea = ref(false);
// 延迟加载Monaco编辑器，避免直接导入可能带来的问题
let monaco: any = null;

// 在组件挂载后动态加载Monaco编辑器
const loadMonaco = async () => {
  try {
    // 动态导入Monaco编辑器
    monaco = await import('monaco-editor');
    // 成功加载后的处理
    nextTick(() => {
      initMonacoEditor();
    });
  } catch (e) {
    // 如果加载失败，使用textarea作为备选方案
    useTextarea.value = true;
    // 在控制台记录错误，但不提示给用户
    // console.error('Monaco编辑器加载失败，使用备选文本编辑器', e);
  }
};

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  height: {
    type: Number,
    default: 300
  },
  language: {
    type: String,
    default: 'JavaScript',
    validator: (value: string) => ['JavaScript', 'LUA', 'Go'].includes(value)
  },
  readonly: {
    type: Boolean,
    default: false
  }
});

const emit = defineEmits(['update:modelValue']);

// 编辑器相关引用
const codeValue = ref(props.modelValue);
const editorContainer = ref(null);
const editorInstance = ref(null);
const isFormatting = ref(false); // 格式化状态标记
const isInserting = ref(false); // 插入片段状态标记

// JavaScript代码片段
const jsSnippets = [
  {
    name: '前置插件模板',
    code: `// 前置插件模板
// 参数: ctx - 上下文对象，包含请求信息
// 返回: 修改后的上下文对象
function beforePlugin(ctx) {
  // 这里可以访问和修改ctx中的数据
  // 例如: ctx.request.headers, ctx.request.params等
  
  console.log("执行前置插件逻辑");
  
  // 可以修改请求参数
  if (ctx.request && ctx.request.params) {
    ctx.request.params.addedByPlugin = true;
  }
  
  // 返回修改后的上下文
  return ctx;
}`
  },
  {
    name: '后置插件模板',
    code: `// 后置插件模板
// 参数: ctx - 上下文对象，包含请求和响应信息
// 返回: 修改后的上下文对象
function afterPlugin(ctx) {
  // 这里可以访问和修改ctx中的数据
  // 例如: ctx.response.data, ctx.response.headers等
  
  console.log("执行后置插件逻辑");
  
  // 可以修改响应数据
  if (ctx.response && ctx.response.data) {
    ctx.response.data.processedByPlugin = true;
  }
  
  // 返回修改后的上下文
  return ctx;
}`
  },
  {
    name: '数据转换',
    code: `// 数据转换示例
function transform(data) {
  if (Array.isArray(data)) {
    return data.map(item => ({
      ...item,
      transformed: true
    }));
  }
  
  return {
    ...data,
    transformed: true
  };
}`
  },
  {
    name: '参数验证',
    code: `// 参数验证示例
function validateParams(params) {
  if (!params.id) {
    throw new Error("缺少必要参数: id");
  }
  
  if (params.type && !["A", "B", "C"].includes(params.type)) {
    throw new Error("type参数值无效，必须是A、B或C之一");
  }
  
  return true;
}`
  }
];

// LUA代码片段
const luaSnippets = [
  {
    name: '前置插件模板',
    code: `-- 前置插件模板
-- 参数: ctx - 上下文对象，包含请求信息
-- 返回: 修改后的上下文对象
function before_plugin(ctx)
  -- 这里可以访问和修改ctx中的数据
  -- 例如: ctx.request.headers, ctx.request.params等
  
  print("执行前置插件逻辑")
  
  -- 可以修改请求参数
  if ctx.request and ctx.request.params then
    ctx.request.params.added_by_plugin = true
  end
  
  -- 返回修改后的上下文
  return ctx
end

return before_plugin`
  },
  {
    name: '后置插件模板',
    code: `-- 后置插件模板
-- 参数: ctx - 上下文对象，包含请求和响应信息
-- 返回: 修改后的上下文对象
function after_plugin(ctx)
  -- 这里可以访问和修改ctx中的数据
  -- 例如: ctx.response.data, ctx.response.headers等
  
  print("执行后置插件逻辑")
  
  -- 可以修改响应数据
  if ctx.response and ctx.response.data then
    ctx.response.data.processed_by_plugin = true
  end
  
  -- 返回修改后的上下文
  return ctx
end

return after_plugin`
  },
  {
    name: '数据转换',
    code: `-- 数据转换示例
function transform(data)
  if type(data) == "table" then
    -- 判断是否是数组
    if #data > 0 then
      local result = {}
      for i, item in ipairs(data) do
        item.transformed = true
        table.insert(result, item)
      end
      return result
    else
      -- 处理普通对象
      data.transformed = true
      return data
    end
  end
  
  return data
end`
  },
  {
    name: '参数验证',
    code: `-- 参数验证示例
function validate_params(params)
  if not params.id then
    error("缺少必要参数: id")
  end
  
  if params.type then
    local valid = false
    for _, v in ipairs({"A", "B", "C"}) do
      if params.type == v then
        valid = true
        break
      end
    end
    
    if not valid then
      error("type参数值无效，必须是A、B或C之一")
    end
  end
  
  return true
end`
  }
];

// Go插件路径示例
const goSnippets = [
  {
    name: 'Go插件路径示例',
    code: 'plugins/my_plugin.so'
  }
];

// 使用计算属性，根据当前语言动态返回相应的代码片段
const snippets = computed(() => {
  switch (props.language) {
    case 'JavaScript':
      return jsSnippets;
    case 'LUA':
      return luaSnippets;
    case 'Go':
      return goSnippets;
    default:
      return jsSnippets;
  }
});

// 获取编辑器语言
const getEditorLanguage = () => {
  switch (props.language) {
    case 'JavaScript':
      return 'javascript';
    case 'LUA':
      return 'lua';
    case 'Go':
      // 对于Go路径，我们使用普通文本编辑器
      return 'plaintext';
    default:
      return 'javascript';
  }
};

// 监听值变化
watch(() => props.modelValue, (newValue) => {
  if (newValue !== codeValue.value) {
    codeValue.value = newValue;
    if (editorInstance.value) {
      // 使用安全的方式更新编辑器内容
      const model = editorInstance.value.getModel();
      if (model) {
        model.setValue(newValue);
      }
    }
  }
});

// 监听语言变化
watch(() => props.language, () => {
  // 语言变化时重新初始化编辑器
  nextTick(() => {
    initMonacoEditor();
  });
});

// 完全禁用Monaco编辑器的worker加载
// 这种方式确保不会尝试加载任何worker脚本
if (typeof window !== 'undefined') {
  window.MonacoEnvironment = {
    // 创建一个空的worker，不尝试加载任何脚本
    getWorker: function() {
      // 返回一个空的worker
      return {
        addEventListener: function() {},
        removeEventListener: function() {},
        postMessage: function() {},
        terminate: function() {}
      };
    }
  };
}

// 初始化Monaco编辑器
const initMonacoEditor = () => {
  if (!editorContainer.value || !monaco) return;

  try {
    // 清理现有实例
    if (editorInstance.value) {
      editorInstance.value.dispose();
      editorInstance.value = null;
    }

    // 确保容器是空的
    if (editorContainer.value.childNodes.length > 0) {
      editorContainer.value.innerHTML = '';
    }

    // 禁用所有worker，防止加载失败
    if (typeof window !== 'undefined' && !window.MonacoEnvironment) {
      window.MonacoEnvironment = {
        getWorkerUrl: function() { return ''; }
      };
    }
    
    // 创建编辑器实例
    // 非常简化的编辑器配置，只保留最基本的功能
    const editor = monaco.editor.create(editorContainer.value, {
      value: codeValue.value || '',
      language: getEditorLanguage(),
      theme: 'vs',
      automaticLayout: true,
      minimap: { enabled: false },
      readOnly: props.readonly
    });

    editorInstance.value = markRaw(editor);

    // 使用节流处理内容变化
    const handleContentChange = () => {
      const currentEditor = editorInstance.value;
      if (!currentEditor) return;
      const value = currentEditor.getValue();
      codeValue.value = value;
      emit('update:modelValue', value);
    };
    const changeModelDisposable = editorInstance.value.onDidChangeModelContent(handleContentChange);

    // 在组件销毁时清理事件监听器
    onBeforeUnmount(() => {
      if (changeModelDisposable) {
        try {
          changeModelDisposable.dispose();
        } catch (e) {
          // Error handling if needed
        }
      }
      
      // 确保也清理 editorInstance
      if (editorInstance.value) {
        try {
          editorInstance.value.dispose();
        } catch (e) {
          // Error handling if needed
        }
        editorInstance.value = null;
      }
    });
  } catch (e) {
    // 初始化编辑器失败
  }
};

// 格式化代码
const formatCode = async () => {
  if (isFormatting.value || !editorInstance.value) return;
  
  isFormatting.value = true;
  try {
    const currentValue = editorInstance.value.getValue();
    if (!currentValue) {
      isFormatting.value = false;
      return;
    }

    // 使用Monaco编辑器的格式化功能
    await editorInstance.value.getAction('editor.action.formatDocument')?.run();
    
    // 触发内容更新
    codeValue.value = editorInstance.value.getValue();
    emit('update:modelValue', codeValue.value);
    ElMessage.success('格式化成功');
  } catch (error) {
    // 格式化失败
    ElMessage.error('格式化失败');
  } finally {
    isFormatting.value = false;
  }
};

// 处理代码片段选择 - 使用防抖动处理
const handleSnippetSelect = (snippet: string) => {
  if (isInserting.value || !editorInstance.value) return;
  
  isInserting.value = true;
  try {
    // 获取当前编辑器的位置
    const position = editorInstance.value.getPosition();
    
    // 创建一个编辑操作
    const edit = {
      range: {
        startLineNumber: position.lineNumber,
        startColumn: position.column,
        endLineNumber: position.lineNumber,
        endColumn: position.column
      },
      text: snippet
    };
    
    // 应用编辑操作
    editorInstance.value.executeEdits('snippet-insert', [edit]);
    
    // 触发内容更新
    codeValue.value = editorInstance.value.getValue();
    emit('update:modelValue', codeValue.value);
  } catch (error) {
    // 插入代码片段失败
  } finally {
    isInserting.value = false;
  }
};

// 添加备用文本编辑器的处理方法
const handleTextareaInput = () => {
  emit('update:modelValue', codeValue.value);
};

// 获取适合当前语言的占位符文本
const getPlaceholder = () => {
  switch (props.language) {
    case 'JavaScript':
      return '请输入JavaScript插件代码';
    case 'LUA':
      return '请输入LUA插件代码';
    case 'Go':
      return '请输入Go插件路径，如 plugins/my_plugin.so';
    default:
      return '请输入插件代码';
  }
};

// 组件挂载后的生命周期钩子
onMounted(() => {
  // 延迟加载 Monaco 编辑器并初始化
  setTimeout(() => {
    loadMonaco();
  }, 300);
});

// 组件销毁前
onBeforeUnmount(() => {
  // 清理编辑器实例
  if (editorInstance.value) {
    try {
      editorInstance.value.dispose();
      editorInstance.value = null;
    } catch (e) {
      // 忽略错误
    }
  }
});
</script>

<style scoped>
.plugin-editor-wrapper {
  width: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.editor-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.editor-toolbar {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #dcdfe6;
}

.monaco-editor-container {
  flex: 1;
  overflow: hidden;
}
</style>
