<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue'
import { NButton } from 'naive-ui'
import loader from '@monaco-editor/loader'

const props = defineProps<{ df: any; record: Record<string, any>; canEdit: boolean; ctx: any }>()

// Label布局：上下结构(vertical) 或 左右结构(horizontal)
const labelLayout = computed(() => props.df.label_layout || 'vertical')

const editorHost = ref<HTMLDivElement | null>(null)
let monaco: any = null
let editor: any = null
const expanded = ref(false)
const mode = ref<'preview' | 'edit'>('preview')
const htmlPreview = computed(() => String(props.record[props.df.fieldname] || ''))

async function mountEditor() {
  if (!editorHost.value) return
  if (!monaco) monaco = await loader.init()
  if (editor) return
  editor = monaco.editor.create(editorHost.value, {
    value: String(props.record[props.df.fieldname] || ''),
    language: 'html',
    automaticLayout: true,
    folding: true,
    minimap: { enabled: false },
    readOnly: !props.canEdit,
    wordWrap: 'on',
    wordWrapColumn: 120,
    wrappingStrategy: 'advanced',
    scrollBeyondLastLine: false,
    scrollBeyondLastColumn: 0,
    scrollbar: { horizontal: 'hidden', vertical: 'auto', horizontalScrollbarSize: 6, verticalScrollbarSize: 6, alwaysConsumeMouseWheel: false },
  })
  const refreshBars = () => {
    if (!editor || !editorHost.value) return
    const info = editor.getLayoutInfo()
    const hasV = editor.getScrollHeight() > info.height + 1
    const hasH = editor.getScrollWidth() > info.width + 1
    editorHost.value.classList.toggle('no-scroll-y', !hasV)
    editorHost.value.classList.toggle('no-scroll-x', !hasH)
  }
  refreshBars()
  editor.onDidContentSizeChange(() => refreshBars())
  editor.onDidScrollChange(() => refreshBars())
  editor.onDidLayoutChange(() => refreshBars())
  editor.onDidChangeModelContent(() => {
    if (!editor) return
    props.record[props.df.fieldname] = editor.getValue()
    refreshBars()
  })
}

function disposeEditor() {
  try { editor?.dispose() } catch {}
  editor = null
}

function toggleExpand() {
  expanded.value = !expanded.value
  nextTick(() => editor?.layout())
}

watch(() => props.canEdit, (v) => {
  editor?.updateOptions({ readOnly: !v })
})

watch(() => props.record[props.df.fieldname], (v) => {
  if (editor && v !== editor.getValue()) editor.setValue(String(v || ''))
})

onMounted(async () => {
  // 默认显示预览，不立即创建编辑器
})

// 修复：监听模式切换，进入编辑时创建编辑器，返回预览时销毁
watch(mode, async (m) => {
  if (m === 'edit') {
    await nextTick()
    await mountEditor()
    nextTick(() => editor?.layout())
  } else {
    disposeEditor()
  }
})

onBeforeUnmount(disposeEditor)
</script>

<template>
  <div :class="['field-wrapper', `layout-${labelLayout}`]">
    <label class="field-label">
      {{ ctx.t(df.label || df.fieldname) }}
      <span v-if="df.reqd" class="required">*</span>
    </label>
    <div class="html-editor">
      <div class="html-editor__toolbar">
        <n-button
          v-if="mode==='edit'"
          size="tiny"
          quaternary
          :type="'default'"
          @click="mode='preview'"
        >{{ ctx.t('Preview') }}</n-button>
        <n-button
          v-else
          size="tiny"
          quaternary
          :type="'default'"
          @click="mode='edit'"
        >{{ ctx.t('Edit') }}</n-button>
      </div>
      <div v-if="mode==='preview'" class="html-editor__preview" v-html="htmlPreview"></div>
      <div v-else ref="editorHost" class="html-editor__monaco" :class="{ collapsed: !expanded }"></div>
      <div class="html-editor__actions">
        <n-button size="tiny" quaternary @click="toggleExpand">{{ expanded ? ctx.t('Collapse') : ctx.t('Expand') }}</n-button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.html-editor { width: 100%; display: grid; grid-template-rows: auto 1fr; gap: 6px; }
.html-editor__toolbar { display: flex; }
.html-editor__preview {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 12px;
}
.html-editor__monaco {
  width: 100%;
  height: 500px; /* 默认高度限制，与云端一致 */
  border: 1px solid #e2e8f0;
  border-radius: 6px;
}
.html-editor__monaco.collapsed { height: 500px; }
.html-editor__monaco:not(.collapsed) { height: 800px; }
/* 细化 Monaco 滚动条，贴合系统风格 */
:deep(.monaco-editor .minimap) { display: none; }
:deep(.monaco-scrollable-element > .scrollbar) {
  background: transparent !important;
  opacity: 0.6;
}
:deep(.monaco-scrollable-element > .scrollbar:hover) { opacity: 0.9; }
:deep(.monaco-scrollable-element > .scrollbar.vertical) { width: 6px !important; }
:deep(.monaco-scrollable-element > .scrollbar.vertical .slider) {
  width: 6px !important;
  background: #cbd5e1 !important;
  border-radius: 4px !important;
}
:deep(.monaco-scrollable-element > .scrollbar.horizontal) { height: 6px !important; }
:deep(.monaco-scrollable-element > .scrollbar.horizontal .slider) {
  height: 6px !important;
  background: #cbd5e1 !important;
  border-radius: 4px !important;
}

/* 当无溢出时完全隐藏滚动条容器（配合 refreshBars 设置的 class）*/
.no-scroll-y :deep(.monaco-scrollable-element > .scrollbar.vertical) { display: none !important; }
.no-scroll-x :deep(.monaco-scrollable-element > .scrollbar.horizontal) { display: none !important; }
</style>


