import { PERMISSIONS } from '@/common/constant';
import SysMenuController from '@/services/apis/SysMenuController';
import SysRoleController from '@/services/apis/SysRoleController';
import SysRoleGroupController from '@/services/apis/SysRoleGroupController';
import SysRoleMenuController from '@/services/apis/SysRoleMenuController';
import { SaveOutlined, UserAddOutlined, UserDeleteOutlined } from '@ant-design/icons';
import { PageContainer, ProCard, ProDescriptions } from '@ant-design/pro-components';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import { App, Button, Divider, Space, theme } from 'antd';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Access, useAccess } from 'umi';
import type { RoleMenuActionItem } from '../utils';
import { buildMenuActionTree } from '../utils';
import AuthList, { AuthListHandles } from './components/AuthList';
import RoleEditModal from './components/RoleEditModal';
import RoleGroupEditModal from './components/RoleGroupEditModal';
import type { RoleTreeHandles } from './components/RoleTree';
import RoleTree from './components/RoleTree';
import RoleUserAddModal from './components/RoleUserAddModal';
import UserList, { UserListHandles } from './components/UserList';


const TAB_AUTH = 'auth';
const TAB_USER = 'user';

export type MenuDataType = {
    menuList: API.SysMenuOutput[];
    menuTreeNodes: RoleMenuActionItem[];
};

/** 角色权限 */
const Role: React.FC = () => {
    const [addRoleUserVisible, setAddRoleUserVisible] = useState<boolean>(false);
    const roleTreeRef = useRef<RoleTreeHandles>(null);
    const authListRef = useRef<AuthListHandles>(null);
    const userListRef = useRef<UserListHandles>(null);
    const editRef = useRef<boolean>(false);

    const [loading, setLoading] = useState<boolean>(true);
    const [roleTabKey, setRoleTabKey] = useState<string>(TAB_AUTH);
    const [roleGroup, setRoleGroup] = useState<API.SysRoleGroupOutput | undefined>(undefined);
    const [role, setRole] = useState<API.SysRoleOutput | undefined>(undefined);
    const [roleGroupList, setRoleGroupList] = useState<API.SysRoleGroupOutput[]>([]);

    const [roleEditVisible, setRoleEditVisible] = useState<boolean>(false);
    const [roleGroupEditVisible, setRoleGroupEditVisible] = useState<boolean>(false);

    const [menuData, setMenuData] = useState<MenuDataType>({ menuList: [], menuTreeNodes: [] });

    const { message, modal } = App.useApp();

    const { hasPermission } = useAccess();
    const { token } = theme.useToken();

    const tabButtonClassName = useEmotionCss(({ token }) => {
        return {
            marginRight: token.marginLG,
        };
    });

    const selectRoleClassName = useEmotionCss(({ token }) => {
        return {
            fontSize: token.fontSize,
        };
    });

    const roleHeaderClassName = useEmotionCss(({ token }) => {
        return {
            display: 'flex',
            flexDirection: 'row',
            alignItems: 'center',
            justifyContent: 'space-between',
            marginTop: token.marginXS,
        };
    });


    const loadRoleGroup = useCallback(async () => {
        const res = await SysRoleGroupController.getAllList();
        setRoleGroupList(res ?? []);
    }, []);

    useEffect(() => {
        loadRoleGroup();
        (async () => {
            const menuList = await SysMenuController.getAllList();
            if (menuList) {
                setMenuData({ menuList, menuTreeNodes: buildMenuActionTree(menuList) });
            }
            setLoading(false);
        })();
    }, []);

    const handleSaveRoleAuth = async () => {
        const mids = authListRef.current?.getRoleMenuAuth();
        if (!mids) {
            return;
        }
        const hide = message.loading('保存中...', 0);
        try {
            await SysRoleMenuController.grantRoleMenu(mids);
            message.success('保存成功！');
        }
        catch (ex) {
            message.error('保存失败！');
        }
        finally {
            hide();
        }
    };

    const roleGroupEditDisabled = roleGroup?.id === 1;
    const roleEditDisabled = role?.id === 1;

    return (
        <PageContainer content="管理角色组和角色信息，管理角色权限及人员。">
            <ProCard split="vertical" loading={loading}>
                <ProCard colSpan="260px">
                    <Access accessible={hasPermission(PERMISSIONS.SYS.ROLE.OP_ADD)}>
                        <div className={roleHeaderClassName}>
                            <Button
                                type="primary"
                                onClick={() => setRoleGroupEditVisible(true)}
                            >
                                新建角色组
                            </Button>
                            <Button
                                type="primary"
                                onClick={() => setRoleEditVisible(true)}
                            >
                                新建角色
                            </Button>
                        </div>
                        <Divider />
                    </Access>
                    <RoleTree ref={roleTreeRef}
                        roleGroupList={roleGroupList}
                        onRoleGroupSelect={(roleGroup) => { setRoleGroup(roleGroup); setRole(undefined); }}
                        onRoleSelect={(role) => {
                            setRoleGroup(undefined);
                            setRole(role);
                        }}
                    />
                    {roleGroupEditVisible && (
                        <RoleGroupEditModal
                            data={editRef.current && roleGroup ? roleGroup : { id: 0 }}
                            onFinish={async (data) => {
                                if (data) {
                                    setRoleGroup(r => ({ ...r, ...data } as API.SysRoleGroupOutput));
                                }
                                await loadRoleGroup();
                                roleTreeRef.current?.reload();
                            }}
                            onClose={() => { editRef.current = false; setRoleGroupEditVisible(false); }}
                        />
                    )}
                    {roleEditVisible && (
                        <RoleEditModal
                            data={editRef.current && role ? role : { id: 0 }}
                            roleGroupList={roleGroupList}
                            onFinish={(data) => {
                                if (data) {
                                    setRole(r => ({ ...r, ...data } as API.SysRoleOutput));
                                }
                                roleTreeRef.current?.reload();
                            }}
                            onClose={() => { editRef.current = false; setRoleEditVisible(false); }}
                        />
                    )}
                </ProCard>
                <ProCard split="horizontal">
                    <ProCard>
                        {(!role && !roleGroup) && <span className={selectRoleClassName}>当前未选择角色或角色组，请从左侧选择！</span>}
                        {roleGroup && (
                            <ProDescriptions
                                title="角色组管理"
                                extra={(
                                    <Space>
                                        <Access accessible={hasPermission(PERMISSIONS.SYS.ROLE.OP_EDIT)}>
                                            <Button type="primary"
                                                disabled={roleGroupEditDisabled}
                                                onClick={() => { editRef.current = true; setRoleGroupEditVisible(true); }}
                                            >修改</Button>
                                        </Access>
                                        <Access accessible={hasPermission(PERMISSIONS.SYS.ROLE.OP_DEL)}>
                                            <Button
                                                disabled={roleGroupEditDisabled}
                                                onClick={() => {
                                                    modal.confirm({
                                                        title: '警告',
                                                        content: '删除角色组，其角色组下所有角色也将被删除，删除后不能恢复，确认立即删除？',
                                                        okText: '确定',
                                                        cancelText: '取消',
                                                        centered: true,
                                                        onOk: async () => {
                                                            try {
                                                                await SysRoleGroupController.del({ id: roleGroup.id ?? 0 });
                                                                message.success('删除成功');
                                                                setRoleGroup(undefined);
                                                                await loadRoleGroup();
                                                                roleTreeRef.current?.reload();
                                                                return true;
                                                            } catch {
                                                                return false;
                                                            }
                                                        },
                                                    });
                                                }}
                                            >删除</Button>
                                        </Access>
                                    </Space>
                                )}
                            >
                                <ProDescriptions.Item label="角色组名称">{roleGroup.name}</ProDescriptions.Item>
                                <ProDescriptions.Item label="备注说明">{roleGroup.remark}</ProDescriptions.Item>
                            </ProDescriptions>
                        )}
                        {role && (
                            <ProDescriptions
                                title="角色管理"
                                extra={(
                                    <Space>
                                        <Button type="primary"
                                            disabled={roleEditDisabled}
                                            onClick={() => { editRef.current = true; setRoleEditVisible(true); }}
                                        >修改</Button>
                                        <Button disabled={roleEditDisabled}
                                            onClick={() => {
                                                modal.confirm({
                                                    title: '警告',
                                                    content: '删除后不能恢复，确认立即删除？',
                                                    okText: '确定',
                                                    cancelText: '取消',
                                                    centered: true,
                                                    onOk: async () => {
                                                        try {
                                                            await SysRoleController.del({ id: role.id ?? '0' });
                                                            message.success('删除成功');
                                                            setRole(undefined);
                                                            await loadRoleGroup();
                                                            roleTreeRef.current?.reload();
                                                            return true;
                                                        } catch {
                                                            return false;
                                                        }
                                                    },
                                                });
                                            }}
                                        >删除</Button>
                                    </Space>
                                )}
                            >
                                <ProDescriptions.Item label="角色名称">{role.name}</ProDescriptions.Item>
                                <ProDescriptions.Item label="备注说明">{role.remark}</ProDescriptions.Item>
                            </ProDescriptions>
                        )}
                    </ProCard>
                    {role && (<ProCard bodyStyle={{ paddingTop: 0 }}
                        tabs={{
                            tabBarStyle: { paddingInlineStart: token.marginXS },
                            tabBarExtraContent: (
                                <>
                                    {roleTabKey === TAB_AUTH && (
                                        // <Access
                                        //     accessible={hasPermission(
                                        //         PERMISSIONS.SYS.ROLE.OP_ACTION_GRANT,
                                        //     )}
                                        // >
                                        <Button
                                            type="primary"
                                            onClick={() => handleSaveRoleAuth()}
                                            icon={<SaveOutlined />}
                                            className={tabButtonClassName}
                                        >
                                            保存权限设置
                                        </Button>
                                        // </Access>
                                    )}
                                    {roleTabKey === TAB_USER && (
                                        <>
                                            <Button
                                                type="primary"
                                                icon={<UserAddOutlined />}
                                                onClick={() => setAddRoleUserVisible(true)}
                                                className={tabButtonClassName}
                                                style={{ marginRight: token.marginXS }}
                                            >
                                                添加成员
                                            </Button>
                                            {addRoleUserVisible && (
                                                <RoleUserAddModal
                                                    role={role}
                                                    onFinish={() =>
                                                        userListRef?.current?.reload()
                                                    }
                                                    onClose={() => setAddRoleUserVisible(false)}
                                                />
                                            )}
                                            <Button
                                                // style={{ marginLeft: 8, marginRight: 8 }}
                                                icon={<UserDeleteOutlined />}
                                                onClick={() => userListRef?.current?.remove()}
                                                className={tabButtonClassName}
                                            >
                                                移除成员
                                            </Button>
                                        </>
                                    )}
                                </>
                            ),
                            onChange: setRoleTabKey,
                            animated: false,
                            items: [
                                {
                                    label: '角色权限设置',
                                    key: TAB_AUTH,
                                    style: { overflow: 'hidden' },
                                    children: (
                                        <AuthList
                                            ref={authListRef}
                                            menuData={menuData}
                                            role={role}
                                        />
                                    ),
                                },
                                {
                                    label: '角色成员管理',
                                    key: TAB_USER,
                                    style: { overflow: 'hidden' },
                                    children: <UserList ref={userListRef} role={role} />,
                                },
                            ],
                        }}
                    />)}
                </ProCard>
            </ProCard>
        </PageContainer>
    );
};

export default Role;
