<script setup lang="ts">
import 'vditor/dist/index.css'
import { createPostBodyMarkdownEditorBridge, type CreateVditorLikeOptions } from './post-body-markdown-editor-vditor-bridge'
import { initializePostBodyMarkdownEditorVditor } from './post-body-markdown-editor-vditor-init'
import { buildQuickNoteEditorVditorOptions } from './quick-note-editor-vditor-config'

const props = defineProps<{
  modelValue: string
  resizeSignal?: string
}>()

const emit = defineEmits<{
  'update:modelValue': [string]
}>()

const toast = useToast()
const mountEl = ref<HTMLElement | null>(null)
const initErrorMessage = ref('')

const vditorCtor = shallowRef<null | (new (element: HTMLElement, options: Record<string, unknown>) => {
  getValue: () => string
  setValue: (value: string, render?: boolean) => void
  destroy: () => void
})>(null)
let unmounted = false

const bridge = createPostBodyMarkdownEditorBridge({
  getModelValue: () => props.modelValue,
  emitUpdate: (value) => emit('update:modelValue', value),
  createEditor: ({ element, value, onInput }: CreateVditorLikeOptions) => {
    const Vditor = vditorCtor.value
    if (!Vditor) {
      throw new Error('Vditor constructor is not ready')
    }
    return new Vditor(element, buildQuickNoteEditorVditorOptions({
      value,
      onInput,
      onUploadError: () => {
        toast.add({ title: '图片上传失败', color: 'warning' })
      },
    }))
  },
})

function flushValue() {
  const current = bridge.getEditor()?.getValue()
  if (typeof current !== 'string') {
    return
  }
  if (current === props.modelValue) {
    return
  }
  emit('update:modelValue', current)
}

defineExpose<{
  flushValue: () => void
}>({
  flushValue,
})

onMounted(async () => {
  if (!import.meta.client) {
    return
  }
  await initializePostBodyMarkdownEditorVditor({
    importVditor: () => import('vditor'),
    isUnmounted: () => unmounted,
    onReady: (ctor) => {
      vditorCtor.value = ctor
      if (mountEl.value) {
        bridge.mount(mountEl.value)
      }
    },
    onError: (error) => {
      initErrorMessage.value = '编辑器加载失败，请刷新重试'
      toast.add({
        title: initErrorMessage.value,
        color: 'error',
      })
      console.error('Failed to initialize quick note editor', error)
    },
  })
})

watch(() => props.modelValue, () => {
  bridge.syncFromProps()
})

watch(() => props.resizeSignal, async () => {
  if (!import.meta.client) {
    return
  }
  await nextTick()
  const editor = bridge.getEditor() as { resize?: () => void } | null
  editor?.resize?.()
})

onBeforeUnmount(() => {
  unmounted = true
  bridge.unmount()
})
</script>

<template>
  <ClientOnly>
    <div v-if="initErrorMessage" class="h-full w-full min-w-0 rounded-lg border border-error/50 bg-error/10 px-4 py-8 text-center">
      <p class="text-sm text-error">
        {{ initErrorMessage }}
      </p>
    </div>
    <div
      v-else
      ref="mountEl"
      class="h-full w-full min-w-0 rounded-lg overflow-hidden ring ring-default"
    />
    <template #fallback>
      <div class="text-muted text-sm py-10 text-center border border-default rounded-lg">
        编辑器加载中…
      </div>
    </template>
  </ClientOnly>
</template>

<style scoped>
:deep(.vditor) {
  height: 100% !important;
  display: flex;
  min-height: 0;
  flex-direction: column;
}

:deep(.vditor-content) {
  flex: 1;
  min-height: 0;
}

:deep(.vditor-ir) {
  height: 100% !important;
  overflow: auto;
}
</style>
