package com.ruansi.wflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import com.ruansi.system.api.domain.SysDept;
import com.ruansi.system.api.domain.SysUser;
import com.ruansi.system.domain.SysUserRole;
import com.ruansi.wflow.bean.do_.DeptDo;
import com.ruansi.wflow.bean.do_.RoleDo;
import com.ruansi.wflow.bean.do_.UserDeptDo;
import com.ruansi.wflow.bean.do_.UserDo;
import com.ruansi.wflow.bean.entity.*;
import com.ruansi.wflow.bean.vo.ModelGroupVo;
import com.ruansi.wflow.bean.vo.OrgTreeVo;
import com.ruansi.wflow.bean.vo.UserVo;
import com.ruansi.wflow.mapper.*;
import com.ruansi.wflow.service.OrgRepositoryService;
import liquibase.pro.packaged.S;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 默认wflow的实现，集成自有系统需要自行实现接口
 * @author : willian fu
 * @date : 2022/11/29
 */
@Service
public class DefaultOrgRepositoryServiceImpl implements OrgRepositoryService {

    @Autowired
    private WflowUsersMapper usersMapper;

    @Autowired
    private WflowRolesMapper rolesMapper;

    @Autowired
    private WflowDepartmentsMapper departsMapper;

    @Autowired
    private WflowUserDepartmentsMapper userDepartmentsMapper;

    @Autowired
    private WflowUserRolesMapper userRolesMapper;

    @Autowired
    private WflowModelPermsMapper modelPermsMapper;

    @Override
    public List<ModelGroupVo.Form> getModelsByPerm(String userId) {
        return modelPermsMapper.selectByPerms(userId);
    }

    @Override
    public UserDo getUserById(String userId) {
        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUser::getUserId,userId);
        SysUser wflowUsers = usersMapper.selectOne(lqw);
        if (Objects.nonNull(wflowUsers)){
            UserDo userDo = new UserDo();
            BeanUtils.copyProperties(wflowUsers, userDo);
            return userDo;
        }
        return null;
    }

    @Override
    public List<OrgTreeVo> selectUsersByPy(String py) {
        return usersMapper.selectUsersByPy(py).stream()
                .peek(u -> u.setType("user")).collect(Collectors.toList());
    }

    @Override
    public List<OrgTreeVo> selectUsersByDept(String deptId) {
        List<OrgTreeVo> orgTreeVos = usersMapper.selectUsersByDept(deptId);
        orgTreeVos.forEach(v -> v.setType("user"));
        return orgTreeVos;
    }

    @Override
    public List<UserDo> getUsersBatch(Collection<String> userIds) {
        try {
            return usersMapper.selectBatchIds(userIds).stream()
                    .map(u -> new UserDo(u.getUserId()+"", u.getUserName(),u.getNickName(), u.getAvatar()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    @Override
    public List<DeptDo> getDeptBatch(Collection<String> deptIds) {
        try {
            return departsMapper.selectBatchIds(deptIds).stream()
                    .map(u -> new DeptDo(u.getDeptId(), u.getDeptName(), u.getLeader(), u.getParentId()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    @Override
    public Set<String> getUsersByDepts(Collection<String> deptIds) {
        try {
           /* List<SysUser> userList = usersMapper.selectList(
                    new LambdaQueryWrapper<SysUser>()
                            .select(SysUser::getUserId)
                            .in(SysUser::getDeptId, deptIds));
            Set<String> stringSet = new HashSet<>();
            for (SysUser user : userList) {
                stringSet.add(user.getUserId()+"");
            }
            return stringSet;*/
            return usersMapper.selectList(
                    new LambdaQueryWrapper<SysUser>()
                            .select(SysUser::getUserId)
                            .in(SysUser::getDeptId, deptIds))
                    .stream().map(n->n.getUserId()+"")
                    .collect(Collectors.toSet());
        } catch (Exception e) {
            return Collections.emptySet();
        }
    }

    @Override
    public DeptDo getDeptById(String deptId) {
        LambdaQueryWrapper<SysDept> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysDept::getDeptId,deptId);
        SysDept departments = departsMapper.selectOne(lqw);
        if (Objects.nonNull(departments)){
            DeptDo deptDo = new DeptDo();
            BeanUtils.copyProperties(departments, deptDo);
            return deptDo;
        }
        return null;
    }

    @Override
    public List<DeptDo> getSysAllDepts() {
        try {
            return departsMapper.selectList(null).stream()
                    .map(d -> new DeptDo(d.getDeptId(), d.getDeptName(), d.getLeader(), d.getParentId()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    @Override
    public List<UserDeptDo> getSysAllUserDepts() {
        try {
            return usersMapper.selectList(null).stream()
                    .map(d -> new UserDeptDo(d.getUserId()+"", d.getDeptId()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    @Override
    public List<OrgTreeVo> getSubDeptById(String parentId) {
        return departsMapper.selectList(new LambdaQueryWrapper<SysDept>()
                .select(SysDept::getDeptId, SysDept::getDeptName)
                .eq(SysDept::getParentId, parentId))
                .stream().map(v -> OrgTreeVo.builder().id(v.getDeptId())
                        .name(v.getDeptName())
                        .type("dept").build())
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getRecursiveSubDept(String parentId) {
        List<String> list = new ArrayList<>();
        loadSubDept(parentId, list);
        return list;
    }

    /**
     * 递归加载所有子部门
     * @param parentId 父部门ID
     * @param subDepts 所有子部门缓存
     */
    private void loadSubDept(String parentId, List<String> subDepts){
        List<SysDept> departments = departsMapper.selectList(
                new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getParentId, parentId));
        subDepts.addAll(departments.stream().map(SysDept::getDeptId).collect(Collectors.toList()));
        departments.forEach(d -> loadSubDept(d.getDeptId(), subDepts));
    }

    @Override
    public List<RoleDo> getSysAllRoles() {
        try {
            return rolesMapper.selectList(null).stream()
                    .map(r -> new RoleDo(r.getRoleId()+"", r.getRoleName()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    @Override
    public Set<String> getUsersByRoles(List<String> roles) {
        return userRolesMapper.selectList(new LambdaQueryWrapper<SysUserRole>()
                        .select(SysUserRole::getUserId)
                        .in(SysUserRole::getRoleId, roles)).stream()
                .map(n -> n.getUserId()+"").collect(Collectors.toSet());
    }

    @Override
    public String getUserSign(String userId) {
        return usersMapper.selectById(userId).getSign();
    }

    @Override
    public void updateUserSign(String userId, String signature) {
        SysUser user = new SysUser();
        user.setUserId(Long.parseLong(userId));
        user.setSign(signature);
        usersMapper.updateById(user);
    }

    @Override
    public SysUser getUserDetail(String userId) {
        SysUser user = usersMapper.selectById(userId);
//        List<WflowRoles> roles = rolesMapper.getRolesByUser(userId);
        return user;
    }

    @Override
    public List<SysDept> getDeptsByUser(String userId) {
        return userDepartmentsMapper.getUserDepts(userId);
    }
}
