<template>
  <div :class="className" class="screen">
    <div class="flex contenteditable align-center space-between">
      <p
        :id="'editor' + id"
        ref="editor"
        :contenteditable="active"
        class="van-field contenteditable-content"
        :data-placeholder="placeholder"
        @focus="onFocus"
        @input="onChange($event.target, $event)"
        v-html="modelValue"
      ></p>
      <!--    <p-->
      <!--      v-else-->
      <!--      ref="editor"-->
      <!--      class="van-field contenteditable-content"-->
      <!--      v-html="modelValue"-->
      <!--      :placeholder="placeholder"-->
      <!--    ></p>-->
      <div class="right-icon ml10">
        <slot name="right-icon"></slot>
      </div>
    </div>
    <teleport to="body">
      <div v-if="showAction && active" ref="editorAction" class="editor-action">
        <button v-for="item in actions" :key="item.name" @click="funEvent(item, $event)">
          <van-icon class-prefix="mobilefont" :name="item.icon"></van-icon>
        </button>
      </div>
    </teleport>

    <div class="error-message">
      {{ errorMessage }}
      <!--      <slot name="error"></slot>-->
    </div>
  </div>
</template>

<script setup>
import { defineEmits, ref, onMounted, watch, onBeforeUnmount } from 'vue';
import { v4 as uuidv4 } from 'uuid';
import CommonApi from '@/api/common.js';

defineProps({
  className: {
    type: String,
    default: ''
  },
  placeholder: {
    type: String,
    default: '请输入'
  }
});
const modelValue = defineModel('modelValue', {
  type: String,
  default: ''
});

const errorMessage = defineModel('errorMessage', {
  type: String,
  default: ''
});
const active = defineModel('active', {
  type: Boolean,
  default: false
});

const id = ref(uuidv4());

const editor = ref(null);
const editorAction = ref(null);
const emit = defineEmits(['update:modelValue', 'blur', 'change']);
const save = (e) => {
  emit('update:modelValue', e.innerHTML);
  emit('blur', e.innerHTML);
};
const savedRange = ref(null);
const functions = {
  boldModern: () => {
    document.execCommand('bold', true, null);
  },
  underLine: () => {
    document.execCommand('underline', false, null);
  },
  italic: () => {
    document.execCommand('italic', false, null);
  },

  uploadImage: async () => {
    // 保存当前光标位置
    savedRange.value = saveSelection();

    const fileInput = document.createElement('input');
    fileInput.type = 'file';

    fileInput.click();

    fileInput.onchange = async (e) => {
      const [file] = e.target.files;
      if (!file) return;
      if (file.size > 2 * 1024 * 1024) {
        // console.error('文件大小不能超过2M');
        return;
      }

      const data = await CommonApi.cosUpload(file);
      const img = document.createElement('img');
      img.src = data.url;
      img.onload = () => {
        // const scale = img.naturalHeight / 50;
        // const width = (img.naturalWidth / scale).toFixed(0);
        // const height = 50;
        // const maxWidth = img.naturalWidth;
        // const maxHeight = img.naturalHeight;
        // eslint-disable-next-line standard/no-callback-literal
        // const style = `style="width:${width}px;
        // height:${height}px;
        // max-width:${maxWidth}px;
        // max-height:${maxHeight}px"`;
        // 使用原始高度
        const minimum = 50;
        let height = img.naturalHeight;
        const scale = img.naturalHeight / 50;
        if (height > minimum * 3) {
          height = height / scale;
        } else {
          height = minimum;
        }
        // 根据宽高比计算宽度
        const width = (height * 3) / 4;
        const maxWidth = img.naturalWidth;
        const maxHeight = img.naturalHeight;
        // eslint-disable-next-line standard/no-callback-literal
        const style = `style="width:${width}px;
        height:${height}px;
        max-width:${maxWidth}px;
        max-height:${maxHeight}px"`;
        // eslint-disable-next-line standard/no-callback-literal
        insertImageAtCaret(`<img src=${data.url} ${style}/>`);

        // 恢复光标位置
        restoreSelection(savedRange.value);
      };
    };
  }
};

const funEvent = (item) => {
  functions[item.fun]();
};

watch(
  () => active.value,
  (newVal) => {
    if (!newVal) {
      save(editor.value);
      setTimeout(() => {
        showAction.value = false;
      }, 100);
    }
  },
  {
    deep: true
  }
);

watch(
  () => modelValue.value,
  (newVal) => {
    if (newVal) {
      setTimeout(() => {
        onChange(editor.value);
      });
    }
  }
);

const isEmptyContent = (html) => {
  // 移除所有空白字符
  const trimmedHtml = html.trim();
  // 检查是否为空字符串、仅包含 <br> 或仅包含 <p><br></p>
  return (
    trimmedHtml === '' ||
    trimmedHtml === '<br>' ||
    trimmedHtml === '<p><br></p>' ||
    trimmedHtml === '<p></p>'
  );
};

const onChange = (target) => {
  if (isEmptyContent(target.innerHTML)) {
    editor.value.classList.add('editor-placeholder');
    // 删除br
    editor.value.innerHTML = editor.value.innerHTML.replace(/<br>/g, '');
  } else {
    editor.value.classList.remove('editor-placeholder');
  }
};
const showAction = ref(false);
const actions = [
  {
    label: '加粗',
    fun: 'boldModern',
    icon: 'jiacu'
  },
  {
    label: '下划线',
    fun: 'underLine',
    icon: 'xiahuaxian'
  },
  {
    label: '图片上传',
    fun: 'uploadImage',
    icon: 'tupian'
  },
  {
    label: '倾斜',
    fun: 'italic',
    icon: 'qingxie'
  }
];
const checkContains = (element, target) => {
  try {
    return element?.contains(target) ?? false;
  } catch (e) {
    return false;
  }
};

const isIOS = ref(/iPad|iPhone|iPod/.test(navigator.userAgent));
const keyboardVisible = ref(false);

// Handle iOS keyboard events
const handleVisualViewportResize = () => {
  if (!isIOS.value) return;

  const viewport = window.visualViewport;
  if (!viewport) return;

  // If the viewport height is significantly reduced, the keyboard is likely visible
  const keyboardShown = viewport.height < window.innerHeight * 0.8;
  keyboardVisible.value = keyboardShown;

  if (keyboardShown && editorAction.value) {
    // Position the editor action bar above the keyboard
    editorAction.value.style.bottom = `${window.innerHeight - viewport.height}px`;
  } else if (editorAction.value) {
    // Reset position when keyboard is hidden
    editorAction.value.style.bottom = 'env(safe-area-inset-bottom, 0)';
  }
};

onMounted(() => {
  onChange(editor.value);
  editor.value.addEventListener('focus', () => {
    showAction.value = true;

    // iOS specific handling for keyboard
    if (isIOS.value) {
      // Add a small delay to ensure the keyboard is fully shown
      setTimeout(() => {
        if (editorAction.value) {
          // On iOS, adjust position when keyboard appears
          window.scrollTo(0, 0);
          document.body.scrollTop = 0;
        }
      }, 300);
    }
  });

  document.addEventListener('click', (e) => {
    if (!editor.value || !editorAction.value) return;

    const target = e.composedPath?.()?.[0] || e.target;
    const isEditor = checkContains(editor.value, target);
    const isActionBar = checkContains(editorAction.value, target);

    if (!isEditor && !isActionBar) {
      showAction.value = false;
      save(editor.value);
      // emit('blur', editor.value);
    }
  });

  document.addEventListener('resize', () => {
    showAction.value = false;
  });

  // Set up visual viewport event listener for iOS
  if (window.visualViewport) {
    window.visualViewport.addEventListener('resize', handleVisualViewportResize);
  }
});

onBeforeUnmount(() => {
  // Clean up event listeners
  if (window.visualViewport) {
    window.visualViewport.removeEventListener('resize', handleVisualViewportResize);
  }
});

const onFocus = (e) => {
  // 阻止
  e.preventDefault();
  e.stopPropagation();
  // console.log('Editor focused');
};

// 保存当前光标位置
const saveSelection = () => {
  const selection = window.getSelection();
  if (selection.rangeCount === 0) return null;

  return selection.getRangeAt(0);
};

// 恢复光标位置
const restoreSelection = (range) => {
  if (!range) return;

  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
};

// 在光标位置插入图片
const insertImageAtCaret = (html) => {
  const selection = window.getSelection();
  if (selection.rangeCount === 0) return;

  const range = selection.getRangeAt(0);
  range.deleteContents();

  const div = document.createElement('div');
  div.innerHTML = html;
  const frag = document.createDocumentFragment();
  for (let child = div.firstChild; child; child = div.firstChild) {
    frag.appendChild(child);
  }

  range.insertNode(frag);
  range.setStartAfter(frag);
  range.collapse(true);

  selection.removeAllRanges();
  selection.addRange(range);
};
</script>

<style>
.screen {
  width: 100%;
}
.contenteditable-content {
  width: 100%;
  height: 100%;
  img {
    vertical-align: text-top;
  }
  & p {
    display: block;
    vertical-align: top;
  }
}
</style>
<style scoped lang="scss">
.contenteditable-content {
  width: 100%;
  height: 100%;
  min-height: 25px;
  & p {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
  }
}

.right-icon {
  color: #c4c9d4;
}
.error-message {
  color: red;
  flex: none;
  font-size: 12px;
}
.editor-action {
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 2008;
  display: flex;
  width: 100%;
  height: 40px;
  padding: 0 10px;
  background: #fff;
  line-height: 40px;
  /* iOS specific fixes */
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
  /* Ensure it works with iOS keyboard */
  bottom: env(safe-area-inset-bottom, 0);
  /* Add box shadow for better visibility */
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);

  & button {
    border: none;
    background: #fff;
    color: #000;
    outline: none;
    /* Improve touch target size for iOS */
    min-width: 44px;
    min-height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  button + button {
    margin-left: 10px;
  }
}
</style>
