package cn.com.ty.lift.system.user.service.impl;

import cn.com.ty.lift.common.constants.ApiConstants;
import cn.com.ty.lift.common.constants.DefaultMenuConstants;
import cn.com.ty.lift.common.utils.ProjectUtils;
import cn.com.ty.lift.system.user.dao.entity.*;
import cn.com.ty.lift.system.user.dao.entity.model.RoleRequest;
import cn.com.ty.lift.system.user.dao.entity.model.RoleResponse;
import cn.com.ty.lift.system.user.dao.mapper.RoleMapper;
import cn.com.ty.lift.system.user.service.*;
import cn.com.xwy.boot.web.dto.RestResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

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

/**
 * @author huangyuan
 * @date 2019-12-01
 * @description 角色接口实现类
 */
@Service
public class RoleService extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private IRoleMenuService roleMenuService;

    @Resource
    private IUserRoleService userRoleService;

    @Resource
    private IMenuService menuService;

    @Resource
    private IUserInfoService userInfoService;

    @Override
    public RestResponse list(RoleRequest roleRequest) {
        IPage rolePage = new Page<>(roleRequest.getPageNum(), roleRequest.getPageSize());
        rolePage = this.page(rolePage, new QueryWrapper<Role>()
                .eq("company_id", roleRequest.getCompanyId())
                .eq("delete_flag", ApiConstants.DELETE_NO)
        );
        List<Role> roleList = rolePage.getRecords();
        if (roleList != null && roleList.size() > 0) {
            List<RoleResponse> roleResponseList = new ArrayList<>();
            //获取创建者名称
            List<Long> userIdList = ProjectUtils.getAttrList(roleList, "createUserId", null);
            Map<Long, UserInfo> userIdToInfo = userInfoService.userIdToInfo(userIdList);
            for (Role role : roleList) {
                RoleResponse roleResponse = new RoleResponse(role);
                //设置创建者名称
                if (userIdToInfo != null) {
                    UserInfo userInfo = userIdToInfo.get(role.getCreateUserId());
                    if (userInfo != null) {
                        roleResponse.setCreateUserName(userInfo.getName());
                    }
                }
                roleResponseList.add(roleResponse);
            }
            rolePage.setRecords(roleResponseList);
        }
        return RestResponse.success(rolePage, ApiConstants.RESULT_SUCCESS, "获取角色列表成功");
    }

    @Override
    @Transactional
    public RestResponse addRole(RoleRequest roleRequest) {
        Role role = new Role(roleRequest);
        role.setCreateTime(new Date());
        //保存角色信息
        if (roleMapper.insert(role) == 0) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存角色信息失败");
        }
        //保存角色菜单关联关系
        if (!roleMenuService.saveRoleMenu(role.getId(), roleRequest.getMenuIds())) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存角色信息失败");
        }
        return RestResponse.success(role, ApiConstants.RESULT_SUCCESS, "保存角色信息成功");
    }

    @Override
    @Transactional
    public RestResponse updateRole(RoleRequest roleRequest) {
        Role role = this.getById(roleRequest.getId());
        //设置角色基础信息
        role.setDescription(roleRequest.getDescription());
        role.setName(roleRequest.getName());
        role.setUpdateTime(new Date());
        //更新角色信息
        if (roleMapper.updateById(role) == 0) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "更新角色信息失败");
        }
        int roleMenuCount = roleMenuService.count(new QueryWrapper<RoleMenu>().eq("role_id", role.getId()));
        if (roleMenuCount > 0) {
            //删除角色原来关联的菜单信息
            if (roleMenuService.deleteRoleMenu(role.getId()) == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(ApiConstants.RESULT_ERROR, "原有菜单删除失败");
            }
        }
        //保存角色关联的新的菜单信息
        if (StringUtils.isNotBlank(roleRequest.getMenuIds())) {
            if (!roleMenuService.saveRoleMenu(role.getId(), roleRequest.getMenuIds())) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(ApiConstants.RESULT_ERROR, "保存新菜单失败");
            }
        }
        return RestResponse.success(role, ApiConstants.RESULT_SUCCESS, "更新角色信息成功");
    }

    @Override
    @Transactional
    public RestResponse deleteRole(RoleRequest roleRequest) {
        Long roleId = roleRequest.getId();
        //判断角色有没有分配给用户
        int userRoleCount = userRoleService.count(new QueryWrapper<UserRole>()
                .eq("role_id", roleId)
        );
        if (userRoleCount > 0) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "角色已关联用户，无法删除");
        }
        Role role = roleMapper.selectById(roleId);
        role.setDeleteFlag(ApiConstants.DELETE_YES);
        int updateRoleFlag = roleMapper.updateById(role);
        if (updateRoleFlag == 0) {
            return RestResponse.fail(ApiConstants.RESULT_ERROR, "删除失败");
        }
        //删除角色菜单关联信息
        roleMenuService.deleteRoleMenu(roleId);
        return RestResponse.success(null, ApiConstants.RESULT_SUCCESS, "删除成功");
    }

    @Override
    public RestResponse getUserMenus(UserRole userRole) {
        userRole = userRoleService.getByUserRole(userRole);
        String menuUrl = "";
        if (userRole != null) {
            List<Menu> menuList = menuService.getByRoleId(userRole.getRoleId());
            menuUrl = menuService.menuToUrl(menuList);
        }
        return RestResponse.success(menuUrl, ApiConstants.RESULT_SUCCESS, "获取菜单信息成功");
    }

    @Override
    public Role getRoleByUserIdAndCompanyId(Long userId, Long companyId) {
        UserRole userRole = userRoleService.getOne(new QueryWrapper<UserRole>()
                .eq("user_id", userId)
                .eq("company_id", companyId)
        );
        if (userRole != null) {
            return getById(userRole.getRoleId());
        }
        return null;
    }

    @Override
    public Map<Long, Role> getUserIdToRoleByUserIdsAndCompanyId(List<Long> userIdList, Long companyId) {
        Map<Long, Role> userIdToRole = new HashMap<>();
        if (userIdList != null && userIdList.size() > 0) {
            List<UserRole> userRoleList = userRoleService.list(new QueryWrapper<UserRole>()
                    .in("user_id", userIdList)
                    .eq("company_id", companyId)
            );
            //转化用户id对应用户角色关联关系
            Map<Long, UserRole> userIdToUserRole = ProjectUtils.attrToObjMap(userRoleList, "userId", null);
            //获取角色列表
            List<Long> roleIdList = ProjectUtils.getAttrList(userRoleList, "roleId", null);
            if (roleIdList != null && roleIdList.size() > 0) {
                List<Role> roleList = (List<Role>) this.listByIds(roleIdList);
                Map<Long, Role> idToRole = ProjectUtils.attrToObjMap(roleList, "id", null);
                for (Long userId : userIdList) {
                    UserRole userRole = userIdToUserRole.get(userId);
                    if (userRole != null) {
                        Role role = idToRole.get(userRole.getRoleId());
                        userIdToRole.put(userId, role);
                    }
                }
            }
        }
        return userIdToRole;
    }

    @Override
    public RestResponse info(RoleRequest roleRequest) {
        Long roleId = roleRequest.getId();
        RoleResponse roleResponse = new RoleResponse();
        //获取角色
        Role role = this.getById(roleId);
        if (role != null) {
            //角色基础信息查看
            roleResponse.setId(roleId);
            roleResponse.setName(role.getName());
            roleResponse.setId(role.getId());
            //获取角色菜单信息
            List<Menu> roleMenuList = roleMenuService.getMenuTree(roleId);
            roleResponse.setCompanyMenuList(roleMenuList);
        }
        return RestResponse.success(roleResponse, ApiConstants.RESULT_SUCCESS, "获取角色信息成功");
    }

    @Override
    public RestResponse companyRoleList(RoleRequest roleRequest) {
        List<Role> roleList = this.list(new QueryWrapper<Role>()
                .eq("company_id", roleRequest.getCompanyId())
                .eq("delete_flag", ApiConstants.DELETE_NO)
        );
        return RestResponse.success(roleList, ApiConstants.RESULT_SUCCESS, "获取角色信息成功");
    }

    @Override
    public boolean assignDefaultMenu(int defaultAssign, List<Role> defaultRoleList, Role enterpriseAdminRole) {
        List<RoleMenu> needSaveRoleMenuList = new ArrayList<>();
        if (0 == defaultAssign) {
            //如果是手动方式，则只给企业管理员分配菜单
            defaultRoleList = new ArrayList<>();
        }
        defaultRoleList.add(enterpriseAdminRole);
        for (Role role : defaultRoleList) {
            long[] defaultRoleMenuIds = DefaultMenuConstants.DEFAULT_ROLE_MENUIDS.get(role.getCode());
            for (Long menuId : defaultRoleMenuIds) {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleId(role.getId());
                needSaveRoleMenuList.add(roleMenu);
            }
        }
        return roleMenuService.saveBatch(needSaveRoleMenuList);
    }

    @Override
    public List<Role> getRoleByUserIdAndRoleCode(Long userId, String roleCode) {
        return roleMapper.getRoleListByUserIdAndRoleCode(userId, roleCode);
    }

}
