<!-- 富文本编辑器 -->
<template>
  <component v-if="inlineEditor" :is="tagName" :id="elementId" />
  <textarea v-else :id="elementId"></textarea>
</template>

<script lang="ts" setup>
  import {
    watch,
    onMounted,
    onBeforeUnmount,
    onActivated,
    onDeactivated,
    nextTick,
    useAttrs
  } from 'vue';
  // TinyMCE 类型定义（避免引入实际模块）
  type TinyMCEEditor = any;
  type EditorEvent = any;
  type RawEditorSettings = any;

  import { storeToRefs } from 'pinia';
  import { useThemeStore } from '@/store/modules/theme';
  import {
    DEFAULT_CONFIG,
    DARK_CONFIG,
    uuid,
    bindHandlers,
    openAlert,
    setupTextIndent
  } from './util';
  import type { AlertOption } from './util';
  import { message } from 'ant-design-vue';

  const props = withDefaults(
    defineProps<{
      // 编辑器唯一 id
      id?: string;
      // v-model
      value?: string;
      // 编辑器配置
      init?: RawEditorSettings;
      // 是否内联模式
      inline?: boolean;
      // model events
      modelEvents?: string;
      // 内联模式标签名
      tagName?: string;
      // 是否禁用
      disabled?: boolean;
      // 是否跟随框架主题
      autoTheme?: boolean;
      // 不跟随框架主题时是否使用暗黑主题
      darkTheme?: boolean;
      // 编辑器是否可见（用于控制初始化时机）
      editorVisible?: boolean;
    }>(),
    {
      inline: false,
      modelEvents: 'change input undo redo',
      tagName: 'div',
      autoTheme: true,
      editorVisible: true
    }
  );

  const emit = defineEmits<{
    (e: 'update:value', value: string): void;
  }>();

  const attrs = useAttrs();
  const themeStore = useThemeStore();
  const { darkMode } = storeToRefs(themeStore);

  // TinyMCE 通过 CDN 加载在 window.tinymce
  const getTinymce = () => (window as any).tinymce;

  // 编辑器唯一 id
  const elementId: string = props.id || uuid('tiny-vue');

  // 编辑器实例
  let editorIns: TinyMCEEditor | null = null;

  // 是否内联模式
  const inlineEditor: boolean = props.init?.inline || props.inline;

  /* 更新 value */
  const updateValue = (value: string) => {
    emit('update:value', value);
  };

  /* 修改内容 */
  const setContent = (value?: string) => {
    if (
      editorIns &&
      typeof value === 'string' &&
      value !== editorIns.getContent()
    ) {
      editorIns.setContent(value);
    }
  };

  /* 渲染编辑器 */
  const render = () => {
    // 如果 prop 标记为不可见，跳过初始化
    if (!props.editorVisible) {
      console.log('[TinymceEditor] Skipping render - editorVisible is false');
      return;
    }

    const isDark = props.autoTheme ? darkMode.value : props.darkTheme;
    const tinymce = getTinymce();
    if (!tinymce) {
      console.warn('[TinymceEditor] window.tinymce is not available, retrying in 100ms...');
      setTimeout(render, 100);
      return;
    }
    // 如果容器元素不可见（如在隐藏的 tab 里），等待其可见后再初始化
    const el = document.getElementById(elementId);
    if (!el) {
      // DOM 还未就绪，稍后重试
      setTimeout(render, 50);
      return;
    }
    {
      // 检测元素是否真正可见：display:none 或 visibility:hidden 或 height:0 都算隐藏
      const isVisible = (() => {
        let node: Element | null = el;
        while (node && node !== document.body) {
          const style = window.getComputedStyle(node);
          if (style.display === 'none' || style.visibility === 'hidden') return false;
          if (style.height === '0px' && (style.overflow === 'hidden' || style.overflowY === 'hidden')) return false;
          node = node.parentElement;
        }
        return true;
      })();
      if (!isVisible) {
        const checkVisible = () => {
          const el2 = document.getElementById(elementId);
          if (!el2) return false;
          let node: Element | null = el2;
          while (node && node !== document.body) {
            const s = window.getComputedStyle(node);
            if (s.display === 'none' || s.visibility === 'hidden') return false;
            if (s.height === '0px' && (s.overflow === 'hidden' || s.overflowY === 'hidden')) return false;
            node = node.parentElement;
          }
          return true;
        };
        const observer = new MutationObserver(() => {
          if (checkVisible()) {
            observer.disconnect();
            render();
          }
        });
        // 监听父级 DOM 变化（tab 切换时会修改 style）
        let parent: Element | null = el.parentElement;
        while (parent) {
          observer.observe(parent, { attributes: true, attributeFilter: ['style', 'class'] });
          parent = parent.parentElement;
          if (parent === document.body) break;
        }
        return;
      }
    }
    // 如果已经初始化过，不重复初始化
    if (editorIns) return;
    try {
      tinymce.init({
        ...DEFAULT_CONFIG,
        ...(isDark ? DARK_CONFIG : {}),
        ...(props.init || {}),
        selector: `#${elementId}`,
        readonly: props.disabled,
        inline: inlineEditor,
        setup: (editor: TinyMCEEditor) => {
          editorIns = editor;

          // 添加首行缩进功能
          setupTextIndent(editor);

          editor.on('init', (e: EditorEvent<any>) => {
            // 回显初始值
            if (props.value) {
              setContent(props.value);
            }
            // v-model
            editor.on(props.modelEvents, () => {
              updateValue(editor.getContent());
            });
            // valid events
            bindHandlers(e, attrs, editor);
          });
          if (typeof props.init?.setup === 'function') {
            props.init.setup(editor);
          }
        }
      }).catch((err: any) => {
        console.error('[TinymceEditor] init failed:', err);
        message.error('编辑器初始化失败: ' + (err?.message || err));
      });
    } catch (err: any) {
      console.error('[TinymceEditor] init threw error:', err);
      message.error('编辑器初始化异常: ' + (err?.message || err));
    }
  };

  /* 销毁编辑器 */
  const destory = () => {
    const tinymce = getTinymce();
    if (tinymce != null && editorIns != null) {
      tinymce.remove(editorIns as any);
      editorIns = null;
    }
  };

  /* 弹出提示框 */
  const alert = (option?: AlertOption) => {
    openAlert(editorIns, option);
  };

  defineExpose({ editorIns, alert });

  watch(
    () => props.value,
    (val: string, prevVal: string) => {
      if (val !== prevVal) {
        setContent(val);
      }
    }
  );

  watch(
    () => props.disabled,
    (disable) => {
      if (editorIns !== null) {
        if (typeof editorIns.mode?.set === 'function') {
          editorIns.mode.set(disable ? 'readonly' : 'design');
        } else {
          editorIns.setMode(disable ? 'readonly' : 'design');
        }
      }
    }
  );

  watch(
    () => props.tagName,
    () => {
      destory();
      nextTick(() => {
        render();
      });
    }
  );

  watch(darkMode, () => {
    if (props.autoTheme) {
      destory();
      nextTick(() => {
        render();
      });
    }
  });

  // 监听 editorVisible 变化，当变为可见时触发渲染
  watch(
    () => props.editorVisible,
    (visible) => {
      if (visible) {
        console.log('[TinymceEditor] editorVisible changed to true, triggering render');
        nextTick(() => {
          render();
        });
      }
    }
  );

  onMounted(() => {
    render();
  });

  onBeforeUnmount(() => {
    destory();
  });

  onActivated(() => {
    render();
  });

  onDeactivated(() => {
    destory();
  });
</script>

<style>
  body .tox-tinymce-aux {
    z-index: 19990000;
  }

  textarea[id^='tiny-vue'] {
    width: 0;
    height: 0;
    margin: 0;
    padding: 0;
    opacity: 0;
    box-sizing: border-box;
  }
</style>
