package com.storlead.system.assemble;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.storlead.framework.auth.vo.LoginUser;
import com.storlead.framework.common.util.ConvertUtils;
import com.storlead.framework.mybatis.entity.SysBaseField;
import com.storlead.framework.util.LoginUserUtil;
import com.storlead.framework.mybatis.query.QueryBaseEntity;
import com.storlead.system.pojo.entity.*;
import com.storlead.system.service.*;
import com.storlead.user.pojo.entity.DeptEntity;
import com.storlead.user.pojo.entity.UserEntity;
import com.storlead.user.service.IDepartService;
import com.storlead.user.service.IUserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: sp-sales-platform
 * @description:
 * @author: chenkq
 * @create: 2024-04-02 18:10
 */
@Component
public class DataScope {

    private final String[] scopeType = {"全部", "本公司", "自定义","仅自己","本部门"};

    @Resource
    private IUserService userService;

    @Resource
    private IMenuService menuService;

    @Resource
    private IRoleMenuService roleMenuService;

    @Resource
    private IRoleService roleService;

    @Resource
    private IDepartService deptService;


    public Set<Long> getDeptIds() {

        UserEntity user = userService.getById(LoginUserUtil.getLoginUser().getId());
        return getDeptIds(user);
    }


    public Set<Long> getDeptIds(UserEntity user) {

        // 查询用户角色
        List<RoleEntity> roleSet = roleService.findByUserId(user.getId());
        UserEntity us = userService.getById(user.getId());
        return getDeptIds(roleSet,us);
    }

    public Long getSubCompanyId(List<RoleEntity> roleSet, UserEntity user) {
        // 存储本公司的数据权限
        for (RoleEntity role : roleSet) {
            if (scopeType[1].equals(role.getDataScope())) {
                return user.getSubCompanyId();
            }
        }
        return null;
    }
    public Set<Long> getDeptIds(List<RoleEntity> roleSet, UserEntity user) {
        // 用于存储部门id
        Set<Long> deptIds = new HashSet<>();

        for (RoleEntity role : roleSet) {
            if (scopeType[0].equals(role.getDataScope())) {
                return new HashSet<>();
            }

            // 存储自定义的数据权限
            if (scopeType[2].equals(role.getDataScope())) {
                Set<DeptEntity> depts = deptService.findByRoleId(role.getId());
                for (DeptEntity dept : depts) {
                    deptIds.add(dept.getId());
                    List<DeptEntity> deptChildren = deptService.findByPid(dept.getId());
                    if (deptChildren != null && deptChildren.size() != 0) {
                        deptIds.addAll(deptService.getDeptChildren(deptChildren));
                    }
                }
            }
            // 存储本部的数据权限
            if (scopeType[4].equals(role.getDataScope())) {
                //deptIds.add(user.getDept().getId());
                deptIds.add(user.getDeptId());
            }
        }
        return deptIds;
    }


    /**
     * 查询当前用户的角色是否只有一个自己的数据权限
     *
     * @param roleSet 用户ID
     * @return boolean
     * @author blank
     * @date 2021-3-31 下午 5:29
     */
    public boolean isSelfDataScope(List<RoleEntity> roleSet) {
        // 查询用户角色
        for (RoleEntity role : roleSet) {
            if (scopeType[3].equals(role.getDataScope())) {
                return true;
            }
        }
        return false;
    }


    /**
     * 判断用户角色中是否有全部的数据，如果有，则表示该用户有全部数据权限
     *
     * @param roleIds
     * @return
     */
    public boolean isAllDataScope(Set<Long> roleIds) {
        List<RoleEntity> roleSet = (List<RoleEntity>) roleService.listByIds(roleIds);
        for (RoleEntity role : roleSet) {
            if (scopeType[0].equals(role.getDataScope())) {
                return true;
            }
        }
        return false;
    }

    public boolean isAllDataScope(List<RoleEntity> roleSet) {
        for (RoleEntity role : roleSet) {
            if (scopeType[0].equals(role.getDataScope())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 自定义
     * @param userId
     * @return
     */
    public boolean isSelfDataScope(Long userId) {
        List<RoleEntity> roleSet = roleService.findByUserId(userId);
        for (RoleEntity role : roleSet) {
            if (scopeType[1].equals(role.getDataScope())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查询是否是超级管理员
     *
     * @param userId 用户ID
     * @return boolean
     * @author blank
     * @date 2021-6-8 下午 6:45
     */
    public boolean isAdmin(Long userId) {
        // 查询用户角色
        List<RoleEntity> roleSet = roleService.findByUserId(userId);
        // roleId =1 =>超级管理员
        return roleSet.stream().anyMatch(role -> role.getId().equals(1L));
    }

//    public boolean isSelfDataScope(Long userId, HttpServletRequest request) {
//
//        List<MenuEntity> menus = menuService.loadMenuType3Resource();
//        boolean isSelfOnly = true;
//        // 查询用户角色
//        List<RoleEntity> roleSet = roleService.findByUserId(userId);
//        boolean isAdmin = roleSet.stream().anyMatch(role -> role.getId().equals(1L)) || roleSet.stream().anyMatch(role -> role.getDataScope().equals(scopeType[0])) ;
//        if (isAdmin) {
//            // roleId =1 =>超级管理员
//            return false;
//        }
//
//        for (RoleEntity role : roleSet) {
//
//            if (scopeType[3].equals(role.getDataScope())) {
//                //跳过只有自己权限的角色
//                continue;
//            }
//
//            Long roleId = role.getId();
//            List<RoleMenuEntity> roleMenuList = roleMenuService.list(new LambdaQueryWrapper<RoleMenuEntity>().eq(RoleMenuEntity::getRoleId, roleId));
//
//            if (roleMenuList != null && roleMenuList.size() > 0) {
//
//                for (RoleMenuEntity roleMenu : roleMenuList) {
//
//                    MenuEntity menu = menus.stream().filter(m -> m.getId().equals(roleMenu.getMenuId())).findAny().orElse(null);
//                    if (menu != null) {
//                        AntPathRequestMatcher antPathRequestMatcher = new AntPathRequestMatcher(menu.getPath());
//                        if (antPathRequestMatcher.matches(request)) {
//                            isSelfOnly = false;
//                        }
//                    }
//                }
//            }
//        }
//
//        return isSelfOnly;
//    }

    public <W extends SysBaseField,E extends QueryBaseEntity> void assemblyDataWrapperPurview(LambdaQueryWrapper<W> wrapper, E e, String mergeSql) {

        StringBuilder whereCondition = new StringBuilder();
        LoginUser currentUser = LoginUserUtil.getLoginUser();
        UserEntity user = userService.getById(currentUser.getId());
        if (StringUtils.isNotEmpty(e.getCommonQueryOrderBy())) {
            String sortField = ConvertUtils.camelToUnderscore(e.getCommonQueryOrderBy());
            String sortMethod = "asc";
            if ("desc".equals(e.getSortMethod())) {
                sortMethod = "desc";
            }
            wrapper.last(" order by "+sortField + " " + sortMethod);
        }
        if (StrUtil.isBlank(currentUser.getScopeMenuId()) && !Integer.valueOf(1).equals(currentUser.getCommonScope())) {
            return;
        }
        if(Integer.valueOf(1).equals(e.getReviewTag())) {
            return;
        }
        Set<Long> roleIds = new HashSet<>();
        if (Integer.valueOf(1).equals(currentUser.getCommonScope())) {
            roleIds = userService.selectUserRoleIdsByCommonScopeType(currentUser.getId(),currentUser.getCommonScopeType());
        } else {
            if (Objects.isNull(currentUser.getScopeMenuId())) {
                return;
            }
            roleIds =  userService.selectUserRoleIdsByMenuId(currentUser.getId(),currentUser.getScopeMenuId());
        }
        if (CollectionUtil.isNotEmpty(roleIds)) {
            List<RoleEntity> roles = roleService.listByIds(roleIds).stream().collect(Collectors.toList());
            boolean allDataScope = this.isAllDataScope(roles);
            if (!allDataScope) {
                boolean selfDataScope = this.isSelfDataScope(roles);
                if (selfDataScope) {
                    whereCondition.append("us.id = "+user.getId());
                }
                Set<Long> deptIds = this.getDeptIds(roles,user);
                if (CollectionUtil.isNotEmpty(deptIds)) {
                    if (whereCondition.length() > 0)  {
                        whereCondition.append(" or ");
                    }
                    whereCondition.append("us.dept_id in (");
                    whereCondition.append(StringUtils.join(deptIds,","));
                    whereCondition.append(" )");
                }
                Long selfSubCompanyId = this.getSubCompanyId(roles,user);
                if (Objects.nonNull(selfSubCompanyId)) {
                    if (whereCondition.length() > 0)  {
                        whereCondition.append(" or ");
                    }
                    whereCondition.append("us.sub_company_id = "+selfSubCompanyId);
                }
            }
        }else {
            whereCondition.append("us.id = 0 ");
        }

        if (StringUtils.isNotEmpty(whereCondition.toString())) {
            String whereSql = " owner_by IN (select id from `user` as us where (" + whereCondition + "))";
            if (StrUtil.isNotBlank(mergeSql)) {
                whereSql = ("("+whereSql +" or ("+mergeSql+"))");
            }
            wrapper.apply(whereSql);
        }

        if (StringUtils.isNotEmpty(e.getCommonQueryOrderBy())) {
            String sortField = ConvertUtils.camelToUnderscore(e.getCommonQueryOrderBy());
            String sortMethod = "asc";
            if ("desc".equals(e.getSortMethod())) {
                sortMethod = "desc";
            }
            wrapper.last(" order by "+sortField + " " + sortMethod);
        }
    }

    public <W extends SysBaseField,E extends QueryBaseEntity> void assemblyDataOnlyWrapper(LambdaQueryWrapper<W> wrapper,String mergeSql) {

        StringBuilder whereCondition = new StringBuilder();
//        if(Integer.valueOf(1).equals(LoginUserUtil.getReviewTag())) {
//            return;
//        }
        LoginUser currentUser = LoginUserUtil.getLoginUser();
        UserEntity user = userService.getById(currentUser.getId());
        Set<Long> roleIds = new HashSet<>();

        if (Integer.valueOf(1).equals(currentUser.getCommonScope())) {
            roleIds = userService.selectUserRoleIdsByCommonScopeType(currentUser.getId(),currentUser.getCommonScopeType());
        } else {
            if (Objects.isNull(currentUser.getScopeMenuId())) {
                return;
            }
            roleIds =  userService.selectUserRoleIdsByMenuId(currentUser.getId(),currentUser.getScopeMenuId());
            roleIds =  userService.selectUserRoleIdsByMenuId(currentUser.getId(),currentUser.getScopeMenuId());
        }
        if (CollectionUtil.isNotEmpty(roleIds)) {
            List<RoleEntity> roles = roleService.listByIds(roleIds).stream().collect(Collectors.toList());
            boolean allDataScope = this.isAllDataScope(roles);
            if (!allDataScope) {
                boolean selfDataScope = this.isSelfDataScope(roles);
                if (selfDataScope) {
                    whereCondition.append("us.id = "+user.getId());
                }
                Set<Long> deptIds = this.getDeptIds(roles,user);
                if (CollectionUtil.isNotEmpty(deptIds)) {
                    if (whereCondition.length() > 0)  {
                        whereCondition.append(" or ");
                    }
                    whereCondition.append("us.dept_id in (");
                    whereCondition.append(StringUtils.join(deptIds,","));
                    whereCondition.append(" )");
                }
                Long selfSubCompanyId = this.getSubCompanyId(roles,user);
                if (Objects.nonNull(selfSubCompanyId)) {
                    if (whereCondition.length() > 0)  {
                        whereCondition.append(" or ");
                    }
                    whereCondition.append("us.sub_company_id = "+selfSubCompanyId);
                }
            }
        }else {
            whereCondition.append("us.id = 0 ");
        }
        if (StringUtils.isNotEmpty(whereCondition.toString())) {
            String whereSql = " owner_by IN (select id from `user` as us where (" + whereCondition + "))";
            if (StrUtil.isNotBlank(mergeSql)) {
                whereSql = ("("+whereSql +" or ("+mergeSql+"))");
            }
            wrapper.apply(whereSql);
        }
//        else {
//            if (StrUtil.isNotBlank(mergeSql)) {
//                String whereSql = ("("+mergeSql+")");
//                wrapper.apply(whereSql);
//            }
//        }
    }


    public  <E extends QueryBaseEntity> void assemblyDataEntityPurview(E e) {
        if (!Integer.valueOf(1).equals(e.getReviewTag())) {
            StringBuilder whereCondition = new StringBuilder();
            LoginUser currentUser = LoginUserUtil.getLoginUser();
            UserEntity user = userService.getById(currentUser.getId());
            Set<Long> roleIds = userService.getUserRoleIdsByApiUrl(currentUser.getId(),currentUser.getApiUrl());
            if (CollectionUtil.isNotEmpty(roleIds)) {
                List<RoleEntity> roles = (List<RoleEntity>) roleService.listByIds(roleIds);
                boolean allDataScope = this.isAllDataScope(roles);
                if (!allDataScope) {
                    boolean selfDataScope = this.isSelfDataScope(roles);
                    if (selfDataScope) {
                        whereCondition.append("us.id = "+user.getId());
                    }
                    Set<Long> deptIds = this.getDeptIds(roles,user);
                    if (CollectionUtil.isNotEmpty(deptIds)) {
                        if (whereCondition.length() > 0)  {
                            whereCondition.append(" or ");
                        }
                        whereCondition.append("us.dept_id in (");
                        whereCondition.append(StringUtils.join(deptIds,","));
                        whereCondition.append(" )");
                    }
                    Long selfSubCompanyId = this.getSubCompanyId(roles,user);
                    if (Objects.nonNull(selfSubCompanyId)) {
                        if (whereCondition.length() > 0)  {
                            whereCondition.append(" or ");
                        }
                        whereCondition.append("sub_company_id = "+selfSubCompanyId);
                    }
                }
            } else {
                whereCondition.append("us.id = 0 ");
            }
            String whereSql = " owner_by IN (select id from `user` as us where (" + whereCondition + "))";
            e.setDataScopeSql(whereSql);
        }
    }
}
