package com.skr.mdm.api.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.skr.mdm.api.system.service.RoleService;
import com.skr.mdm.bean.qo.role.RoleQO;
import com.skr.mdm.bean.vo.role.RoleVO;
import com.skr.mdm.dao.*;
import com.skr.mdm.dto.LoginAdminDTO;
import com.skr.mdm.entity.*;
import com.skr.mdm.enums.LogAdminTypeEnum;
import com.skr.mdm.enums.ResultCodeEnum;
import com.skr.mdm.handle.LogAdminHandler;
import com.skr.mdm.result.ResponseResult;
import com.skr.mdm.util.PageUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
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 javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author nfq
 * @date 2020/9/8 17:45
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Value("${token.expire.seconds}")
    private Long expireSeconds;

    @Autowired
    private AuCompanyDao companyDao;
    @Autowired
    private SysFunctionScopePermissionDao functionScopePermissionDao;
    @Autowired
    private AuPermissionDao permissionDao;
    @Autowired
    private AuRolePermissionDao rolePermissionDao;
    @Autowired
    private AuRoleDao roleDao;
    @Autowired
    private AuAdminRoleDao auAdminRoleDao;
    @Autowired
    private LogAdminHandler logAdminHandler;

    @Override
    public ResponseResult menuTree(Integer companyId, Integer roleId) {
        AuCompanyDO companyDO = companyDao.selectById(companyId);
        Integer functionScopeId = companyDO.getFunctionScopeId();
        // 获取公司功能范围
        List<SysFunctionScopePermissionDO> functionScopePermissionDOList = new LambdaQueryChainWrapper<>(functionScopePermissionDao)
                .eq(SysFunctionScopePermissionDO::getFunctionScopeId, functionScopeId)
                .list();
        if (CollectionUtils.isNotEmpty(functionScopePermissionDOList)) {
            // 获取权限信息
            List<Integer> permissionIdList = functionScopePermissionDOList.stream().map(SysFunctionScopePermissionDO::getPermissionId).collect(Collectors.toList());
            List<AuPermissionDO> permissionDOList = new LambdaQueryChainWrapper<>(permissionDao)
                    .eq(AuPermissionDO::getUsable, 1)
                    .in(AuPermissionDO::getId, permissionIdList)
                    .orderByAsc(AuPermissionDO::getCreateTime)
                    .list();
            if (CollectionUtils.isNotEmpty(permissionDOList)) {
                List<Integer> rolePermissionIdList = null;
                if (roleId != null) {
                    rolePermissionIdList = new LambdaQueryChainWrapper<>(rolePermissionDao)
                            .eq(AuRolePermissionDO::getRoleId, roleId)
                            .list()
                            .stream()
                            .map(AuRolePermissionDO::getPermissionId)
                            .collect(Collectors.toList());
                }
                return ResponseResult.success(getChildren(0, rolePermissionIdList, permissionDOList));
            }
        }
        return ResponseResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult addRole(RoleQO roleQO, LoginAdminDTO loginAdminDTO) {
        LambdaQueryChainWrapper<AuRoleDO> queryChainWrapper = new LambdaQueryChainWrapper<>(roleDao);
        Long count = queryChainWrapper.eq(AuRoleDO::getRoleName, roleQO.getRoleName()).eq(AuRoleDO::getCompanyId, loginAdminDTO.getCompanyId()).count();
        if (count > 0) {
            return ResponseResult.failure(ResultCodeEnum.ROLE_NAME_REPEAT);
        }
        AuCompanyDO companyDO = companyDao.selectById(loginAdminDTO.getCompanyId());
        AuRoleDO roleDO = new AuRoleDO();
        roleDO.setRoleName(roleQO.getRoleName());
        roleDO.setFunctionScopeId(companyDO.getFunctionScopeId());
        roleDO.setIsUsable(1);
        roleDO.setNote(roleQO.getNote());
        roleDO.setCompanyId(loginAdminDTO.getCompanyId());
        roleDO.setLevel(roleQO.getLevel());
        roleDO.setOperator(loginAdminDTO.getAdminName());
        roleDao.insert(roleDO);
        rolePermissionDao.insertBatch(roleDO.getId(), roleQO.getMenuIdList());

        String content = "创建角色  角色名：" + roleQO.getRoleName();
        String module = "角色管理";
        logAdminHandler.log(loginAdminDTO, roleQO.getRoleName(), LogAdminTypeEnum.OTHER_TYPE.getLogType(), content, module);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult listRole(Integer pageNum, Integer pageSize, Integer companyId, String roleName) {
        PageHelper.startPage(pageNum, pageSize);
        List<RoleVO> roleVOList = roleDao.listRole(companyId, roleName);
        PageInfo<RoleVO> pageInfo = new PageInfo<>(roleVOList);
        return ResponseResult.success(PageUtil.getPageResult(pageInfo));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult updateRole(RoleQO roleQO, LoginAdminDTO loginAdminDTO, HttpServletRequest request) {
        if (StringUtils.isNotBlank(roleQO.getRoleName())) {
            LambdaQueryChainWrapper<AuRoleDO> queryChainWrapper = new LambdaQueryChainWrapper<>(roleDao);
            Long count = queryChainWrapper.eq(AuRoleDO::getRoleName, roleQO.getRoleName()).ne(AuRoleDO::getId, roleQO.getId())
                    .eq(AuRoleDO::getCompanyId, loginAdminDTO.getCompanyId()).count();
            if (count > 0) {
                return ResponseResult.failure(ResultCodeEnum.ROLE_NAME_REPEAT);
            }
        }
        if (StringUtils.isNotBlank(roleQO.getRoleName()) || StringUtils.isNotBlank(roleQO.getNote())) {
            LambdaUpdateChainWrapper<AuRoleDO> updateChainWrapper = new LambdaUpdateChainWrapper<>(roleDao);
            updateChainWrapper
                    .set(StringUtils.isNoneBlank(roleQO.getRoleName()), AuRoleDO::getRoleName, roleQO.getRoleName())
                    .set(AuRoleDO::getNote, roleQO.getNote())
                    .set(roleQO.getLevel() != null, AuRoleDO::getLevel, roleQO.getLevel())
                    .set(AuRoleDO::getOperator, loginAdminDTO.getAdminName())
                    .eq(AuRoleDO::getId, roleQO.getId())
                    .update();
        }

        LambdaQueryWrapper<AuRolePermissionDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AuRolePermissionDO::getRoleId, roleQO.getId());
        rolePermissionDao.delete(queryWrapper);
        rolePermissionDao.insertBatch(roleQO.getId(), roleQO.getMenuIdList());

        String content = "编辑角色 角色名：" + roleQO.getRoleName();
        String module = "角色管理";
        logAdminHandler.log(loginAdminDTO, roleQO.getRoleName(), LogAdminTypeEnum.OTHER_TYPE.getLogType(), content, module);
        return ResponseResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteRole(Integer roleId, LoginAdminDTO loginAdminDTO) {
        LambdaQueryChainWrapper<AuAdminRoleDO> queryChainWrapper = new LambdaQueryChainWrapper<>(auAdminRoleDao);
        Long count = queryChainWrapper.eq(AuAdminRoleDO::getRoleId, roleId).count();
        if (count > 0) {
            return ResponseResult.failure(ResultCodeEnum.ROLE_ADMIN_EXIT);
        }
        AuRoleDO roleDO = roleDao.selectById(roleId);
        String roleName = roleDO.getRoleName();
        roleDao.deleteById(roleId);
        LambdaQueryWrapper<AuRolePermissionDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AuRolePermissionDO::getRoleId, roleId);
        rolePermissionDao.delete(queryWrapper);

        String content = "删除角色 角色名：" + roleName;
        String module = "角色管理";
        logAdminHandler.log(loginAdminDTO, roleName, LogAdminTypeEnum.OTHER_TYPE.getLogType(), content, module);
        return ResponseResult.success();
    }

    private List<Map<String, Object>> getChildren(Integer parentId, List<Integer> rolePermissionIdList, List<AuPermissionDO> permissionDOList) {
        List<Map<String, Object>> list = Lists.newArrayListWithCapacity(64);
        if (CollectionUtils.isNotEmpty(permissionDOList)) {
            Map<String, Object> map;
            for (AuPermissionDO permissionDO : permissionDOList) {
                if (permissionDO.getParentId().equals(parentId)) {
                    map = Maps.newHashMapWithExpectedSize(5);
                    map.put("name", permissionDO.getName());
                    map.put("value", permissionDO.getId());
                    map.put("percode", permissionDO.getPercode());
                    map.put("checked", false);
                    if (CollectionUtils.isNotEmpty(rolePermissionIdList) && rolePermissionIdList.contains(permissionDO.getId())) {
                        map.put("checked", true);
                    }
                    map.put("children", getChildren(permissionDO.getId(), rolePermissionIdList, permissionDOList));
                    list.add(map);
                }
            }
        }
        return list;
    }

}
