import { PERMISSIONS } from '@/common/constant';
import { SuperTable } from '@/components';
import SysRoleMenuController from '@/services/apis/SysRoleMenuController';
import { MenuType, RoleType } from '@/services/enums';
import type { ProColumns } from '@ant-design/pro-components';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import { useAccess, useRequest } from '@umijs/max';
import { Checkbox } from 'antd';
import lodash from 'lodash';
import { forwardRef, useCallback, useImperativeHandle, useState } from 'react';
import type { MenuDataType } from '..';
import { RoleMenuActionItem, buildRoleMenuActions } from '../../utils';

export interface AuthListHandles {
    getRoleMenuAuth: () => API.GrantSysRoleMenuInput;
}

type AuthListProps = {
    menuData: MenuDataType;
    role: API.SysRoleOutput;
};

type AuthActionType = Record<number, number[]>;
type SelectedMenuType = {
    id: number;
    selected: boolean;
};

/** 授权列表 */
const AuthList = forwardRef<AuthListHandles, AuthListProps>(({ menuData, role }, ref) => {
    const { menuList, menuTreeNodes } = menuData;
    const [expandedRowKeys, setExpandedRowKeys] = useState<React.Key[]>(
        (menuList?.map((t) => t.id) ?? []) as React.Key[],
    );
    const [roleMenuAuth, setRoleMenuAuth] = useState<AuthActionType>({});
    const [selectedData, setSelectedData] = useState<{
        selectedRowKeys: number[];
        selectedMenus: SelectedMenuType[];
    }>({ selectedRowKeys: [], selectedMenus: [] });

    // const { getDictOptions } = useModel('useDict');
    // const dataScopeOptions = getDictOptions('data_scope_type');

    const { hasPermission } = useAccess();

    const checkboxGroupClassName = useEmotionCss(() => {
        return {
            flexWrap: 'wrap',
            wordBreak: 'keep-all',
            '.ant-checkbox-wrapper': {
                marginInlineStart: 4,
            },
        };
    });

    useImperativeHandle(ref, () => ({
        getRoleMenuAuth: (): API.GrantSysRoleMenuInput => {
            const { selectedMenus } = selectedData;
            let menuIds = selectedMenus.map((t) => t.id) ?? [];
            for (const k in roleMenuAuth) {
                if (roleMenuAuth.hasOwnProperty(k)) {
                    const mid = parseInt(k);
                    if (menuIds.includes(mid)) {
                        menuIds = menuIds.concat(roleMenuAuth[k]);
                    }
                }
            }
            return {
                roleId: role?.id ?? '0',
                roleMenuScopeList: menuIds.map(t => ({ menuId: t })),
            };
        },
    }));

    // 获取数据
    const { loading } = useRequest<API.SysRoleMenuOutput[]>(
        () => {
            return SysRoleMenuController.getRoleMenuList({ roleid: role.id });
        },
        {
            formatResult: (res: API.SysRoleMenuOutput[]) => {
                const menus = res?.map(t => t.sysMenu) ?? [];
                const roleMenuList = buildRoleMenuActions(menus);
                const smenus = roleMenuList.map((t) => ({
                    id: t.id,
                    selected: false,
                })) as SelectedMenuType[];
                const notButtonMenuList = menuList.filter(
                    (t) => t.menuType !== MenuType.BUTTON,
                );
                smenus.forEach((t) => {
                    if (lodash.findIndex(notButtonMenuList, ['pid', t.id]) === -1) {
                        t.selected = true;
                    }
                });

                const rma: AuthActionType = {};
                roleMenuList.forEach((t) => {
                    rma[t.id] = t.actions?.map((a) => a.id) ?? [];
                });

                setSelectedData({
                    selectedMenus: smenus,
                    selectedRowKeys: smenus.filter((t) => t.selected).map((t) => t.id) ?? [],
                });
                setRoleMenuAuth(rma);
            },
            refreshDeps: [role?.id],
        },
    );

    const { selectedMenus, selectedRowKeys } = selectedData;
    const selectedMenuIds = selectedMenus?.map((t: any) => t.id) || [];

    // 获取菜单父级
    const getMenuParentId = useCallback(
        (id: number, parentId: number, selectedRows: number[]) => {
            const ps: SelectedMenuType[] = [{ id, selected: selectedRows.includes(id) }];
            let sps: SelectedMenuType[] = [];
            const m = menuList.find((t) => t.id === parentId);
            if (m) {
                sps = getMenuParentId(parentId, m?.pid ?? 0, selectedRows);
            }
            return ps.concat(sps);
        },
        [menuList],
    );

    // 获取选中的菜单
    const getSelectedMenus = useCallback(
        (selectedRows: RoleMenuActionItem[]) => {
            let menus: SelectedMenuType[] = [];
            for (let i = 0; i < selectedRows.length; i++) {
                const sr = selectedRows[i];
                menus = menus.concat(getMenuParentId(sr.id, sr.pid, selectedRows.map((t: any) => t.id)));
            }
            const smenus = lodash.uniqBy(menus, 'id');
            const sks = smenus.filter((t) => t.selected).map((t) => t.id) || [];
            setSelectedData({
                selectedMenus: smenus,
                selectedRowKeys: sks,
            });
        },
        [getMenuParentId],
    );

    // 处理操作权限事件
    const handleCheckOperationAuth = (record: RoleMenuActionItem, action_ids: number[]) => {
        const rma = { ...roleMenuAuth };
        rma[record.id] = action_ids ?? [];
        setRoleMenuAuth(rma);
    };

    // 表列定义
    const columns: ProColumns<RoleMenuActionItem>[] = [
        {
            title: '功能模块',
            dataIndex: 'name',
            width: 180,
            className: 'minw-160',
        },
        {
            title: '操作权限',
            dataIndex: 'actions',
            render: (_, r) => {
                const options = r?.actions?.map((t) => ({ value: t.id, label: t.name }));
                return (
                    <Checkbox.Group
                        className={checkboxGroupClassName}
                        disabled={!selectedMenuIds.includes(r.id)}
                        options={options}
                        value={roleMenuAuth[r.id]}
                        onChange={(checkedValue) =>
                            handleCheckOperationAuth(r, checkedValue as number[])
                        }
                    />
                );
            },
        },
        // {
        //     title: '数据权限',
        //     dataIndex: 'dataScopeType',
        //     width: 320,
        //     render: (_, r) => {
        //         return (<Radio.Group disabled={!selectedRowKeys.includes(r.id)} defaultValue={r.dataScopeType} options={dataScopeOptions} />);
        //     },
        // }
    ];

    return (
        <SuperTable
            columns={columns}
            loading={loading}
            search={false}
            dataSource={menuTreeNodes}
            toolBarRender={false}
            tableAlertRender={false}
            tableLayout="fixed"
            sticky={false}
            rowSelection={{
                checkStrictly: false,
                fixed: true,
                selections: false,
                onSelect: (record, selected, selectedRows) => {
                    getSelectedMenus(selectedRows);
                },
                onSelectAll: (selected, selectedRows) => {
                    getSelectedMenus(selectedRows);
                },
                selectedRowKeys: selectedRowKeys,
                getCheckboxProps: () => ({
                    disabled: role?.roleType === RoleType.SUPER_ADMIN || !hasPermission(PERMISSIONS.SYS.ROLE.OP_GRANT),
                }),
            }}
            expandable={{
                expandedRowKeys: expandedRowKeys,
                onExpandedRowsChange: (erks) => {
                    setExpandedRowKeys(erks as number[]);
                },
            }}
            pagination={false}
        />
    );
});

export default AuthList;
