<script setup>
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
import { setupMonaco } from '../../utils/monacoSetup'

const props = defineProps({
  modelValue: { type: String, default: '' },
  language: { type: String, default: 'markdown' },
  readOnly: { type: Boolean, default: false },
  minimap: { type: Boolean, default: false },
  lineNumbers: { type: Boolean, default: true },
  wordWrap: { type: Boolean, default: true },
  height: { type: String, default: '400px' }
})

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

const editorContainer = ref(null)
let editor = null
// 外部通过 modelValue 更新（watch 触发 setValue）时，屏蔽内部 change 事件，
// 避免上层「加载文件 → 设置 modelValue → 触发 change → 误标脏」链路
let suppressChange = false

// 语言映射表
function getLanguage(filename) {
  if (!filename) return 'plaintext'
  const ext = filename.split('.').pop().toLowerCase()
  const map = {
    js: 'javascript', jsx: 'javascript', ts: 'typescript', tsx: 'typescript',
    json: 'json', html: 'html', css: 'css', scss: 'scss', less: 'less',
    md: 'markdown', py: 'python', java: 'java', xml: 'xml', yaml: 'yaml',
    yml: 'yaml', sh: 'shell', bash: 'shell', sql: 'sql', rs: 'rust',
    go: 'go', vue: 'html', txt: 'plaintext'
  }
  return map[ext] || 'plaintext'
}

onMounted(async () => {
  setupMonaco()
  const monaco = await import('monaco-editor')

  await nextTick()

  editor = monaco.editor.create(editorContainer.value, {
    value: props.modelValue || '',
    language: props.language,
    theme: 'vs-dark',
    readOnly: props.readOnly,
    minimap: { enabled: props.minimap },
    lineNumbers: props.lineNumbers ? 'on' : 'off',
    wordWrap: props.wordWrap ? 'on' : 'off',
    automaticLayout: true,
    fontSize: 13,
    lineHeight: 20,
    scrollBeyondLastLine: false,
    renderLineHighlight: 'gutter',
    padding: { top: 12, bottom: 12 },
    overviewRulerBorder: false,
    scrollbar: {
      verticalScrollbarSize: 8,
      horizontalScrollbarSize: 8
    }
  })

  editor.onDidChangeModelContent(() => {
    if (suppressChange) return
    const value = editor.getValue()
    emit('update:modelValue', value)
    emit('change', value)
  })
})

onBeforeUnmount(() => {
  if (editor) {
    editor.dispose()
    editor = null
  }
})

// 外部 modelValue 变化时更新编辑器
watch(() => props.modelValue, (newVal) => {
  if (editor && editor.getValue() !== newVal) {
    // monaco.setValue 会同步触发 onDidChangeModelContent，包裹屏蔽标志
    suppressChange = true
    try {
      editor.setValue(newVal || '')
    } finally {
      suppressChange = false
    }
  }
})

// 外部 language 变化时更新
watch(() => props.language, (newLang) => {
  if (editor) {
    const model = editor.getModel()
    if (model) {
      import('monaco-editor').then(monaco => {
        monaco.editor.setModelLanguage(model, newLang)
      })
    }
  }
})

defineExpose({ getLanguage })
</script>

<template>
  <div
    ref="editorContainer"
    class="code-editor"
    :style="{ height }"
  />
</template>

<style scoped>
.code-editor {
  width: 100%;
  border-radius: 6px;
  overflow: hidden;
}
</style>
