package com.sunxung.factoring.service.sys.impl;

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

import com.github.pagehelper.Page;
import com.sunxung.factoring.component.util.ThreadLocalUtil;
import com.sunxung.factoring.entity.sys.vo.GradationVo;
import com.sunxung.factoring.entity.sys.vo.SysGradationVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageHelper;
import com.sunxung.factoring.component.cache.CacheKeyGenerator;
import com.sunxung.factoring.component.cache.RedisCache;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.CodeUtil;
import com.sunxung.factoring.component.util.ConstantConversionUtil;
import com.sunxung.factoring.component.util.ValidatorUtil;
import com.sunxung.factoring.entity.GridPage;
import com.sunxung.factoring.entity.ValidatorEntity.ValidatorType;
import com.sunxung.factoring.entity.sys.Permission;
import com.sunxung.factoring.entity.sys.Role;
import com.sunxung.factoring.entity.sys.RolePermissionRel;
import com.sunxung.factoring.entity.sys.User;
import com.sunxung.factoring.entity.sys.UserRoleRel;
import com.sunxung.factoring.entity.sys.vo.SearchRoleanization;
import com.sunxung.factoring.mapper.sys.RoleMapper;
import com.sunxung.factoring.service.sys.PermissionService;
import com.sunxung.factoring.service.sys.RoleService;
import com.sunxung.factoring.service.sys.UserService;

/**
 * @Description:系统角色业务层实现类
 * @Author:JingJiang
 * @E-mail:254702920@qq.com
 * @Date:2017年6月6日 下午6:30:20
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private UserService userService;
    @Autowired
    RedisCache redisCache;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Role add(Role role) {
        ValidatorUtil.validator(ValidatorType.ADD, role);
        roleMapper.add(role);
        addRolePermissionRel(role.getId(), role.getPermissions());
        return get(role.getId());
    }

    /**
     * 新增角色与权限的关系
     *
     * @param roleId      角色ID
     * @param permissions 权限ID
     */
    private void addRolePermissionRel(Long roleId, List<Permission> permissions) {
        if (permissions == null || permissions.size() == 0) {
            return;
        }
        for (Permission per : permissions) {
            if (null != per && null != per.getId()) {
                roleMapper.addRolePermissionRel(new RolePermissionRel(roleId, per.getId()));
            }
        }
    }

    private void findNodesByRoleIdPermissionId(Long roleId, Long parentId) {
        List<Long> listNodes = permissionService.findNodesByRoleIdPermissionId(parentId, roleId);
        if (listNodes != null && listNodes.size() > 0) {
            for (int i = 0; i < listNodes.size(); i++) {
                permissionService.deleteRolePermissionRel(listNodes.get(i), roleId);
                findNodesByRoleIdPermissionId(roleId, listNodes.get(i));
            }
        }
    }

    /**
     * 更新角色与权限的关系
     *
     * @param roleId      角色ID
     * @param permissions 权限的List
     */
    private void updateRolePermissionRel(Long roleId, List<Permission> permissions) {
        if (null != permissions && permissions.size() > 0) {
            permissionService.deleteRolePermissionRel(null, roleId);
            for (Permission permission : permissions) {
                Long permissionId = permission.getId();
                roleMapper.addRolePermissionRel(new RolePermissionRel(roleId, permissionId));
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Role update(Role role) {
        ValidatorUtil.validator(ValidatorType.UPDATE, role);
        roleMapper.update(role);
        Role ro = roleMapper.get(role.getId());
        cacheRole(ro);
        updateRolePermissionRel(role.getId(), role.getPermissions());
        return get(role.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        List<Long> del = getUserIdByRoleId(Long.valueOf(id));
        if (null != del && del.size() > 0) {
            throw new ValidatorException(CodeUtil.FAIL, "当前角色下有用户，不可删除！请先移除用户");
        }
        Role role = roleMapper.get(id);
        List<Role> roleList = roleMapper.findByParentRoleId(id);
        if (null != roleList && roleList.size() > 0) {
            throw new ValidatorException(CodeUtil.FAIL, "当前角色下有子角色，不可删除！请先删除子角色");
        }
        if (role != null) {
            redisCache.remove(CacheKeyGenerator.generateCacheKeyFromId(Role.class, id));
            roleMapper.deleteByRoleId(id);
            return roleMapper.delete(id) > 0;
        }
        return false;
    }

    @Override
    public Role get(Long id) {
        Role role = (Role) redisCache.get(CacheKeyGenerator.generateCacheKeyFromId(Role.class, id));
        if (role == null) {
            role = roleMapper.get(id);
            cacheRole(role);
        }
        return role;
    }

    @Override
    public Role getDetail(Long id) {
        Role role = (Role) redisCache.get(CacheKeyGenerator.generateCacheKeyFromId(Role.class, id));
        if (role == null) {
            role = roleMapper.get(id);
            cacheRole(role);
        }
        autoPermissions(role);
        return role;
    }

    @Override
    public GridPage<Role> findBySearch(SearchRoleanization search) {
        List<Role> list = new ArrayList<Role>();
        Page<Object> objects = PageHelper.startPage(search.getPage(), search.getRows());
        list = roleMapper.findBySearch(search);
        for (Role role : list) {
            List<Role> childList = roleMapper.findByParentRoleId(role.getId());
            role.setChildList(childList);
        }
        return new GridPage<Role>(search.getRows(), search.getPage(), objects.getTotal(), list);
    }

    @Override
    public Role getByRoleName(String name) {
        return roleMapper.getByRoleName(name);
    }

    @Override
    public boolean validateAdd(String name) {
        Role role = getByRoleName(name);
        if (role != null) {
            return false;
        }
        return true;
    }

    @Override
    public boolean validateUpdate(String name, Long roleId) {
        Role role = getByRoleName(name);
        String rolename = get(roleId).getName();
        if (role != null && !rolename.equals(role.getName())) {
            return false;
        }
        return true;
    }

    @Override
    public List<Role> findAll() {
        return roleMapper.findAll();
    }

    @Override
    public List<Long> getUserIdByRoleId(Long roleId) {
        return roleMapper.getUserIdByRoleId(roleId);
    }

    @Override
    public Long getAdminUserId(Long roleId) {
        return roleMapper.getAdminUserId(roleId, true);
    }

    @Override
    public boolean isRoleAdminExist(Long roleId) {
        return null != getAdminUserId(roleId);
    }

    @Override
    public List<Role> findByOrgId(Long orgId) {
        return roleMapper.findByOrgId(orgId);
    }

    /**
     * 根据roleId获取缓存中的role信息
     *
     * @param roleId
     * @return
     */
    public Role getRedisByRoleId(Long roleId) {
        Role role = (Role) redisCache.get(CacheKeyGenerator.generateCacheKeyFromId(Role.class, roleId));
        return role;
    }

    /**
     * 缓存role
     *
     * @param role
     */
    private void cacheRole(Role role) {
        if (role != null) {
            String cacheKey = CacheKeyGenerator.generateCacheKeyFromId(Role.class, role.getId());
            redisCache.set(cacheKey, role);
        }
    }

    @Override
    public List<Long> findPermissionIdByRoleId(Long roleId) {
        return roleMapper.findPermissionIdByRoleId(roleId);
    }

    @Override
    public List<Long> getAllPermissionId() {
        return roleMapper.getAllPermissionId();
    }

    @Override
    public List<Long> getRootIdByRoleId(Long roleId) {
        return roleMapper.getRootIdByRoleId(roleId);
    }

    @Override
    public List<Long> getNodeIdByRoleId(Long roleId) {
        return roleMapper.getNodeIdByRoleId(roleId);
    }

    @Override
    public Long isChecked(Long roleId, Long permissionId) {
        return roleMapper.isChecked(roleId, permissionId);
    }

    @Override
    public List<UserRoleRel> getUserRoleByUserId(Long userId) {
        return roleMapper.getUserRoleByUserId(userId);
    }

    @Override
    public boolean deletes(String[] ids) {
        if (null == ids || ids.length < 1) {
            throw new ValidatorException(CodeUtil.FAIL, "请选择删除的数据");
        }
        for (String id : ids) {
            Long roleId = Long.valueOf(id);
            List<Long> del = getUserIdByRoleId(roleId);
            if (del.size() > 0) {
                throw new ValidatorException(CodeUtil.FAIL, "当前角色下有用户，不可删除！请先移除用户");
            }
            List<Role> roleList = roleMapper.findByParentRoleId(roleId);
            if (null != roleList && roleList.size() > 0) {
                throw new ValidatorException(CodeUtil.FAIL, "当前角色下有子角色，不可删除！请先删除子角色");
            }
        }
        boolean flag = true;
        for (String id : ids) {
            flag = delete(Long.valueOf(id));
            if (!flag) {
                return flag;
            }
        }
        return flag;
    }

    @Override
    public List<Role> findGroupRole() {
        return roleMapper.findGroupRole();
    }

    @Override
    public boolean addUserRole(Long roleId, String[] userIds) {
        boolean b = false;
        if (null == roleId || userIds.length == 0) {
            throw new ValidatorException(CodeUtil.FAIL, "参数不正确，请检查参数");
        }
        Role adminRole = getByRoleName(ConstantConversionUtil.ADMINISTORIES_DISPLAYNAME);
        Role childRole = getByRoleName(ConstantConversionUtil.CHILD_ADMINISTORIES_DISPLAYNAME);
        if (null != adminRole && adminRole.getId().equals(roleId)) {
            UserRoleRel userRoleRel = userService.getRoleRelByRoleId(roleId, null);
            if (null != userRoleRel) {
                throw new ValidatorException(CodeUtil.FAIL,
                        "该" + ConstantConversionUtil.ADMINISTORIES_DISPLAYNAME + "角色下已经存在用户，不能再添加了");
            }
        }
        boolean admin = false;
        if (null != adminRole && null != childRole) {
            if (adminRole.getId() == roleId || childRole.getId() == roleId) {
                admin = true;
            }
        }
        for (String idStr : userIds) {
            Long userId = Long.valueOf(idStr);
            UserRoleRel userRoleRel = new UserRoleRel();
            userRoleRel.setUserId(userId);
            userRoleRel.setRoleId(roleId);
            userRoleRel.setAdmin(admin);
            UserRoleRel userRoleRelRel = userService.getRoleRelByRoleId(roleId, userId);
            if (null == userRoleRelRel) {
                userService.addUserRoleRel(userRoleRel);
                b = true;
            }
        }
        return b;
    }

    @Override
    public List<Role> findByParentRoleId(Long parentRoleId) {
        return roleMapper.findByParentRoleId(parentRoleId);
    }

    @Override
    public boolean removeUserRole(Long roleId, String[] userIds) {
        boolean b = false;
        if (null == roleId || userIds.length == 0) {
            throw new ValidatorException(CodeUtil.FAIL, "参数不正确，请检查参数");
        }
        for (String idStr : userIds) {
            Long userId = Long.valueOf(idStr);
            b = roleMapper.deleteUserRole(userId, roleId) >= 0;
        }
        return b;
    }

    @Override
    public boolean judgmentAdmin(Long userId) {
        Role role = getByRoleName(ConstantConversionUtil.ADMINISTORIES_DISPLAYNAME);
        if (null != role) {
            UserRoleRel userRoleRel = roleMapper.getByUserRole(userId, role.getId());
            if (null != userRoleRel) {
                return true;
            }
        }
        return false;
    }

    @Override
    @Transactional
    public boolean adjustOrder(SysGradationVo sysVo) {
        boolean b = false;
        if (null != sysVo && null != sysVo.getList() && sysVo.getList().size() > 0) {
            for (GradationVo vo : sysVo.getList()) {
                if (null != vo.getRoleId()) {
                    b = roleMapper.adjustOrder(vo.getRoleId(), vo.getGradation(), vo.getUserId()) > 0;
                }
            }
        }
        return b;
    }

    @Override
    public List<Role> getRoleListByUseId() {
        Long userId = ThreadLocalUtil.getUserId();
        return roleMapper.getRoleListByUseId(userId);
    }

    private void autoPermissions(Role role) {
        List<Permission> permissionList = new ArrayList<>();
        if (null != role && null != role.getId()) {
            List<Long> list = permissionService.getPermissionIdByRoleId(role.getId());
            if (null != list && list.size() > 0) {
                for (Long pid : list) {
                    Permission permission = permissionService.get(pid);
                    if (null != permission) {
                        permissionList.add(permission);
                    }
                }
            }
            role.setPermissions(permissionList);
        }
    }
}
