import { IBimComponent } from '../../types/component';
import { ThemeConfig } from '../../themes/types';
import { localeManager } from '../../services/locale';
import { themeManager } from '../../services/theme';
import { TreeOptions, TreeNodeConfig, TreeNodeCheckState } from './types';
import { BimTreeNode } from './tree-node';
import './index.css';

// 定义辅助事件发射器接口 (由于 BimTree 通常作为 Manager 的一部分或独立使用)
// 为了方便，这里我们假设它会被 TreeManager 管理，TreeManager 会处理事件发射
// 但 BimTree 本身也需要一个方式通知 Manager。
// 我们可以通过构造函数传入 event bus 适配器，或者直接使用 CustomEvent。
// 更好的方式：BimTree 提供 onEvent 回调。

export class BimTree implements IBimComponent {
    public element: HTMLElement;
    private options: TreeOptions;
    private nodeMap: Map<string, BimTreeNode> = new Map();
    private rootNodes: BimTreeNode[] = [];
    
    // 订阅清理函数
    private unsubscribeLocale: (() => void) | null = null;
    private unsubscribeTheme: (() => void) | null = null;
    
    // 事���回调 (由 Manager 注入)
    public onNodeCheck?: (node: BimTreeNode) => void;
    public onNodeSelect?: (node: BimTreeNode) => void;
    public onNodeExpand?: (node: BimTreeNode) => void;

    constructor(options: TreeOptions) {
        this.options = {
            checkable: true,
            checkStrictly: true,
            indent: 24,
            defaultExpandAll: false,
            ...options
        };
        this.element = document.createElement('div');
        this.element.className = 'bim-tree';
    }

    public init(): void {
        this.render();

        // 订阅系统事件
        this.unsubscribeLocale = localeManager.subscribe(() => this.setLocales());
        this.unsubscribeTheme = themeManager.subscribe((theme) => this.setTheme(theme));
    }

    /**
     * 设置主题
     */
    public setTheme(theme: ThemeConfig): void {
        const style = this.element.style;
        style.setProperty('--bim-ui_bg_color', theme.panelBackground);
        style.setProperty('--bim-ui_text_primary', theme.textPrimary);
        style.setProperty('--bim-ui_text_secondary', theme.textSecondary || '#999');
        style.setProperty('--bim-ui_border_color', theme.border);
        style.setProperty('--bim-ui_bg_hover', theme.componentHover);
        style.setProperty('--bim-primary_color', theme.primary);
        // style.setProperty('--bim-ui_text_disabled', theme.textDisabled); // 如果 ThemeConfig 有这个字段
    }

    /**
     * 响应语言变更
     */
    public setLocales(): void {
        this.nodeMap.forEach(node => node.updateLabel());
    }

    public destroy(): void {
        if (this.unsubscribeLocale) {
            this.unsubscribeLocale();
            this.unsubscribeLocale = null;
        }
        if (this.unsubscribeTheme) {
            this.unsubscribeTheme();
            this.unsubscribeTheme = null;
        }
        this.rootNodes.forEach(node => node.destroy());
        this.rootNodes = [];
        this.nodeMap.clear();
        this.element.remove();
    }
    
    /**
     * 核心渲染逻辑
     */
    private render(): void {
        this.element.innerHTML = '';
        this.nodeMap.clear();
        this.rootNodes = [];

        this.options.data.forEach(config => {
            this.createNodeRecursively(config, null);
        });
        
        // 如果设置了 defaultExpandAll，展开所有
        if (this.options.defaultExpandAll) {
            this.expandAll(true);
        }
    }

    /**
     * 递归创建节点
     */
    private createNodeRecursively(config: TreeNodeConfig, parent: BimTreeNode | null) {
        const node = new BimTreeNode(config, this.options, {
            onExpand: (n) => { if (this.onNodeExpand) this.onNodeExpand(n); },
            onCheck: (n) => this.handleNodeCheck(n),
            onClick: (n) => { if (this.onNodeSelect) this.onNodeSelect(n); }
        });

        this.nodeMap.set(config.id, node);

        if (parent) {
            parent.appendChild(node);
        } else {
            this.rootNodes.push(node);
            this.element.appendChild(node.element);
        }

        if (config.children && config.children.length > 0) {
            config.children.forEach(childConfig => {
                this.createNodeRecursively(childConfig, node);
            });
        }
        
        // 如果是初始化渲染，需要处理 checkStrictly 的向上联动（因为数据里可能只给了子节点 checked，父节点没给）
        // 这里做一个简单的后处理：如果 checkStrictly 开启，且当前节点 checked，则触发一次联动
        // 注意：这可能会导致性能问题，优化做法是在所有节点创建完后统一计算一次状态
    }

    /**
     * 处理节点勾选逻辑 (核心算法)
     */
    private handleNodeCheck(node: BimTreeNode) {
        const isChecked = node.checkState === TreeNodeCheckState.Checked;

        // 1. 触发外部回调 (Event)
        if (this.onNodeCheck) this.onNodeCheck(node);

        // 2. 如果不联动，直接返回
        if (this.options.checkStrictly === false) return;

        // 3. 联动逻辑
        // 3.1 向下级联 (Cascade Down): 父变子全变
        const updateChildren = (n: BimTreeNode, state: TreeNodeCheckState) => {
            n.children.forEach(child => {
                if (child.config.disabled) return; // 跳过禁用节点
                child.setChecked(state, false); // 不再触发事件，只更新状态 UI
                updateChildren(child, state);
            });
        };
        
        // 当前节点是 Checked 或 Unchecked，子节点跟随
        if (isChecked) {
            updateChildren(node, TreeNodeCheckState.Checked);
        } else {
            updateChildren(node, TreeNodeCheckState.Unchecked);
        }

        // 3.2 向上冒泡 (Bubble Up): 子变父更新
        let current = node.parent;
        while (current) {
            if (current.config.disabled) {
                current = current.parent;
                continue;
            }

            const children = current.children;
            const allChecked = children.every(c => c.checkState === TreeNodeCheckState.Checked);
            const allUnchecked = children.every(c => c.checkState === TreeNodeCheckState.Unchecked);

            if (allChecked) {
                current.setChecked(TreeNodeCheckState.Checked, false);
            } else if (allUnchecked) {
                current.setChecked(TreeNodeCheckState.Unchecked, false);
            } else {
                current.setChecked(TreeNodeCheckState.Indeterminate, false);
            }
            
            current = current.parent;
        }
    }

    // ================== Public APIs ==================

    public getNode(id: string): BimTreeNode | undefined {
        return this.nodeMap.get(id);
    }

    public checkNode(id: string, checked: boolean) {
        const node = this.nodeMap.get(id);
        if (node) {
            node.setChecked(checked ? TreeNodeCheckState.Checked : TreeNodeCheckState.Unchecked, true);
            // 手动调用联动处理，因为 setChecked 的 fireEvent 只触发回调，不包含内部逻辑调用?
            // 不，我们在 createNodeRecursively 里绑定的 onCheck 就是 handleNodeCheck
            // 所以只要 fireEvent=true，就会触发 handleNodeCheck，进而触发联动。
        }
    }

    public expandAll(expanded: boolean) {
        this.nodeMap.forEach(node => node.toggleExpand(expanded));
    }

    public getCheckedNodes(includeHalfChecked: boolean = false): TreeNodeConfig[] {
        const result: TreeNodeConfig[] = [];
        this.nodeMap.forEach(node => {
            if (node.checkState === TreeNodeCheckState.Checked) {
                result.push(node.config);
            } else if (includeHalfChecked && node.checkState === TreeNodeCheckState.Indeterminate) {
                result.push(node.config);
            }
        });
        return result;
    }
}
