<template>
  <div>
    <div ref="editor"></div>
  </div>
</template>

<script>
import Vue from "vue";
import Quill from "quill";
import PresetReplyBlot from "./preset-reply-blot.js";
import { EventBus } from "../../../event-bus";
import LocalMixin from "../../../mixins/locale-mixin.ts";
import { consts } from "../../../constants.ts";

Quill.register(PresetReplyBlot);

export default Vue.extend({
  name: "QuillEditor",
  inject: {
    showVideoScreenShotButton: {
      default: false,
    },
    $rootComponent: {
      default: {},
    },
  },
  mixins: [LocalMixin],
  props: {
    value: {
      type: String,
      default: "",
    },
    placeholder: {
      type: String,
      default: "",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    maxlength: {
      type: Number,
      default: 5000,
    },
  },
  mounted() {
    this.initQuill();
    EventBus.$on("screen-shot-urls", this.handleScreenShotUrl);
    this.componentId = this.generateRandomId();
  },
  computed: {
    imageCount() {
      if (this.value) {
        let imgTagRegex = /<img\s[^>]*src=[\"']?([^>\"']+)[\"']?[^>]*>/g;
        let matches = this.value.match(imgTagRegex);
        return matches ? matches.length : 0;
      }
      return 0;
    },
  },
  methods: {
    handleScreenShotUrl(screenData) {
      if (this.componentId === screenData.messageId) {
        // 清除超时定时器
        if (this.screenShotTimeoutId) {
          clearTimeout(this.screenShotTimeoutId);
          this.screenShotTimeoutId = null;
        }

        // 恢复按钮状态
        this.setScreenShotButtonEnabled(true);
        this.isScreenShotting = false;

        if (this.imageCount > consts.RICH_TEXT_IMAGE_COUNT_LIMIT) {
          this.$Message.error(
            this.getLocaleValue(
              "survey_creator.common.tips.upload_image_exceed_the_limit"
            )
          );
          return;
        }
        for (let url of screenData.urls) {
          this.insertImageUrl(url);
        }
      }
    },
    insertImageEmbed(url) {
      let range = this.quill.getSelection();
      if (!range) {
        range = { index: this.quill.getLength(), length: 0 };
      }
      this.quill.insertEmbed(range, "image", url, "user");
      this.$nextTick(() => {
        this.quill.update("user");
      });
    },
    insertImageUrl(url) {
      if (url) {
        let range = this.quill.getSelection();
        if (!range) {
          range = { index: this.quill.getLength(), length: 0 };
        }
        const imgTag = `<img src="${url}" alt="image load fail">`;
        this.quill.clipboard.dangerouslyPasteHTML(range.index, imgTag);
        this.quill.setSelection(range.index + 1);
      }
    },
    changeVideoScreenShotButtonName() {
      // 查找自定义按钮并更新其文本
      const toolbar = this.quill.getModule("toolbar");
      const buttons = toolbar.container.querySelectorAll(
        "button.ql-video-screen-shot"
      );
      if (buttons.length > 0) {
        let button = buttons[0];
        // 先设置样式，避免抖动
        button.style.visibility = "hidden";
        button.innerHTML = this.getLocaleValue(
          "survey_creator.common.tips.get_screen_shot_name"
        );
        button.style.padding = "2px";
        button.style.fontSize = "12px";
        button.style.color = "rgb(105, 140, 208)";
        button.style.border = "1px solid rgb(105, 140, 208)";
        button.style.borderRadius = "4px";
        button.style.width = "auto";
        button.style.display = "flex";
        button.style.alignItems = "center";
        // 样式设置完成后再显示，避免抖动
        this.$nextTick(() => {
          button.style.visibility = "visible";
        });
      }
    },
    getScreenShotButton() {
      // 获取截屏按钮
      const toolbar = this.quill.getModule("toolbar");
      const buttons = toolbar.container.querySelectorAll(
        "button.ql-video-screen-shot"
      );
      return buttons.length > 0 ? buttons[0] : null;
    },
    setScreenShotButtonEnabled(enabled) {
      // 设置截屏按钮的启用/禁用状态
      const button = this.getScreenShotButton();
      if (button) {
        if (enabled) {
          button.disabled = false;
          button.style.opacity = "1";
          button.style.cursor = "pointer";
          button.innerHTML = this.getLocaleValue(
            "survey_creator.common.tips.get_screen_shot_name"
          );
        } else {
          button.disabled = true;
          button.style.opacity = "0.6";
          button.style.cursor = "not-allowed";
          button.innerHTML =
            this.getLocaleValue(
              "survey_creator.common.tips.get_screen_shot_name"
            ) + "...";
        }
      } else {
        console.log("⚠️ [QuillEditor-Creator] Screenshot button not found");
      }
    },
    initQuill() {
      let toolbarOptions = [
        [
          "bold",
          "italic",
          "underline",
          "strike",
          { list: "ordered" },
          { list: "bullet" },
          { color: [] },
          { background: [] },
          { align: [] },
          "clean",
        ],
      ];
      if (this.showVideoScreenShotButton) {
        toolbarOptions.push([{ "video-screen-shot": "video-screen-shot" }]);
      }
      this.quill = new Quill(this.$refs.editor, {
        theme: "snow", // 或者 'bubble'
        placeholder: this.disabled ? "" : this.placeholder,
        readOnly: this.disabled,
        modules: {
          toolbar: this.disabled
            ? false
            : {
                container: toolbarOptions,
                handlers: {
                  "video-screen-shot": this.customVideoScreenShot,
                },
              },
        },
      });
      this.quill.root.innerHTML = this.value;
      this.quill.on("text-change", this.handleTextChange);
      //quill 剪切事件自定义处理
      this.quill.root.addEventListener("paste", this.handlePaste, true);
      // 中文输入法开始时立即隐藏 placeholder，避免与拼音文本重叠
      this.quill.root.addEventListener("compositionstart", () => {
        this.quill.root.classList.remove("ql-blank");
      });

      // 设置 readOnly 模式下的背景颜色
      if (this.disabled) {
        this.setReadOnlyBackgroundColor();
      }

      if (this.showVideoScreenShotButton && !this.disabled) {
        // 使用 $nextTick 确保 DOM 更新完成后再设置按钮样式，避免抖动
        this.$nextTick(() => {
          this.changeVideoScreenShotButtonName();
        });
      }
    },
    handleTextChange() {
      let text = this.quill.getText();
      if (text.length > this.maxlength) {
        this.$Message.error(
          this.getLocaleValue("survey_creator.common.tips.max_length_hint")
        );
        this.quill.deleteText(this.maxlength, text.trim().length);
      }
      text = this.quill.getText();
      let html = this.quill.root.innerHTML;
      //手动删除文字时，删空富文本留下的内容是<p><br></p>。需要将内容修改为'',外层必填校验才会生效
      if (html.trim() === "<p><br></p>") {
        // 设置编辑器内容为空
        this.quill.root.innerHTML = "";
        html = "";
      }
      this.$emit("input", html);
    },
    handlePaste(event) {
      let clipboard = event.clipboardData || window.clipboardData;
      // IE 11 is .files other browsers are .items
      if (clipboard && (clipboard.items || clipboard.files)) {
        let items = clipboard.items || clipboard.files;
        const IMAGE_MIME_REGEX = /^image\/(jpe?g|gif|png|svg|webp)$/i;

        for (let i = 0; i < items.length; i++) {
          if (IMAGE_MIME_REGEX.test(items[i].type)) {
            let file = items[i].getAsFile ? items[i].getAsFile() : items[i];

            if (file) {
              this.quill.focus();
              this.range = this.quill.getSelection();
              event.preventDefault();
              setTimeout(() => {
                this.quill.focus();
                this.range = this.quill.getSelection();
                this.uploadAndInsertImage(file);
              }, 0);
            }
          }
        }
      }
    },
    customVideoScreenShot() {
      // 如果正在截屏，直接返回，防止重复点击
      if (this.isScreenShotting) {
        console.log(
          "⚠️ [QuillEditor-Creator] Already screenshotting, ignoring click"
        );
        return;
      }

      // 设置截屏状态
      this.isScreenShotting = true;
      // 禁用按钮并显示加载状态
      this.setScreenShotButtonEnabled(false);

      // 设置超时保护，防止截屏失败时按钮一直禁用
      const timeoutId = setTimeout(() => {
        if (this.isScreenShotting) {
          this.isScreenShotting = false;
          this.setScreenShotButtonEnabled(true);
        }
      }, 30000); // 30秒超时

      // 存储超时ID以便在成功时清除
      this.screenShotTimeoutId = timeoutId;

      //获取视频截图
      EventBus.$emit("get-screen-shot-image", this.componentId);
    },
    setReadOnlyBackgroundColor() {
      // 设置 readOnly 模式下的背景颜色
      if (this.quill && this.quill.root) {
        this.quill.root.style.backgroundColor = "#f5f5f5";
        this.quill.root.style.color = "#ccc";
      }
    },
    generateRandomId() {
      return "id-" + Math.random().toString(36).slice(2, 11) + "-" + Date.now();
    },
    getLocaleValue(key) {
      return this.t(key, this.$rootComponent.currentLanguage);
    },
    uploadAndInsertImage(file) {
      const formData = new FormData();
      formData.append("file", file);
      let qmsAxios = this.$serverHttp;
      if (qmsAxios) {
        qmsAxios
          .post("/api/storage/upload/file", formData)
          .then((response) => {
            if (response.status === 200 && response.data.data) {
              let imageUrl = response.data.data.downloadUrl;
              this.insertImageUrl(imageUrl);
            }
          })
          .catch((error) => {
            console.log("upload fail", error);
            this.$Message.error(
              this.getLocaleValue("survey_creator.common.tips.upload_fail")
            );
          });
      }
    },
  },
  data() {
    return {
      quill: null,
      componentId: null,
      isScreenShotting: false, // 标记是否正在截屏
      screenShotTimeoutId: null, // 截屏超时定时器ID
    };
  },
  watch: {
    value(newValue) {
      if (newValue !== this.quill.root.innerHTML) {
        this.quill.root.innerHTML = newValue;
        this.$nextTick(() => {
          this.quill.setSelection(newValue.length);
        });
      }
    },
    disabled(newVal) {
      // 监听 disabled 变化，动态更新 readOnly 状态和背景颜色
      if (this.quill) {
        this.quill.enable(!newVal);
        if (newVal) {
          this.setReadOnlyBackgroundColor();
        } else {
          // 恢复默认背景颜色
          if (this.quill.root) {
            this.quill.root.style.backgroundColor = "";
          }
        }
      }
    },
  },
  beforeDestroy() {
    // 清除超时定时器
    if (this.screenShotTimeoutId) {
      clearTimeout(this.screenShotTimeoutId);
    }
    // 移除事件监听器
    EventBus.$off("screen-shot-urls", this.handleScreenShotUrl);
    this.quill.root.removeEventListener("paste", this.handlePaste);
  },
});
</script>

<style src="quill/dist/quill.snow.css"></style>
<style src="quill/dist/quill.core.css"></style>
<style lang="less">
/* 预设回复标签样式 - 非 scoped，Quill 内部内容需要全局样式 */
.ql-preset-reply-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  margin: 0 2px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background: #f7f7f7;
  font-size: 13px;
  color: #515a6e;
  line-height: 1.6;
  cursor: default;
  user-select: none;
  vertical-align: baseline;

  .ql-preset-reply-text {
    margin-right: 4px;
  }

  .ql-preset-reply-delete {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    color: #999;
    cursor: pointer;
    border-radius: 50%;
    transition: all 0.2s;

    &::after {
      content: "×";
    }

    &:hover {
      color: #fff;
      background: var(--primary-brand-color, #2d8cf0);
    }
  }
}
</style>
<style scoped>
.ql-snow .ql-editor img {
  max-width: 600px;
  height: auto;
  width: 100%;
}

.ql-editor {
  box-sizing: border-box;
  counter-reset: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8
    list-9;
  line-height: 1.42;
  height: 100%;
  outline: 0;
  overflow-y: auto;
  padding: 12px 15px;
  tab-size: 4;
  -moz-tab-size: 4;
  text-align: left;
  white-space: pre-wrap;
  word-wrap: break-word;
  max-height: 500px;
}

/* readOnly 模式下的背景颜色（CSS 备选方案） */
.ql-editor[contenteditable="false"] {
  background-color: #f5f5f5;
}

/* Quill的基本样式已经包含在引入的CSS文件中，如有需要，可以在这里添加额外的样式 */
</style>
