import SysRoleController from '@/services/apis/SysRoleController';
import { RoleType } from '@/services/enums';
import { PushpinFilled } from '@ant-design/icons';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import type { TreeDataNode } from 'antd';
import { Tree } from 'antd';
import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react';

export interface RoleTreeHandles {
    reload: () => void;
}

/** 角色树属性 */
type RoleTreeProps = {
    roleGroupList: API.SysRoleGroupOutput[],
    onRoleGroupSelect: (roleGroup: API.SysRoleGroupOutput | undefined) => void;
    onRoleSelect: (role: API.SysRoleOutput | undefined) => void;
};

/** 角色树 */
const RoleTree = forwardRef<RoleTreeHandles, RoleTreeProps>(({ roleGroupList, onRoleSelect, onRoleGroupSelect }, ref) => {
    const [expandedKeys, setExpandedKeys] = useState<number[]>([0, 1]);
    const [selectedKeys, setSelectedKeys] = useState<number[]>([1]);

    const [roleTreeData, setRoleTreeData] = useState<TreeDataNode[]>([]);
    const [roleList, setRoleList] = useState<API.SysRoleOutput[]>([]);

    const treeClassName = useEmotionCss(({ token }) => {
        return {
            '.ant-tree-treenode': {
                marginBottom: 4,
                padding: '2px 0 6px 0',
                '::before': {
                    borderRadius: token.borderRadius,
                },

                '.icon-fixed': {
                    float: 'right',
                    marginTop: 4,
                    opacity: 0.2,
                },
                '.icon-ding': {
                    float: 'right',
                    marginTop: 4,
                    opacity: 0.4,
                    color: '#1677ff',
                }
            },
        };
    });

    // 加载数据
    const loadData = useCallback(async () => {
        const rlist = await SysRoleController.getAllList();
        setRoleList(rlist ?? []);
    }, []);

    // 构建角色树
    const buildTreeData = useCallback(
        (roleGroups: API.SysRoleGroupOutput[], roles: API.SysRoleOutput[]) => {
            const treeData: TreeDataNode[] = [];
            roleGroups.forEach((roleGroup) => {
                const node: TreeDataNode = {
                    key: `rg-${roleGroup?.id}`,
                    title: (
                        <div style={{ width: '100%' }}>
                            {roleGroup?.name}
                            {roleGroup?.id === 1 && <PushpinFilled className="icon-fixed" />}
                        </div>
                    ),
                    selectable: true,
                    children: [],
                };
                const rgRoles = roles.filter(t => t.sysRoleGroupId === roleGroup?.id);
                rgRoles.forEach((role) => {
                    node.children?.push({
                        key: `r-${role.id}`,
                        title: (
                            <div style={{ width: '100%' }}>
                                {role.name}
                                {role.roleType > RoleType.NORMAL && <PushpinFilled className="icon-fixed" />}
                            </div>
                        ),
                        selectable: true,
                        isLeaf: true,
                    });
                });
                treeData.push(node);
            });
            return treeData;
        },
        [loadData],
    );

    useEffect(() => {
        loadData();
    }, [loadData]);
    useEffect(() => {
        setRoleTreeData(buildTreeData(roleGroupList, roleList));
    }, [buildTreeData, roleList, roleGroupList]);

    useImperativeHandle(ref, () => ({
        reload: () => loadData(),
    }));

    const handleSelect = (sks: any[]) => {
        const sk = sks[0].split('-');
        if (sk[0] === 'r') {
            const roleId = parseInt(sk[1]);
            setSelectedKeys(sks);
            const role = roleList.find((t: any) => t.id === roleId);
            onRoleSelect(role);
        }
        else if (sk[0] === 'rg') {
            const roleGroupId = parseInt(sk[1]);
            setSelectedKeys(sks);
            const roleGroup = roleGroupList.find((t: any) => t.id === roleGroupId);
            onRoleGroupSelect(roleGroup);
        }
    };

    return (
        <>
            <Tree.DirectoryTree
                className={treeClassName}
                showIcon={false}
                icon={null}
                expandedKeys={expandedKeys}
                selectedKeys={selectedKeys}
                onExpand={(eks) => setExpandedKeys(eks as number[])}
                treeData={roleTreeData}
                onSelect={handleSelect}
            />
        </>
    );
});

export default RoleTree;
