package com.sckw.system.service;

import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.MenuTypeEnum;
import com.sckw.core.model.enums.SystemTypeEnum;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.config.CustomConfig;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.excel.utils.ExcelUtil;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.system.dao.*;
import com.sckw.system.model.*;
import com.sckw.system.model.pojo.FindManagePojo;
import com.sckw.system.model.pojo.FindMenuTreePojo;
import com.sckw.system.model.report.KwsRoleExcel;
import com.sckw.system.model.report.KwsUserExcel;
import com.sckw.system.model.vo.req.EditRoleReqVo;
import com.sckw.system.model.vo.req.RoleBindMenuReqVo;
import com.sckw.system.model.vo.req.UserBindRoleReqVo;
import com.sckw.system.model.vo.res.IdResVo;
import com.sckw.system.model.vo.res.KwsMenuResVo;
import com.sckw.system.model.vo.res.RoleResVo;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 角色service接口
 *
 * @author zk
 * @date 2023-05-31
 */
@Service
public class KwsRoleService {

    @Autowired
    KwsRoleDao kwsRoleDao;

    @Autowired
    KwsUserDao kwsUserDao;

    @Autowired
    KwsUserRoleDao kwsUserRoleDao;

    @Autowired
    KwsAuthorityDao kwsAuthorityDao;

    @Autowired
    KwsUserDeptDao kwsUserDeptDao;

    @Autowired
    KwsDeptDao kwsDeptDao;

    @Autowired
    KwsEnterpriseDao kwsEnterpriseDao;

    @Autowired
    KwsMenuService kwsMenuService;

    @Autowired
    KwsMenuDao kwsMenuDao;

    @Autowired
    KwsMenuRightsDao kwsMenuRightsDao;

    @Autowired
    CustomConfig customConfig;

    @Value("${isBindManyRole}")
    private Integer isBindManyRole;

    /**
     * @param params KwsRole
     * @desc: 单表插入
     * @author: czh
     * @date: 2023/6/15
     */
    public void add(KwsRole params) {
        if (kwsRoleDao.insert(params) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }

    /**
     * @param reqVo 新增角色
     * @desc: 新增角色
     * @author: czh
     * @date: 2023/6/15
     */
    @Transactional(rollbackFor = Exception.class)
    public IdResVo add(EditRoleReqVo reqVo) {
        Long currentUnitId = reqVo.getCurrentUnitId();
        KwsDept kwsDept = kwsDeptDao.selectByKey(currentUnitId);
        if (Objects.isNull(kwsDept)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.DEPT_NOT_EXISTS);
        }

        String parentIds = kwsDept.getParentIds();
        String[] split = parentIds.split(Global.COMMA);
        Long topDeptId = Long.parseLong(split[0]);
        IdResVo idResVo = new IdResVo();
        List<KwsRole> kwsRoles = kwsRoleDao.selectBatchByUnitIds(Collections.singletonList(topDeptId));
        if (CollectionUtils.isNotEmpty(kwsRoles)) {
            List<String> nameList = kwsRoles.stream().map(KwsRole::getName).toList();
            if (nameList.contains(reqVo.getName())) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.MSG_024);
            }
        }

        /*1、存角色信息*/
        KwsRole kwsRole = new KwsRole();
        long roleId = new IdWorker(1L).nextId();
        idResVo.setId(roleId);
        kwsRole.setId(roleId);
        kwsRole.setName(reqVo.getName());
        kwsRole.setDeptId(topDeptId);
        kwsRole.setRemark(reqVo.getRemark());
        if (kwsRoleDao.insert(kwsRole) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }

        /*2、绑定菜单功能*/
        RoleBindMenuReqVo roleBindMenuReqVo = new RoleBindMenuReqVo();
        if (Objects.isNull(reqVo.getIsManage()) || !reqVo.getIsManage()) {
            roleBindMenuReqVo.setRoleId(roleId);
        }
        roleBindMenuReqVo.setEntId(kwsDept.getEntId());
        roleBindMenuReqVo.setMenuIds(reqVo.getMenuIds());
        kwsMenuService.roleBindMenu(roleBindMenuReqVo);

        /*3、设置数据权限*/
        if (reqVo.getVisiblePersonal()) {
            //只能看见自己的数据则不管
            return idResVo;
        }

        String deptIds = reqVo.getDeptIds();
        if (StringUtils.isBlank(deptIds)) {
            return idResVo;
        }

        saveAuthority(roleId, deptIds);

        return idResVo;
    }

    /**
     * @param roleId 角色id  deptIds能访问的机构数据id
     * @desc: 存数据权限
     * @author: czh
     * @date: 2023/8/16
     */
    private void saveAuthority(Long roleId, String deptIds) {
        String[] deptIdArr = deptIds.split(",");
        List<KwsAuthority> kwsAuthorities = new ArrayList<>();
        Long userId = LoginUserHolder.getUserId();
        Date date = new Date();
        for (String deptId : deptIdArr) {
            KwsAuthority kwsAuthority = new KwsAuthority();
            kwsAuthority.setRoleId(roleId);
            kwsAuthority.setDeptId(Long.parseLong(deptId));
            kwsAuthority.setId(new IdWorker(1L).nextId());
            kwsAuthority.setStatus(Global.NO);
            kwsAuthority.setCreateBy(userId);
            kwsAuthority.setCreateTime(date);
            kwsAuthority.setUpdateBy(userId);
            kwsAuthority.setUpdateTime(date);
            kwsAuthority.setDelFlag(Global.NO);
            kwsAuthorities.add(kwsAuthority);
        }
        if (kwsAuthorityDao.saveBatch(kwsAuthorities) != kwsAuthorities.size()) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }

    /**
     * @param unitIdList 企业/机构id集合
     * @desc: 根据机构删除角色信息
     * @author: czh
     * @date: 2023/6/25
     */
    public void deleteByDeptIds(List<Long> unitIdList) {
        List<KwsRole> kwsRoles = kwsRoleDao.selectBatchByUnitIds(unitIdList);
        if (CollectionUtils.isEmpty(kwsRoles)) {
            return;
        }
        deleteRole(kwsRoles);
    }

    /**
     * 删除记录-根据主键
     *
     * @param ids 主键
     */
    public void deleteByKey(String ids) {
        List<Long> idList = Arrays.stream(ids.split(",")).map(Long::parseLong).toList();
        List<KwsRole> kwsRoles = kwsRoleDao.selectBatchByKeys(idList);
        if (CollectionUtils.isEmpty(kwsRoles)) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }

        List<KwsUser> kwsUsers = kwsUserDao.selectByRoleIds(idList);
        if (CollectionUtils.isNotEmpty(kwsUsers)) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.MSG_011);
        }
        deleteRole(kwsRoles);
    }

    /**
     * @param kwsRoles 角色实体类集合
     * @desc: 删角色
     * @author: czh
     * @date: 2023/6/28
     */
    @Transactional(rollbackFor = {})
    public void deleteRole(List<KwsRole> kwsRoles) {
        /*1、删角色*/
        for (KwsRole kwsRole : kwsRoles) {
            kwsRole.setDelFlag(Global.YES);
            if (kwsRoleDao.update(kwsRole) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
            }
        }

        /*2、删用户角色关系*/
        List<Long> idList = kwsRoles.stream().map(KwsRole::getId).toList();
        List<KwsUserRole> kwsUserRoleList = kwsUserRoleDao.findAllByRoleIds(idList);
        if (CollectionUtils.isEmpty(kwsUserRoleList)) {
            return;
        }

        for (KwsUserRole kwsUserRole : kwsUserRoleList) {
            kwsUserRole.setDelFlag(Global.YES);
            if (kwsUserRoleDao.update(kwsUserRole) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
            }
        }

        /*3、删除角色菜单关系*/
        kwsMenuService.deleteMenuRightsByRoleIds(idList);

        //让涉及到的用户重新登录获取菜单权限
        for (KwsUserRole kwsUserRole : kwsUserRoleList) {
            Long userId = kwsUserRole.getUserId();
            RedissonUtils.deleteBactch(Global.REDIS_USER_LOGIN_PREFIX + userId + Global.ASTERISK1);
        }
    }

    /**
     * 更新记录
     */
    @Transactional(rollbackFor = {})
    public void update(EditRoleReqVo reqVo) {
        KwsRole kwsRole = kwsRoleDao.selectByKey(reqVo.getId());
        if (Objects.isNull(kwsRole)) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }

        List<KwsMenuRights> kwsMenuRightsList = kwsMenuRightsDao.selectByRoleIds(Collections.singletonList(kwsRole.getId()));
        if (CollectionUtils.isNotEmpty(kwsMenuRightsList)) {
            for (KwsMenuRights kwsMenuRights : kwsMenuRightsList) {
                kwsMenuRights.setDelFlag(Global.YES);
                if (kwsMenuRightsDao.update(kwsMenuRights) <= 0) {
                    throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
                }
            }
        }
        //删除kws_authority表数据
        List<KwsAuthority> kwsAuthorityList = kwsAuthorityDao.selectByRoleIds(Collections.singletonList(kwsRole.getId()));
        if (CollectionUtils.isNotEmpty(kwsAuthorityList)) {
            for (KwsAuthority kwsAuthority : kwsAuthorityList) {
                kwsAuthority.setDelFlag(Global.YES);
                if (kwsAuthorityDao.update(kwsAuthority) <= 0) {
                    throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
                }
            }
        }

        KwsDept kwsDept = kwsDeptDao.selectByKey(kwsRole.getDeptId());

        RoleBindMenuReqVo roleBindMenuReqVo = new RoleBindMenuReqVo();
        roleBindMenuReqVo.setRoleId(kwsRole.getId());
        roleBindMenuReqVo.setEntId(kwsDept.getEntId());
        roleBindMenuReqVo.setMenuIds(reqVo.getMenuIds());
        kwsMenuService.roleBindMenu(roleBindMenuReqVo);
        //修改权限名称与备注信息
        KwsRole kwsRoleTable = new KwsRole();
        kwsRoleTable.setId(reqVo.getId());
        kwsRoleTable.setName(reqVo.getName());
        kwsRoleTable.setRemark(reqVo.getRemark());
        if (kwsRoleDao.update(kwsRoleTable) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
        if(StringUtils.isNotBlank(reqVo.getDeptIds())){
            saveAuthority(reqVo.getId(), reqVo.getDeptIds());
        }

//        List<KwsUser> kwsUsers = kwsUserDao.selectByRoleIds(Collections.singletonList(reqVo.getId()));
//
//        //删除以前的角色
//        deleteRole(Collections.singletonList(kwsRole));
//
//        //新增
//        add(reqVo);
//
//        //重新绑定以前的员工
//        if (CollectionUtils.isEmpty(kwsUsers)) {
//            return;
//        }

//        for (KwsUser kwsUser : kwsUsers) {
//            UserBindRoleReqVo userBindRoleReqVo = new UserBindRoleReqVo();
//            userBindRoleReqVo.setUserId(kwsUser.getId());
//            userBindRoleReqVo.setRoleIds(String.valueOf(reqVo.getId()));
//            userBindRoleReqVo.setSystemType(LoginUserHolder.getSystemType());
//            userBindRoleReqVo.setRemark("");
//            userBindRole(userBindRoleReqVo);
//        }
    }

    /**
     * 根据主键查询
     *
     * @param key 主键
     * @return KwsRole
     */
    public KwsRole selectByKey(Long key) {
        return kwsRoleDao.selectByKey(key);
    }

    /**
     * 分页查询
     * @param params 分页入参
     * @return List
     */
    public PageResult findPage(Map<String, Object> params) {
        PageHelper.startPage(PageResult.getPage(params), PageResult.getPageSize(params));
        FindManagePojo manageInfoByEntId = kwsEnterpriseDao.findManageInfoByEntId(LoginUserHolder.getEntId());
        params.put("entId", LoginUserHolder.getEntId());
        params.put("manageRoleId", manageInfoByEntId.getRoleId());
        List<RoleResVo> roleResVos = kwsRoleDao.findPage(params);
        if (CollectionUtils.isEmpty(roleResVos)) {
            return PageHelperUtil.getPageResult(new PageInfo<>(roleResVos));
        }

        List<Long> roleIdList = roleResVos.stream().map(RoleResVo::getId).toList();
        List<KwsAuthority> kwsAuthorities = kwsAuthorityDao.selectByRoleIds(roleIdList);
        if (CollectionUtils.isNotEmpty(kwsAuthorities)) {
            Map<Long, List<KwsAuthority>> collectKwsAuthority = kwsAuthorities.stream().collect(Collectors.groupingBy(KwsAuthority::getRoleId));
            roleResVos.forEach(item -> {
                List<KwsAuthority> kwsAuthorityList = collectKwsAuthority.get(item.getId());
                if (CollectionUtils.isNotEmpty(kwsAuthorityList)) {
                    item.setDeptIds(String.join(Global.COMMA, kwsAuthorityList.stream().map(KwsAuthority::getDeptId).map(String::valueOf).toList()));
                }
            });
        }

        List<KwsMenuRights> kwsMenuRights = kwsMenuRightsDao.selectByRoleIds(roleIdList);
        if (CollectionUtils.isNotEmpty(kwsMenuRights)) {
            List<Long> menuIdList = kwsMenuRights.stream().map(KwsMenuRights::getMenuId).toList();
            List<KwsMenu> kwsMenus = kwsMenuDao.selectByKeys(menuIdList);
            List<Long> longs = kwsMenus.stream().map(KwsMenu::getParentId).toList();
            //获取最后一级的菜单或者按钮
            List<Long> collect = kwsMenus.stream().map(KwsMenu::getId).filter(id -> !longs.contains(id)).toList();
            kwsMenuRights = kwsMenuRights.stream().filter(item -> collect.contains(item.getMenuId())).toList();
            Map<Long, List<KwsMenuRights>> collectKwsMenuRights = kwsMenuRights.stream().collect(Collectors.groupingBy(KwsMenuRights::getRoleId));
            roleResVos.forEach(item -> {
                List<KwsMenuRights> kwsMenuRightsList = collectKwsMenuRights.get(item.getId());
                if (CollectionUtils.isNotEmpty(kwsMenuRightsList)) {
                    item.setMenuIds(String.join(Global.COMMA, kwsMenuRightsList.stream().map(KwsMenuRights::getMenuId).map(String::valueOf).toList()));
                }
            });
        }
        return PageHelperUtil.getPageResult(new PageInfo<>(roleResVos), roleResVos, PageResult.getPageSize(params));
    }

    /**
     * @param userId 用户id
     * @return List
     * @desc: 根据用户id查角色
     * @author: czh
     * @date: 2023/6/12
     */
    public List<KwsRole> queryRoleByUserId(Long userId) {
        return kwsRoleDao.queryRoleByUserId(userId);
    }

    /**
     * @param reqVo 多个角色用","隔开
     * @desc: 用戶分配權限
     * @author: czh
     * @date: 2023/6/13
     */
    @Transactional(rollbackFor = Exception.class)
    public void userBindRole(UserBindRoleReqVo reqVo) {
        //特殊校验，之前说用户和角色是一对多，后来产品改成一对一
        String[] roleIdArr = reqVo.getRoleIds().split(Global.COMMA);
        if (isBindManyRole.equals(Global.NO) && roleIdArr.length > 1) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.MSG_006);
        }

        /*1、若有数据则先置为删除状态*/
        extracted(reqVo);

        /*2、存用户角色信息*/
        List<KwsUserRole> kwsUserRolelist = new ArrayList<>();
        Date date = new Date();
        Long currentUserId = LoginUserHolder.getUserId();
        long userId = reqVo.getUserId();
        List<Long> roleIdList = new ArrayList<>();
        for (String roleId : roleIdArr) {
            KwsUserRole kwsUserRole = new KwsUserRole();
            kwsUserRole.setUserId(userId);
            kwsUserRole.setRoleId(Long.parseLong(roleId));
            kwsUserRole.setRemark(reqVo.getRemark());
            kwsUserRole.setId(new IdWorker(1).nextId());
            kwsUserRole.setCreateTime(date);
            kwsUserRole.setCreateBy(currentUserId);
            kwsUserRole.setUpdateTime(date);
            kwsUserRole.setUpdateBy(currentUserId);
            kwsUserRole.setStatus(Global.NO);
            kwsUserRole.setDelFlag(Global.NO);
            kwsUserRolelist.add(kwsUserRole);
            roleIdList.add(Long.parseLong(roleId));
        }
        if (kwsUserRoleDao.saveBatch(kwsUserRolelist) < kwsUserRolelist.size()) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }

        /*3、后置处理，修改redis中的信息*/
        FindMenuTreePojo findMenuTreePojo = new FindMenuTreePojo();
        findMenuTreePojo.setRoleIds(roleIdList);
        List<KwsMenuResVo> kwsMenuResVos = kwsMenuService.findList(findMenuTreePojo);
        if (CollectionUtils.isEmpty(kwsMenuResVos)) {
            return;
        }

        List<String> menus = new ArrayList<>();
        for (KwsMenuResVo kwsMenuResVo : kwsMenuResVos) {
            String links = kwsMenuResVo.getLinks();
            if (StringUtils.isNotBlank(links)) {
                menus.addAll(Arrays.asList(kwsMenuResVo.getLinks().split(",")));
            }
        }
        RedissonUtils.putSet(Global.getFullUserMenuKey(reqVo.getSystemType(), userId), menus);
        RedissonUtils.deleteBactch(Global.REDIS_USER_LOGIN_PREFIX + userId + "*");

    }

    private void extracted(UserBindRoleReqVo reqVo) {
        List<KwsUserRole> currentUserRoleList = kwsUserRoleDao.findAllByUserId(reqVo.getUserId());
        if (!CollectionUtils.isEmpty(currentUserRoleList)) {
            for (KwsUserRole kwsUserRole : currentUserRoleList) {
                kwsUserRole.setDelFlag(Global.YES);
                if (kwsUserRoleDao.update(kwsUserRole) <= 0) {
                    throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
                }
            }
        }

    }

    public List<KwsUserRole> findAllByUserId(long userId) {
        return kwsUserRoleDao.findAllByUserId(userId);
    }



    public void export(HashMap params, HttpServletResponse response) {
        FindManagePojo manageInfoByEntId = kwsEnterpriseDao.findManageInfoByEntId(LoginUserHolder.getEntId());
        params.put("entId", LoginUserHolder.getEntId());
        params.put("manageRoleId", manageInfoByEntId.getRoleId());
        String ids = StringUtils.valueOf(params.get("ids"));
        if (StringUtils.isNotBlank(ids)) {
            params.put("idList", StringUtils.splitStrToList(ids, Long.class));
        }
        List<RoleResVo> roleResVos = kwsRoleDao.findPage(params);
        if (CollectionUtils.isEmpty(roleResVos)) {
            throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
        }
        ExcelUtil.downData(response, KwsRoleExcel.class, BeanUtils.copyToList(roleResVos, KwsRoleExcel.class));
    }
}