<template>
  <div class="formula-container">
    <el-row class="formula-editor">
      <!-- 左侧编辑面板 -->
      <el-col :xs="24" :span="16" class="left-panel">
        <div class="editor-area">
          <div class="operator-toolbar">
            <el-button
              v-for="op in operatorMap"
              :key="op.value"
              v-wave
              class="operator-btn"
              :title="op.name"
              @click="() => insertOperator(op.value)"
            >
              <span class="symbol">{{ op.symbol }}</span>
            </el-button>

            <el-dropdown @command="insertFunction" trigger="click">
              <el-button type="primary" class="func-btn">
                <span>函数列表</span>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu class="func-menu">
                  <el-dropdown-item v-for="func in functions" :key="func" :command="func" class="func-item">
                    <span class="func-name">{{ func }}</span>
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>

          <el-input
            ref="editorRef"
            v-model="formulaValue"
            type="textarea"
            :rows="8"
            placeholder="请输入公式，例如：SUM(【基础工资】*1.2 + 【绩效奖金】)"
            resize="none"
            class="editor-input"
            spellcheck="false"
          />
        </div>
      </el-col>

      <!-- 右侧参数面板 -->
      <el-col :xs="24" :span="8" class="right-panel">
        <div class="param-tree">
          <el-input
            v-model="filterText"
            size="default"
            placeholder="搜索参数..."
            clearable
            class="search-box"
            @input="onFilterInput"
            @keyup.enter="onFilterEnter"
            @clear="onFilterClear"
          />

          <div class="tree-container">
            <el-tree-v2
              ref="treeRef"
              :data="treeData"
              :props="defaultProps"
              :filter-node-method="filterNode"
              @node-click="handleNodeClick"
              node-key="text"
              :height="treeHeight"
            />
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch, nextTick, computed, onMounted, onUnmounted } from "vue";
import { ElMessage, ElTree } from "element-plus";
import { debounce } from "lodash-es";
import { pinyin } from "pinyin-pro";
import { FormulaCheck } from "@/api/modules/basicinfo";

/**
 *
 */
interface TreeNode {
  text: string;
  value?: number | string | null;
  children?: TreeNode[];
}

interface Props {
  modelValue: string;
  treeData: TreeNode[];
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: "",
  treeData: () => []
});

const emits = defineEmits<{
  "update:modelValue": [v: string];
}>();

// 引用与状态
const editorRef = ref<any | null>(null);
const treeRef = ref<InstanceType<typeof ElTree> | null>(null);
const formulaValue = ref<string>(props.modelValue);
const filterText = ref<string>("");
const treeHeight = ref<number>(200); // 默认高度

// 监听v-model同步
watch(formulaValue, val => {
  emits("update:modelValue", val);
});

/**
 * 左边区域
 */
const operatorMap = ref([
  { value: "+", symbol: "+", name: "加" },
  { value: "-", symbol: "-", name: "减" },
  { value: "*", symbol: "×", name: "乘" },
  { value: "/", symbol: "÷", name: "除" },
  { value: "(", symbol: "(", name: "左括号" },
  { value: ")", symbol: ")", name: "右括号" },
  { value: "**", symbol: "^", name: "幂" },
  { value: "%", symbol: "%", name: "模" }
]);
const functions = ["SUM", "AVG", "IF", "MAX", "MIN"];

// 插入运算符
const insertOperator = (op: string) => handleInsertFormula(op);
// 插入函数（光标定位到括号内）
const insertFunction = (func: string) => handleInsertFormula(`${func}()`, { cursorOffset: -1 });

// 重置公式
const reset = () => {
  formulaValue.value = "";
};

// 校验公式
const handleCheck = async (): Promise<boolean> => {
  if (!formulaValue.value?.trim()) {
    // ElMessage.warning("请先输入公式");
    return true;
  }

  try {
    const result = await FormulaCheck({
      formula: formulaValue.value
    });

    if (result) {
      ElMessage.success("公式检查通过");
      return true;
    }
    return false;
  } catch (error) {
    return false;
  }
};

/**
 * 右边区域
 */
const defaultProps = {
  value: "value",
  label: "text",
  children: "children"
};

// 搜索优化：扁平索引 + 拼音缓存
const pinyinCache = new Map<string, string>();
// 构建扁平索引（提升搜索性能）
const buildIndex = (list: TreeNode[], parentPath: string[] = []) => {
  const result: { node: TreeNode; path: string[] }[] = [];
  for (const n of list) {
    const currentPath = parentPath.concat(n.text);
    result.push({ node: n, path: currentPath });
    if (n.children && n.children.length) {
      result.push(...buildIndex(n.children, currentPath));
    }
  }
  return result;
};

// 节点过滤方法（使用缓存提升性能）
const filterNode = (value: string, data: TreeNode, node: any): boolean => {
  // 空搜索：保留有效节点（有值或有子节点）
  if (!value) {
    const selfValid = !!data.value || !!(data.children && data.children.length);
    return selfValid;
  }

  const q = value.trim().toLowerCase();

  // 文本与拼音匹配检查
  const text = data.text || "";
  const cachedPinyin = pinyinCache.get(text) ?? pinyin(text, { toneType: "none", type: "array" }).join("").toLowerCase();
  if (!pinyinCache.has(text)) pinyinCache.set(text, cachedPinyin);

  const selfMatch = (text && text.toLowerCase().includes(q)) || (cachedPinyin && cachedPinyin.includes(q));

  // 子节点匹配检查
  if (selfMatch) return true;
  if (data.children && data.children.length) {
    return data.children.some(child => filterNode(value, child, node));
  }

  return false;
};

// 防抖处理搜索输入
const doFilter = debounce((val: string) => {
  treeRef.value?.filter?.(val ?? "");
}, 200);

const onFilterInput = (val: string) => {
  doFilter(val);
};
const onFilterEnter = () => {
  treeRef.value?.filter?.(filterText.value ?? "");
};
const onFilterClear = () => {
  filterText.value = "";
  treeRef.value?.filter?.("");
};

// 插入公式辅助方法（精确控制光标位置）
const getTextarea = (): HTMLTextAreaElement | null => {
  const el = (editorRef.value as any)?.$el ?? null;
  if (!el) return null;
  return el.querySelector("textarea");
};

const handleInsertFormula = async (insertText: string, options?: { cursorOffset?: number }) => {
  if (!insertText) return;
  await nextTick();
  const textarea = getTextarea();
  if (!textarea) {
    // 降级处理：直接拼接到末尾
    formulaValue.value = formulaValue.value + insertText;
    return;
  }
  const start = textarea.selectionStart ?? textarea.value.length;
  const end = textarea.selectionEnd ?? textarea.value.length;

  // 插入文本
  formulaValue.value = formulaValue.value.slice(0, start) + insertText + formulaValue.value.slice(end);

  await nextTick();
  // 调整光标位置
  const offset = options?.cursorOffset ?? 0;
  const newPos = start + insertText.length + offset;
  try {
    textarea.setSelectionRange(newPos, newPos);
    textarea.focus();
  } catch (err) {
    textarea.focus();
  }
};

// 点击树节点插入参数
const handleNodeClick = (data: TreeNode) => {
  if (data.children?.length < 100) return;
  handleInsertFormula(`【${data.text}】`);
};

// 动态计算树高度
const calculateTreeHeight = () => {
  nextTick(() => {
    const treeContainer = document.querySelector(".tree-container") as HTMLElement;
    if (treeContainer) {
      // 获取tree-container的实际高度，减去可能的padding/margin
      const containerHeight = treeContainer.clientHeight;
      // 设置一个最小高度，确保树至少有200px高
      treeHeight.value = Math.max(containerHeight, 200);
    }
  });
};

// 监听窗口大小变化
const handleResize = () => {
  calculateTreeHeight();
};

onMounted(() => {
  calculateTreeHeight();
  window.addEventListener("resize", handleResize);
});

onUnmounted(() => {
  window.removeEventListener("resize", handleResize);
});

// 暴露方法给父组件
defineExpose({
  reset,
  check: handleCheck
});
</script>

<style scoped lang="scss">
.formula-container {
  height: 100%;
  width: 100%;
  --editor-border: #dcdfe6;
  --panel-bg: #f8f9fa;

  .formula-editor {
    height: calc(100% - 20px);
    margin-top: 12px;
    display: flex;

    .left-panel {
      width: 100%;
      height: 100%;

      .editor-area {
        display: flex;
        flex-direction: column;
        padding: 8px;
      }

      .operator-toolbar {
        gap: 12px;
        display: flex;
        flex-wrap: wrap;
        padding-bottom: 12px;
      }

      .operator-btn {
        min-width: 36px;
        padding: 8px 12px;
      }

      .editor-input {
        border-radius: 4px;
        transition: border-color 0.2s;

        &:focus-within {
          border-color: #4096ff;
          box-shadow: 0 0 0 2px rgba(64, 150, 255, 0.2);
        }
      }
    }

    .right-panel {
      width: 100%;
      height: 100%;

      .param-tree {
        padding: 8px;
        display: flex;
        flex-direction: column;
        height: 100%;

        .search-box {
          flex-shrink: 0;
          margin-bottom: 8px;
          border-radius: 4px;
        }

        .tree-container {
          flex: 1;
          min-height: 0;
          /* 允许垂直滚动，禁止水平滚动 */
          overflow-y: auto;
          overflow-x: hidden;
          /* 添加边框样式 */
          border: 1px solid var(--editor-border);
          border-radius: 4px;

          /* 优化滚动条样式 */
          &::-webkit-scrollbar {
            width: 6px;
          }
          &::-webkit-scrollbar-thumb {
            background-color: #ddd;
            border-radius: 3px;
          }
          &::-webkit-scrollbar-track {
            background-color: #f5f5f5;
          }

          .el-tree {
            padding: 0 12px;
            height: 100%;

            :deep(.el-tree-node__content) {
              padding: 6px 0;
              cursor: pointer;
              &:hover {
                background-color: #f5f7fa;
              }
            }
          }
        }
      }
    }
  }
}
</style>
