package com.lantone.security.aop;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lantone.common.constant.AuthConstant;
import com.lantone.common.enums.IsDeleteEnum;
import com.lantone.common.exception.Asserts;
import com.lantone.common.service.RedisService;
import com.lantone.common.util.ListUtil;
import com.lantone.common.util.SysUserUtils;
import com.lantone.common.vo.base.BasePageVo;
import com.lantone.common.vo.base.BaseVo;
import com.lantone.security.entity.UserRole;
import com.lantone.security.facade.base.UserRoleFacade;
import com.lantone.security.annotation.DataAuthFilter;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:数据权限过滤处理切面
 * @Author songxl
 * @Date 2021/8/25
 */
@Aspect
@Component
public class DataAuthFilterAspect {
    @Autowired
    private UserRoleFacade userRoleFacade;
    @Autowired
    private RedisService redisService;
    //切入点
    @Pointcut("@annotation(com.lantone.security.annotation.DataAuthFilter)")
    public void dataFilterCut() {

    }

    @Before("dataFilterCut()")
    public void dataFilter(JoinPoint point) {
        Object params = point.getArgs()[0];
        if (params != null) {
            //获取当前用户角色集合如果是超级管理员则不进行数据过滤
            List<Long> roleIds = userRoleFacade.list(new QueryWrapper<UserRole>()
                    .eq("user_id", SysUserUtils.getCurrentPrincipleId())
                    .eq("is_deleted", IsDeleteEnum.N.getKey())).stream().map(UserRole::getRoleId).collect(Collectors.toList());
            if (!roleIds.contains(AuthConstant.SUPPER_ADMIN)) {
                if (params instanceof BaseVo) {
                    BaseVo vo = (BaseVo) params;
                    vo.getMap().put(AuthConstant.DATAAUTH_FILTER_SQL, getSQLFilter(point));
                }
                if (params instanceof BasePageVo) {
                    BasePageVo vo = (BasePageVo) params;
                    vo.getMap().put(AuthConstant.DATAAUTH_FILTER_SQL, getSQLFilter(point));
                }
            }
            return;
        } else {
            Asserts.fail("数据权限接口入参对象要继承BaseVo或BasePageVo，且不能为NULL");
        }
    }

    /**
     * @param point
     * @Description获取数据过滤的SQL
     * @Return java.lang.String
     */
    private String getSQLFilter(JoinPoint point) {

        MethodSignature signature = (MethodSignature) point.getSignature();
        DataAuthFilter dataAuthFilter = signature.getMethod().getAnnotation(DataAuthFilter.class);
        //获取该用户数据权限
        Map<String,List> dataAuthMap = redisService.hGetAll(SysUserUtils.getCurrentHospitalId()+"_"+SysUserUtils.getCurrentPrincipleId()+"_"+SysUserUtils.getCurrentSoftwareIdStr());

        StringBuilder sqlFilter = new StringBuilder();
        sqlFilter.append(" (");

        //sql拼接
        //1.筛选用户组
        if (StringUtils.isNotEmpty(dataAuthFilter.usersAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("users"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.usersAlias()).append(" in(").append(StringUtils.join(dataAuthMap.get("users"), ",")).append(")");
        }

        if (StringUtils.isNotEmpty(dataAuthFilter.usersAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("notUsers"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.usersAlias()).append(" not in(").append(StringUtils.join(dataAuthMap.get("notUsers"), ",")).append(")");
        }

        //2.筛选科室组
        if (StringUtils.isNotEmpty(dataAuthFilter.deptsAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("depts"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.deptsAlias()).append(" in(").append(StringUtils.join(dataAuthMap.get("depts"), ",")).append(")");
        }
        if (StringUtils.isNotEmpty(dataAuthFilter.deptsAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("notDepts"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.deptsAlias()).append(" not in(").append(StringUtils.join(dataAuthMap.get("notDepts"), ",")).append(")");
        }

        //3.筛选组织组
        if (StringUtils.isNotEmpty(dataAuthFilter.hospitalsAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("hospitals"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.hospitalsAlias()).append(" in(").append(StringUtils.join(dataAuthMap.get("hospitals"), ",")).append(")");
        }
        if (StringUtils.isNotEmpty(dataAuthFilter.hospitalsAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("notHospitals"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.hospitalsAlias()).append(" not in(").append(StringUtils.join(dataAuthMap.get("notHospitals"), ",")).append(")");
        }

        //4.自身
        if (StringUtils.isNotEmpty(dataAuthFilter.self())) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.self()).append(" =").append(SysUserUtils.getCurrentPrincipleId());
        }

        //5.医生组（医疗组）
        if (StringUtils.isNotEmpty(dataAuthFilter.doctorsAlias()) && ListUtil.isNotEmpty(dataAuthMap.get("doctors"))) {
            sqlAppend(sqlFilter);
            sqlFilter.append(dataAuthFilter.doctorsAlias()).append(" in(").append(StringUtils.join(dataAuthMap.get("doctors"), ",")).append(")");
        }

        sqlFilter.append(") ");

        if (sqlFilter.toString().trim().equals("()")) {
            return null;
        }

        return sqlFilter.toString();
    }

    private void sqlAppend(StringBuilder sqlFilter) {
        if (sqlFilter.toString().trim().length() > 1) {
            sqlFilter.append(" or ");
        }
    }
}
