<script setup lang="ts">
import { ref, nextTick, computed } from "vue";
import HandleComponents from "./HandleComponents.vue";
import NodeTitle from "./NodeTitle.vue";

const props = defineProps(["id", "data", "position"]);

// 编辑状态：false=展示(可拖动节点) true=编辑(可选中文字)
const isEditing = ref(false);
// 节点上的内容：独立字段 data.text（与下方编辑器的 data.panel.content 互不同步）
const displayText = ref(props.data?.text ?? props.data?.label ?? "默认显示文本");
// 编辑时的临时值
const editValue = ref("");
const textareaRef = ref<any>(null);

// 记录 textarea 被 resize 后的尺寸，展示态复用同一尺寸
// null 表示未自定义，使用默认值
const DEFAULT_W = 240;
const DEFAULT_H = 150;
const nodeWidth = ref<number | null>(null);
const nodeHeight = ref<number | null>(null);

// 通过 CSS 变量同时驱动展示态与编辑态的尺寸，
// 这样 resize 后切回展示态大小一致；再次进入编辑也保持上次尺寸
const nodeStyleVars = computed(() => ({
  "--node-w": `${nodeWidth.value ?? DEFAULT_W}px`,
  "--node-h": `${nodeHeight.value ?? DEFAULT_H}px`,
}));

// 获取 ElInput 内部的 textarea 原生元素
const getInnerEl = (): HTMLElement | null => {
  const comp: any = textareaRef.value;
  if (!comp) return null;
  // Element Plus 2.x：comp.ref 指向 textarea DOM
  const el = comp.ref ?? comp.textarea ?? comp?.$el?.querySelector?.(".el-textarea__inner");
  return (el as HTMLElement) ?? null;
};

// 退出编辑前抓取 textarea 当前外框尺寸（含 padding+border）
const captureSize = () => {
  const el = getInnerEl();
  if (el) {
    nodeWidth.value = el.offsetWidth;
    nodeHeight.value = el.offsetHeight;
  }
};

// 双击进入编辑：把当前展示文本填入 textarea 并聚焦
const startEdit = () => {
  editValue.value = displayText.value;
  isEditing.value = true;
  // 等待 DOM 更新后聚焦 textarea
  nextTick(() => {
    const el = getInnerEl();
    el?.focus?.();
    (el as HTMLTextAreaElement | null)?.select?.();
  });
};

// 失焦保存：先记录尺寸，再切回展示态；非空才更新文本，并写回节点自己的 data.text
const saveEdit = () => {
  captureSize();
  if (editValue.value.trim()) {
    displayText.value = editValue.value;
    if (props.data) props.data.text = editValue.value;
  }
  isEditing.value = false;
};

// ESC 取消编辑：同样记录尺寸，避免 resize 结果丢失
const onKeydown = (e: KeyboardEvent) => {
  if (e.key === "Escape") {
    captureSize();
    isEditing.value = false;
  }
};

// 编辑框内阻止 mousedown 冒泡，
// 避免 Vue Flow 把在 textarea 内拖动鼠标识别为节点拖拽，
// 从而保留原生「拖动选中文本」的行为
const stopDragPropagation = (e: Event) => {
  e.stopPropagation();
};

const emit = defineEmits<{
  'node-added': [nodeId: string]
}>()

// 是否有内容（有文本时不允许添加父节点）
const hasContent = computed(() => !!(props.data?.text && String(props.data.text).trim()));
</script>

<template>
  <div class="text-node" :style="nodeStyleVars">
    <NodeTitle :data="data" />
    <div class="text-row">
      <HandleComponents
        v-if="!hasContent"
        :position="position"
        :id="id"
        :data="data"
        type="target"
        handleType="text"
        @node-added="$emit('node-added', $event)"
      />

      <!-- 展示模式：失去焦点时显示文本，整体可拖动节点，尺寸跟随上次 resize -->
      <div
        v-if="!isEditing"
        class="text-display"
        @dblclick.stop="startEdit"
      >
        {{ displayText }}
      </div>

      <!-- 编辑模式：双击进入，textarea 内可拖动选中文字，不会拖动节点 -->
      <ElInput
        v-else
        ref="textareaRef"
        v-model="editValue"
        class="text-edit"
        type="textarea"
        :autosize="false"
        resize="both"
        placeholder="编辑文本"
        @blur="saveEdit"
        @keydown="onKeydown"
        @mousedown.stop="stopDragPropagation"
        @pointerdown.stop="stopDragPropagation"
      />

      <HandleComponents
        :position="position"
        :id="id"
        :data="data"
        type="source"
        handleType="text"
        @node-added="$emit('node-added', $event)"
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
.vue-flow__handle {
  background: #000;
  border: none;
  box-shadow: 0 0 0 1px #fff;
  width: 8px;
  height: 8px;
  line-height: 6px;
  font-size: 8px;
  color: #fff;
}

.text-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  --node-bg: #1f1f1f;
  --node-border: #3a3a3a;
  --node-border-hover: #555;
  --node-border-focus: #409eff;
}

.text-row {
  display: flex;
  align-items: center;
}

/* 展示态：禁用文本选中，避免拖动时误选；保留给 Vue Flow 的节点拖拽 */
.text-display {
  width: var(--node-w);
  height: var(--node-h);
  box-sizing: border-box;
  padding: 10px 12px;
  background: var(--node-bg);
  color: #e6e6e6;
  border: 1px dashed var(--node-border);
  border-radius: 6px;
  font-size: 14px;
  line-height: 1.6;
  word-break: break-word;
  white-space: pre-wrap;
  overflow: hidden;
  user-select: none;
  cursor: move;
  transition: border-color 0.2s, box-shadow 0.2s;

  &:hover {
    border-color: var(--node-border-hover);
  }
  &:empty::before {
    content: "双击编辑文本";
    color: #777;
  }
}

/* 编辑态：恢复文本可选，textarea 内可拖动选中文字 */
.text-edit {
  /* 让 ElInput 包装层不约束子元素宽高，由内层 textarea 自身控制 */
  :deep(.el-textarea) {
    width: auto;
  }
  /* 初始尺寸由 CSS 变量给到；用户拖拽 resize 后产生 inline 尺寸覆盖变量 */
  :deep(.el-textarea__inner) {
    width: var(--node-w);
    height: var(--node-h);
    min-height: var(--node-h);
    box-sizing: border-box;
    padding: 10px 12px;
    background: var(--node-bg);
    color: #e6e6e6;
    border: 1px solid var(--node-border-focus);
    border-radius: 6px;
    font-size: 14px;
    line-height: 1.6;
    user-select: text;
    cursor: text;
    resize: both;
    overflow: auto;

    &::placeholder {
      color: #777;
    }
    &:focus {
      border-color: var(--node-border-focus);
      box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.25);
    }
  }
}

input,
textarea {
  &:focus {
    outline: none;
  }
}
</style>
