<template>
    <li
        class="epic-tree-node"
        :class="{
            expanded: hasChildren,
            'level-1': props.schema.type === 'page'
        }"
    >
        <a>
            <span
                v-if="hasChildren && props.schema.type !== 'page'"
                class="icon-expanded"
                :class="{ expanded }"
                @click="handleExpanded"
            >
                <EIcon name="icon-youjiantou" />
            </span>
            <TreeNodeText />
        </a>
        <!-- 关键修改：绑定内部响应式数据 innerChildren，而非直接绑定 props.schema.children -->
        <ETreeNodes
            v-if="hasChildren"
            class="epic-tree-sublist"
            :class="{ expanded }"
            v-model:schemas="innerChildren"
            :parentSchema="props.schema"
            @update:schemas="handleChildrenUpdate"
        />
    </li>
</template>
<script lang="ts" setup>
import { ComponentSchema } from "../../../types/epic-designer";
import EIcon from "../../icon";
import { inject, computed, ref, Ref, h, defineComponent, Slots, watch } from "vue";
import { pluginManager } from "@/components/EpicDesigner/utils";
import ETreeNodes from "./treeNodes.vue";

defineOptions({
    name: "ETreeNodeItem"
});

const props = defineProps<{
    schema: ComponentSchema;
}>();

// 关键步骤1：创建内部响应式数据，复制 props.schema.children 的初始值
// 避免直接操作 props 的嵌套属性，通过内部数据做中间层
const innerChildren = ref<ComponentSchema[]>(props.schema.children || []);

// 关键步骤2：监听 props.schema.children 的变化，同步到内部响应式数据
// 确保父组件更新 children 时，子组件能同步更新（遵循单向数据流）
watch(
    () => props.schema.children,
    newChildren => {
        innerChildren.value = newChildren || [];
    },
    { deep: true, immediate: true }
);

// 计算属性：判断是否有子节点（基于内部响应式数据，而非直接读 props）
const hasChildren = computed(() => {
    return innerChildren.value.length > 0;
});

// 注入上层依赖（保持不变）
const slots = inject("slots", {}) as Slots;
const expandedKeys = inject("expandedKeys") as Ref<string[]>;
const treeProps = inject("treeProps") as any;
const selectedKeys = inject("selectedKeys") as Ref<string[]>;
const handleSelect = inject("handleSelect") as (id: string, componentSchema: ComponentSchema) => void;

// 计算属性：判断当前节点是否展开（保持不变）
const expanded = computed(() => {
    return expandedKeys.value.includes(props.schema.id ?? "");
});

// 节点文本组件（保持不变，仅读取 props.schema，无修改）
const TreeNodeText = defineComponent({
    setup() {
        const getComponentLabel = () => {
            return (
                props.schema.label ||
                pluginManager.getComponentConfingByType(props.schema.type)?.defaultSchema.label ||
                "未命名组件"
            );
        };

        return () =>
            h(
                "span",
                {
                    class: {
                        text: true,
                        hover: treeProps.hoverKey === props.schema.id,
                        checked: selectedKeys.value.includes(props.schema.id!)
                    },
                    onClick: () => {
                        if (props.schema.id) {
                            // 传递 schema 副本，避免父组件可能的意外修改
                            handleSelect(props.schema.id, { ...props.schema });
                        }
                    }
                },
                slots["tree-node"]?.(props) ??
                    h(
                        "span",
                        { class: "epic-text-padding" },
                        {
                            default: () => [getComponentLabel(), h("span", { class: "epic-node-type-text" }, props.schema.type)]
                        }
                    )
            );
    }
});

// 展开/折叠节点（保持不变，仅修改注入的 expandedKeys，不碰 props）
function handleExpanded() {
    const id = props.schema.id;
    if (!id) return;

    expandedKeys.value = expandedKeys.value.includes(id)
        ? expandedKeys.value.filter(item => item !== id)
        : [...expandedKeys.value, id];
}

// 关键步骤3：子节点更新时，通过父组件暴露的方法同步（而非直接修改 props）
// 需在父组件中处理 children 的更新逻辑，子组件仅触发事件
function handleChildrenUpdate(newChildren: ComponentSchema[]) {
    // 触发自定义事件，通知父组件更新 children
    // 父组件需通过 @update:children 接收并更新自身的 schema.children
    emit("update:children", newChildren);
}

// 初始化展开节点（保持不变，仅修改注入的 expandedKeys，不碰 props）
function init() {
    const id = props.schema.id;
    if (!id || !hasChildren.value) return;

    if (!expandedKeys.value.includes(id)) {
        expandedKeys.value = [...expandedKeys.value, id];
    }
}

// 注册自定义事件，用于通知父组件更新 children
const emit = defineEmits<{
    (e: "update:children", newChildren: ComponentSchema[]): void;
}>();

init();
</script>
