package cn.estsh.i3plus.core.apiservice.serviceimpl.busi;

import cn.estsh.i3plus.core.api.iservice.busi.IPersonnelService;
import cn.estsh.i3plus.core.api.iservice.busi.ISysRoleService;
import cn.estsh.i3plus.core.apiservice.dao.IUserPermissionDao;
import cn.estsh.i3plus.pojo.base.bean.ListPager;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.common.PagerHelper;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.HqlPack;
import cn.estsh.i3plus.pojo.platform.bean.*;
import cn.estsh.i3plus.pojo.platform.repository.SysMenuRepository;
import cn.estsh.i3plus.pojo.platform.repository.SysRefRoleMenuRepository;
import cn.estsh.i3plus.pojo.platform.repository.SysRoleRepository;
import cn.estsh.i3plus.pojo.platform.sqlpack.CoreHqlPack;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import cn.estsh.impp.framework.boot.exception.ImppExceptionEnum;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description : 系统角色业务接口实现
 * @Reference   :
 * @Author      : wei.peng
 * @Date        : 2018-10-22 16:58:43.779
 * @Modify      :
 **/
@Service
public class SysRoleService implements ISysRoleService {

    public static final Logger LOGGER = LoggerFactory.getLogger(SysRoleService.class);

    @Autowired
    private SysRoleRepository roleRDao;

    @Autowired
    private SysMenuRepository sysMenuRDao;

    @Autowired
    private SysRefRoleMenuRepository refRoleMenuRDao;

    @Autowired
    private IPersonnelService personnelService;

    @Autowired
    private IUserPermissionDao userPermissionDao;

    @Override
    @ApiOperation(value = "更新角色信息",notes = "更新角色信息")
    public void updateSysRole(SysRole sysRole) {
        LOGGER.info("系统角色 SYS_ROLE :{}", sysRole);
        roleRDao.update(sysRole);
        // 更新冗余信息
        personnelService.refreshUpdateSysRoleRdd(sysRole.getId());
    }

    @Override
    @ApiOperation(value = "更新角色信息",notes = "更新角色状态信息")
    public void updateSysRoleStatus(Long id, int status, SessionUser user) {
        LOGGER.info("系统角色 SYS_MENU  id:{} status:{} user:{}", id,status,user);
        SysRole role = roleRDao.getById(id);
        role.setRoleStatus(status);
        role.setModifyUser(user.getUserName());
        roleRDao.update(role);
    }

    @Override
    @ApiOperation(value = "更新角色信息",notes = "根据ID 批量更新角色状态信息")
    public void updateSysRoleStatusByIds(Long[] ids, int status, SessionUser user) {
        LOGGER.info("系统功能 SYS_MENU  ids:{}  status:{} user:{}", ids, status, user);
        StringBuffer where = new StringBuffer();

        HqlPack.getInPack(StringUtils.join( ids,","), "id", where);
        roleRDao.updateByHqlWhere(where.toString(), "roleStatus", status);
    }

    @Override
    @ApiOperation(value = "删除角色信息",notes = "根据ID 删除角色信息")
    public void deleteSysRoleById(Long id) {
        LOGGER.info("系统角色 SYS_ROLE Key:{}", id);
        refRoleMenuRDao.deleteByProperty("roleId",id);
        roleRDao.deleteById(id);
    }

    @Override
    @ApiOperation(value = "删除角色信息",notes = "根据ID 批量删除角色信息")
    public void deleteSysRoleByIds(Long[] ids) {
        LOGGER.info("系统角色 SYS_ROLE ids :{}", ids);
        long positionCount = roleRDao.findByHqlWhereCount(CoreHqlPack.packHqlIds("parentId",ids));
        if (positionCount >= 1) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("存在相关系统功能信息无法删除！")
                    .setErrorSolution("请先删除子集信息在操作")
                    .build();
        }else {
            refRoleMenuRDao.deleteByPropertyIn("roleId",ids);
            roleRDao.deleteByIds(ids);
        }
    }

    @Override
    @ApiOperation(value = "新增角色信息")
    public SysRole insertSysRole(SysRole sysRole) {
        LOGGER.info("系统角色 SYS_ROLE :{}", sysRole);
        return roleRDao.insert(sysRole);
    }

    @Override
    @ApiOperation(value = "刷新角色菜单关系",notes = "刷新 角色 菜单关系信息")
    public void refreshSysRoleRef(Long roleId,Long[] ids,String userName) {
        LOGGER.info("系统角色 SYS_ROLE :{}", roleId);
        LOGGER.info("系统角色 List<SysMenu> :{}", ids);

        refreshBatchSysRoleRef(new Long[]{roleId}, ids, userName);
    }

    @Override
    @ApiOperation(value = "刷新角色菜单关系",notes = "批量刷新 角色 菜单关系信息")
    public void refreshBatchSysRoleRef(Long[] roleIds, Long[] ids,String userName) {
        LOGGER.info("系统角色 String[] :{}", roleIds);
        LOGGER.info("系统角色 List<SysMenu> :{}", ids);

        String roleWhere = CoreHqlPack.packHqlIds("id", roleIds);
        List<SysRole> roleList = roleRDao.findByHqlWhere(roleWhere);

        if(roleList != null && roleList.size() > 0){
            List<String> moduleListRdd = new ArrayList<>();
            List<String> featuresListRdd = new ArrayList<>();           // 冗余
            List<SysRefRoleMenu> refs = new ArrayList<>();                 // 角色权限关系

            // 封装需要删除的IDS
            Long[] rids = new Long[roleList.size()];
            for (int i = 0; i < roleList.size(); i++) {
                rids[i] = roleList.get(i).getId();
            }
            // 删除角色权限关系
            String deleteWhere = CoreHqlPack.packHqlIds("roleId", roleIds);
            List<SysRefRoleMenu> refRoleMenuList = refRoleMenuRDao.findByHqlWhere(deleteWhere);
            refRoleMenuRDao.deleteAll(refRoleMenuList);

            if(ids != null && ids.length > 0){
                String menuWhere = CoreHqlPack.packHqlIds("id", ids);
                List<SysMenu> list = sysMenuRDao.findByHqlWhere(menuWhere);
                SysRefRoleMenu ref = null;

                // 插入角色权限关系
                if(list != null && list.size() > 0){
                    for (SysMenu menu : list) {
                        for (SysRole role : roleList) {
                            ref = new SysRefRoleMenu();
                            ref.setRoleId(role.getId());
                            ref.setRoleNameRdd(role.getName());
                            ref.setMenuNameRdd(menu.getName());
                            ref.setMenuId(menu.getId());
                            ref.setIsValid(CommonEnumUtil.IS_VAILD.VAILD.getValue());
                            ref.setMenuTypeRdd(menu.getMenuType());

                            refs.add(ref);
                        }

                        // 冗余信息封装
                        if(CommonEnumUtil.METHOD_LEVEL.MODULE.getValue() == menu.getMenuType().intValue()){
                            moduleListRdd.add(menu.getName());
                        }
                        if(CommonEnumUtil.METHOD_LEVEL.METHOD.getValue() == menu.getMenuType().intValue()){
                            featuresListRdd.add(menu.getName());
                        }
                    }
                }
            }

            // 冗余信息
            for (SysRole role : roleList) {
                role.setModuleNumber(moduleListRdd.size());
                role.setModuleNamesRdd(String.join(",",moduleListRdd));

                role.setMenuNumber(featuresListRdd.size());
                role.setMenuNamesRdd(String.join(",",featuresListRdd));

//                ConvertBean.serviceModelUpdate(role,userName);
            }

            refRoleMenuRDao.saveAll(refs);
            roleRDao.saveAll(roleList);
        }else {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("角色信息不存在")
                    .setErrorSolution("请重新输入")
                    .build();
        }
    }

    @Override
    @ApiOperation(value = "查信角色菜单关系",notes = "查询 ID 查询角色菜单关系")
    public List<SysRefRoleMenu> findSysRefRoleMenuByRoleId(Long roleId) {
        LOGGER.info("系统角色权限关系 RefRoleMenu find By RoleId");
        return refRoleMenuRDao.findByProperty(
                new String[]{"roleId","isValid"},
                new Object[]{roleId,CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()}
                );
    }

    @Override
    @ApiOperation(value = "查信角色信息",notes = "查询所有角色信息")
    public List<SysRole> findSysRoleAll() {
        LOGGER.info("系统角色 SYS_ROLE find All");
        return roleRDao.findByProperty(new String[]{"roleStatus"},new Object[]{CommonEnumUtil.DATA_STATUS.ENABLE.getValue()});
    }

    @Override
    @ApiOperation(value = "查信角色信息",notes = "查询指定角色信息")
    public List<SysRole> findSysRoleByInId(Long[] ids) {
        LOGGER.info("系统角色 SYS_ROLE find In Id");
        StringBuffer findWhere = new StringBuffer();
        HqlPack.getInPack(StringUtils.join(ids,","),"id",findWhere);
        return roleRDao.findByHqlWhere(findWhere.toString());
    }

    @Override
    public List<SysRole> findSysRoleByInIdAndStatus(Long[] ids, Integer status) {
        LOGGER.info("系统角色 SYS_ROLE findSysRoleByInIdAndStatus ids:{} , status:{}",ids,status);
        StringBuffer findWhere = new StringBuffer();
        HqlPack.getInPack(StringUtils.join(ids,","),"id",findWhere);
        HqlPack.getNumEqualPack(status,"roleStatus",findWhere);
        return roleRDao.findByHqlWhere(findWhere.toString());
    }

    @Override
    @ApiOperation(value = "查信用户的所有角色信息",notes = "查信用户的所有角色信息")
    public List<SysRole> findSysRoleByUser(SysUser user) {
        LOGGER.info("系统角色 查询用户所有角色");
        return userPermissionDao.findSysRoleByUser(user);
    }

    @Override
    @ApiOperation(value = "查信角色信息",notes = "根据 ID 查询角色信息")
    public SysRole getSysRoleById(Long  id) {
        LOGGER.info("系统角色 SYS_ROLE find id:{}", id);
        return roleRDao.getOne(id);
    }

    @Override
    @ApiOperation(value = "查信角色信息",notes = "查询角色信息(分页/组合)")
    public ListPager<SysRole> querySysRole(SysRole role, Pager pager) {
        LOGGER.info("系统角色 SysRole find role :{} page :{}", role, pager);

        if (role == null) {
            //不传入实体对象，查询所有
            int count = roleRDao.listCount();
            pager = PagerHelper.getPager(pager, count);
            return new ListPager(roleRDao.listPager(pager), pager);
        } else {
            //生成hql查询语句
            String hqlPack = CoreHqlPack.packHqlSysRole(role);
            pager = PagerHelper.getPager(pager, roleRDao.findByHqlWhereCount(hqlPack));
            return new ListPager(roleRDao.findByHqlWherePage(hqlPack + role.orderBy(), pager), pager);
        }
    }

    @Override
    public void checkSysRoleOnly(SysRole role) {
        if(role != null){
            // 登录名唯一教研
            if(!checkSysRoleName(role.getName(), role.getId() == null ? 0 : role.getId())){
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_EXIT.getCode())
                        .setErrorDetail("用户名已存在")
                        .setErrorSolution("请重新输入用户名")
                        .build();
            }
        }
    }


    /**
     * 登录名 唯一检查
     * @param roleName
     * @param roleId
     * @return
     */
    private boolean checkSysRoleName(String roleName, long roleId) {
        int count = 0;
        if(roleId > 0){
            StringBuffer sw = new StringBuffer();
            HqlPack.getNumEqualPack(CommonEnumUtil.IS_VAILD.VAILD.getValue(),"isValid",sw);
            HqlPack.getStringEqualPack(roleName,"name",sw);
            HqlPack.getNumNOEqualPack(roleId,"id",sw);
            count = roleRDao.findByHqlWhereCount(sw.toString());
        }else{
            count = roleRDao.findByPropertyCount(
                    new String[]{"name","isValid"},
                    new Object[]{roleName,CommonEnumUtil.IS_VAILD.VAILD.getValue()});
        }
        return count <= 0 ;
    }
}
