package cn.common.service.impl;


import cn.common.common.constants.BaseConstant;
import cn.common.common.entity.Tree;
import cn.common.common.redis.RedisRepository;
import cn.common.common.utils.collection.CollectionUtils;
import cn.common.common.utils.common.CheckParam;
import cn.common.common.utils.common.TreeUtil;
import cn.common.interaction.req.department.DepartmentAddReq;
import cn.common.interaction.req.department.DepartmentQueryReq;
import cn.common.interaction.req.department.DepartmentUpdateReq;
import cn.common.interaction.resp.department.AuthDepartmentTreeResp;
import cn.common.interaction.resp.department.AuthDepartmentTreeWrapResp;
import cn.common.repository.entity.AuthDepartment;
import cn.common.repository.repository.AuthDepartmentRepository;
import cn.common.repository.repository.AuthMenuRepository;
import cn.common.repository.repository.AuthPermissionRepository;
import cn.common.repository.repository.AuthRoleRepository;
import cn.common.repository.repository.PlatformUserConfigRepository;
import cn.common.repository.repository.AuthUserRepository;
import cn.common.repository.repository.AuthUserRoleRepository;
import cn.common.repository.repository.PlatformLoginLogRepository;
import cn.common.repository.result.AuthDepartmentResult;
import cn.common.service.AuthCacheService;
import cn.common.service.AuthDepartmentService;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Singer create by singer email:singer-coder@qq.com
 * @projectName health-platform-api
 * @Description: 部门
 * @date 2019-08-23
 */
@Service(value = "authDepartmentService")
@Slf4j
public class AuthDepartmentImpl implements AuthDepartmentService {

    @Resource
    private AuthUserRepository authUserRepository;

    @Resource
    private AuthDepartmentRepository authDepartmentRepository;

    @Resource
    private AuthPermissionRepository authPermissionRepository;

    @Resource
    private AuthRoleRepository authRoleRepository;

    @Resource
    private AuthUserRoleRepository authUserRoleRepository;

    @Resource
    private BaseConstant baseConstant;

    @Resource
    private AuthCacheService authCacheService;

    @Resource
    private PlatformLoginLogRepository platformLoginLogRepository;

    @Resource
    private RedisRepository redisRepository;

    @Resource
    private PlatformUserConfigRepository platformUserConfigRepository;

    @Resource
    private AuthMenuRepository authMenuRepository;



    /**
      * 新增部门
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2019-08-30
      * @param departmentAddReq 新增部门
      */
    @Override
    public void addAuthDepartment(DepartmentAddReq departmentAddReq){

        AuthDepartment authDepartment = new AuthDepartment();

         String parentId = departmentAddReq.getParentId();

        if(CheckParam.isNull(parentId)) {
            authDepartment.setParentId("0");
        }
        if(!CheckParam.isNull(departmentAddReq.getDepartmentName())){
            authDepartment.setDepartmentName(departmentAddReq.getDepartmentName());
        }
        if(!CheckParam.isNull(departmentAddReq.getOrderNum())){
            authDepartment.setOrderNum(departmentAddReq.getOrderNum());
        }
        if(!CheckParam.isNull(departmentAddReq.getParentId())){
            authDepartment.setParentId(departmentAddReq.getParentId());
        }
        authDepartmentRepository.insert(authDepartment);
    }


    /**
     * 更新部门信息
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2019-08-30
     * @param req 部门更新req
     */
    @Override
    public void updateDepartment(DepartmentUpdateReq req){
        String departmentId = req.getDepartmentId();
        AuthDepartment authDepartment = authDepartmentRepository
                .selectOne(new LambdaQueryWrapper<AuthDepartment>().eq(AuthDepartment::getDepartmentId, departmentId));
        if(CheckParam.isNull(authDepartment)) {
            return;
        }
        if(!CheckParam.isNull(req.getDepartmentName())){
            authDepartment.setDepartmentName(req.getDepartmentName());
        }
        if(!CheckParam.isNull(req.getOrderNum())){
            authDepartment.setOrderNum(req.getOrderNum());
        }
        if(!CheckParam.isNull(req.getParentId())){
            authDepartment.setParentId(req.getParentId());
        }
        authDepartment.setUpdateTime(LocalDateTime.ofInstant(Instant.now(), Clock.systemDefaultZone().getZone()));
        authDepartmentRepository.updateById(authDepartment);
    }


    /**
     * 删除部门
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2019-09-05
     * @param departmentIdList 需要被删除的部门的主键ID
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteDepartment(List<String> departmentIdList){
        List<AuthDepartmentResult> departmentResultList =
                authDepartmentRepository.queryAllDepartment(baseConstant.getUnDeleteStatus());

        Map<String, List<AuthDepartmentResult>> authDepartmentHashMap = departmentResultList.stream()
                .collect(Collectors.groupingBy(AuthDepartmentResult::getParentId));

        ArrayList<String> authDepartmentIdList = Lists.newArrayList();

        //处理菜单级联的问题
        departmentIdList.stream().forEach(item -> {
            handleParentId(authDepartmentIdList,authDepartmentHashMap,item);
        });

        if(!authDepartmentIdList.isEmpty()){
            authDepartmentRepository.updateDeleteStatusByDepartmentIdList(baseConstant.getDeleteStatus(),authDepartmentIdList);
        }
    }

    /**
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/4/18
     * @param departmentIdList 需要装载部门ID的ID
     * @param authDepartmentHashMap
     * @param departmentId 菜单ID
     */
    public void handleParentId(List<String> departmentIdList,
                               Map<String, List<AuthDepartmentResult>> authDepartmentHashMap,
                               String departmentId){
        List<AuthDepartmentResult> authDepartmentList = authDepartmentHashMap.get(departmentId);

        if(!CollectionUtils.isEmpty(authDepartmentList)){
            List<String> needHandleIdList =
                    authDepartmentList.stream().map(item -> item.getDepartmentId()).distinct().collect(Collectors.toList());
            departmentIdList.addAll(needHandleIdList);
            needHandleIdList.stream().forEach(item -> {
                handleParentId(departmentIdList,authDepartmentHashMap,item);
            });
        }
        if(!CollectionUtil.contains(departmentIdList,departmentId)){
            departmentIdList.add(departmentId);
        }
    }

    /**
      * 查询所有的部门的树型结构
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2019-08-23
      * @param queryReq 部门分页查询req
      * @return AuthDepartmentTreeWrapResp
      */
    @Override
    public AuthDepartmentTreeWrapResp queryAllDepartmentTreeList(DepartmentQueryReq queryReq){
        LambdaQueryWrapper<AuthDepartment> queryWrapper = new LambdaQueryWrapper<>();
        //构建查询条件
        if(!CheckParam.isNull(queryReq.getDepartmentName())){
            queryWrapper.like(true,AuthDepartment::getDepartmentName,queryReq.getDepartmentName());
        }
        if(!CheckParam.isNull(queryReq.getBeginTime())){
            queryWrapper.ge(true,AuthDepartment::getCreateTime,queryReq.getBeginTime());
        }
        if(!CheckParam.isNull(queryReq.getEndTime())){
            queryWrapper.le(true,AuthDepartment::getCreateTime,queryReq.getEndTime());
        }
        queryWrapper.orderByDesc(AuthDepartment::getCreateTime);
        //开始分页
        List<AuthDepartment> entityList = authDepartmentRepository.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(entityList)) {
            return new AuthDepartmentTreeWrapResp();
        }
        List<AuthDepartmentTreeResp> authDepartmentRespList = new ArrayList<>();
        entityList.forEach(u1 -> {
            AuthDepartmentTreeResp treeResp = new AuthDepartmentTreeResp();
            treeResp.setCreateTime(u1.getCreateTime());
            treeResp.setDepartmentId(u1.getDepartmentId());
            treeResp.setDepartmentName(u1.getDepartmentName());
            treeResp.setOrderNum(u1.getOrderNum());
            treeResp.setParentId(u1.getParentId());
            treeResp.setCreateTime(u1.getCreateTime());
            treeResp.setUpdateTime(u1.getUpdateTime());
            authDepartmentRespList.add(treeResp);
        });
        //构建一颗部门树
        List<Tree<AuthDepartmentTreeResp>> treeRespList = new ArrayList<>();
        //构建部门树，包装业务数据
        buildTrees(treeRespList, authDepartmentRespList);
        AuthDepartmentTreeWrapResp resp = new AuthDepartmentTreeWrapResp();
        Tree<AuthDepartmentTreeResp> departmentTree = TreeUtil.build(treeRespList);
        resp.setTrees(departmentTree);
        resp.setTotal(treeRespList.size());
        //在部门树的最外层再包装一层数据
        return resp;
    }

    /**
      * 构建部门树
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2019-08-23
      * @param trees  已经构建好的部门树的List
      * @param authDepartmentList  部门集合
      */
    private void buildTrees(List<Tree<AuthDepartmentTreeResp>> trees, List<AuthDepartmentTreeResp> authDepartmentList) {
        authDepartmentList.forEach(dept -> {
            Tree<AuthDepartmentTreeResp> tree = new Tree<>();

            tree.setId(dept.getDepartmentId());
            tree.setKey(tree.getId());
            tree.setParentId(dept.getParentId());
            tree.setCreateTime(dept.getCreateTime());
            tree.setUpdateTime(dept.getUpdateTime());
            tree.setOrder(dept.getOrderNum());
            tree.setText(dept.getDepartmentName());
            tree.setTitle(tree.getText());
            tree.setValue(tree.getId());
            trees.add(tree);
        });
    }


    /**
     * 查询所有的部门的树型结构
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2019-08-23
     * @return Tree
     */
    @Override
    public Tree<AuthDepartmentTreeResp> queryAllDepartmentTree(){
        List<AuthDepartment> authDepartmentList =
                authDepartmentRepository.selectList(new LambdaQueryWrapper<>());
        if(CollectionUtils.isEmpty(authDepartmentList)) {
            return new Tree<>();
        }
        List<AuthDepartmentTreeResp> authDepartmentRespList = new ArrayList<>();
        authDepartmentList.forEach(u1 -> {
            AuthDepartmentTreeResp treeResp = new AuthDepartmentTreeResp();

            treeResp.setCreateTime(u1.getCreateTime());
            treeResp.setDepartmentId(u1.getDepartmentId());
            treeResp.setDepartmentName(u1.getDepartmentName());
            treeResp.setOrderNum(u1.getOrderNum());
            treeResp.setParentId(u1.getParentId());

            authDepartmentRespList.add(treeResp);
        });
        //构建一颗部门树
        List<Tree<AuthDepartmentTreeResp>> treeRespList = new ArrayList<>();
        //构建部门树，包装业务数据
        buildTrees(treeRespList, authDepartmentRespList);
        //在部门树的最外层再包装一层数据
        return TreeUtil.build(treeRespList);
    }
}
