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

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

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

const toast = useToast()
const mountEl = ref<HTMLElement | null>(null)
const isMobileViewport = ref(false)
const isEditorReady = ref(false)
const editorContainerStyle = computed(() => {
  if (isMobileViewport.value) {
    return {
      height: 'min(62vh, 560px)',
      minHeight: '360px',
    }
  }
  return {
    height: 'min(78vh, 900px)',
    minHeight: '520px',
  }
})
let viewportMql: MediaQueryList | null = null
let onViewportChange: ((event: MediaQueryListEvent) => void) | null = null

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

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

onMounted(async () => {
  if (!import.meta.client) {
    return
  }
  viewportMql = window.matchMedia('(max-width: 767px)')
  isMobileViewport.value = viewportMql.matches
  onViewportChange = (event: MediaQueryListEvent) => {
    const nextIsMobile = event.matches
    const changed = handlePostBodyMarkdownEditorViewportSwitch({
      currentIsMobile: isMobileViewport.value,
      nextIsMobile,
      hasMountedEditor: Boolean(mountEl.value && bridge.getEditor()),
      remountEditor: () => {
        if (!mountEl.value) {
          return
        }
        bridge.unmount()
        bridge.mount(mountEl.value)
      },
    })
    if (changed) {
      isMobileViewport.value = nextIsMobile
    }
  }
  viewportMql.addEventListener('change', onViewportChange)
  await initializePostBodyMarkdownEditorVditor({
    importVditor: () => import('vditor'),
    isUnmounted: () => unmounted,
    onReady: (ctor) => {
      vditorCtor.value = ctor
      if (mountEl.value) {
        bridge.mount(mountEl.value)
        isEditorReady.value = true
      }
    },
    onError: (error) => {
      console.error('Failed to initialize Vditor editor', error)
    },
  })
})

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

onBeforeUnmount(() => {
  unmounted = true
  isEditorReady.value = false
  if (viewportMql && onViewportChange) {
    viewportMql.removeEventListener('change', onViewportChange)
  }
  onViewportChange = null
  viewportMql = null
  bridge.unmount()
})
</script>

<template>
  <ClientOnly>
    <div class="relative">
      <div
        ref="mountEl"
        :style="editorContainerStyle"
        class="w-full min-w-0 rounded-lg overflow-hidden ring ring-default"
      />
      <div
        v-if="!isEditorReady"
        class="absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 rounded-lg bg-default/80 backdrop-blur-[1px] text-muted ring ring-default"
        aria-live="polite"
        aria-busy="true"
      >
        <UIcon name="i-lucide-loader-2" class="size-5 animate-spin text-primary" />
        <span class="text-sm">编辑器加载中…</span>
      </div>
    </div>
    <template #fallback>
      <div class="text-muted text-sm py-12 text-center border border-default rounded-lg">
        编辑器加载中…
      </div>
    </template>
  </ClientOnly>
</template>

<style scoped>
@media (max-width: 767px) {
  :deep(.vditor) {
    min-width: 0;
    width: 100%;
  }

  :deep(.vditor-toolbar) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px;
    padding: 4px 6px;
  }

  :deep(.vditor-toolbar__item) {
    float: none;
    flex: 0 0 auto;
    padding: 0 !important;
  }

  :deep(.vditor-toolbar__item .vditor-tooltipped) {
    width: 30px;
    height: 30px;
    min-width: 30px;
    padding: 7px;
    border-radius: 6px;
  }

  :deep(.vditor-toolbar__divider) {
    display: none;
  }

  :deep(.vditor-content),
  :deep(.vditor-ir),
  :deep(.vditor-wysiwyg) {
    min-width: 0;
  }
}
</style>
