package com.keyware.shandan.frame.aspect;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.keyware.shandan.bianmu.entity.DirectoryVo;
import com.keyware.shandan.bianmu.entity.MetadataBasicVo;
import com.keyware.shandan.bianmu.enums.ReviewStatus;
import com.keyware.shandan.common.enums.DataPermisScope;
import com.keyware.shandan.frame.annotation.DataPermissions;
import com.keyware.shandan.frame.config.security.SecurityUtil;
import com.keyware.shandan.system.entity.SysOrg;
import com.keyware.shandan.system.entity.SysPermissions;
import com.keyware.shandan.system.entity.SysRole;
import com.keyware.shandan.system.entity.SysUser;
import com.keyware.shandan.system.service.SysOrgService;
import com.keyware.shandan.system.service.SysPermissionsService;
import com.keyware.shandan.system.service.SysRoleService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 数据权限处理
 */
@Aspect
@Component
public class DataPermissionsAspect {

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysOrgService sysOrgService;

    @Autowired
    private SysPermissionsService permissionsService;

    @Autowired
    private SecurityUtil securityUtil;


    @Around(value = "@annotation(com.keyware.shandan.frame.annotation.DataPermissions)")
    public Object permissionsProtected(ProceedingJoinPoint joinPoint) throws Throwable {

        //获取登录用户信息
        SysUser currentUser = securityUtil.getLoginUser();
        Assert.notNull(currentUser, "无法获取到当前登录的用户信息");
        // 当前用户权限范围
        List<SysPermissions> permisList = getCurrentUserPermissions(currentUser.getUserId());
        DataPermissions annotation = AspectCommon.getAnnotationByMethod(joinPoint, DataPermissions.class);

        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof QueryWrapper) {
                QueryWrapper<Object> wrapper = (QueryWrapper<Object>) args[i];
                Set<String> orgIds = getAllPermitOrgId(permisList, currentUser);
                if (!isSuperAdmin(permisList)) {
                    wrapper.and(true, wp -> {
                        if (orgIds.size() > 0) {
                            wp.in(true, annotation.orgColumn(), orgIds);
                        }
                        wp.or().eq(true, "CREATE_USER", currentUser.getUserId()).or();
                    });
                }
                appendReviewStatusWrapper(joinPoint, wrapper);
                args[i] = wrapper;
                break;
            }
        }
        return joinPoint.proceed(args);
    }

    /**
     * 获取当前用户的所有被授权访问的部门ID
     *
     * @param permisList  权限列表
     * @param currentUser 当前用户
     * @return 部门ID集合
     */
    private Set<String> getAllPermitOrgId(List<SysPermissions> permisList, SysUser currentUser) {
        Set<String> orgIds = new HashSet<>();
        SysOrg currentOrg = sysOrgService.getById(currentUser.getOrgId());
        if (permisList.stream().anyMatch(permis -> permis.getPermisScope() == DataPermisScope.CURRENT_ORG_CHILDRENS)) {
            // 添加当前部门和子部门
            orgIds.add(currentOrg.getId());
            sysOrgService.getOrgAllChildren(currentOrg.getId()).forEach(org -> orgIds.add(org.getId()));

        } else if (permisList.stream().anyMatch(permis -> permis.getPermisScope() == DataPermisScope.ONLY_CURRENT_ORG)) {
            // 只添加当前部门
            orgIds.add(currentOrg.getId());
        }

        // 自定义权限
        if (permisList.stream().anyMatch(permis -> permis.getPermisScope() == DataPermisScope.SPECIAL)) {
            permisList.stream()
                    .filter(permis -> permis.getPermisScope() == DataPermisScope.SPECIAL)
                    .forEach(permis -> orgIds.addAll(permissionsService.getOrgConfigs(permis.getPermisId())));
        }
        return orgIds;
    }

    /**
     * 为查询包装器追加审核条件
     *
     * @param joinPoint 切面连接点
     * @param wrapper   查询包装器
     */
    private void appendReviewStatusWrapper(ProceedingJoinPoint joinPoint, QueryWrapper<Object> wrapper) {
        Object entity = wrapper.getEntity();
        Class entityClass = AspectCommon.geTargetClassTType(joinPoint);
        if (entity != null && entityClass != null) {
            ReviewStatus reviewStatus = null;
            if (entityClass.equals(DirectoryVo.class)) {
                DirectoryVo dir = (DirectoryVo) entity;
                reviewStatus = dir.getReviewStatus();
            } else if (entityClass.equals(MetadataBasicVo.class)) {
                MetadataBasicVo metadata = (MetadataBasicVo) entity;
                reviewStatus = metadata.getReviewStatus();
            }
            if (reviewStatus != null) {
                wrapper.eq("REVIEW_STATUS", reviewStatus.getValue());
            }
        }
    }

    /**
     * 获取当前用户的权限集合
     *
     * @return
     */
    private List<SysPermissions> getCurrentUserPermissions(String userId) {
        List<SysRole> roleList = sysRoleService.getUserRoles(userId);
        List<SysPermissions> permisList = new ArrayList<>();
        roleList.forEach(role -> permisList.addAll(role.getPermissionsList()));
        return permisList;
    }

    /**
     * 判断是否包含超级管理员权限
     *
     * @param permisList 权限集合
     * @return 是否超级管理员
     */
    private boolean isSuperAdmin(List<SysPermissions> permisList) {
        return permisList.stream().anyMatch(permis -> permis.getPermisScope() == DataPermisScope.ALL_SCOPE);
    }

}
