package org.dromara.wflow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.dromara.wflow.bean.do_.DeptDo;
import org.dromara.wflow.bean.do_.RoleDo;
import org.dromara.wflow.bean.do_.UserDeptDo;
import org.dromara.wflow.bean.do_.UserDo;
import org.dromara.wflow.bean.entity.SysDept;
import org.dromara.wflow.bean.entity.SysUser;
import org.dromara.wflow.bean.entity.VSysRole;
import org.dromara.wflow.bean.entity.VSysUserRole;
import org.dromara.wflow.bean.vo.FileResourceVo;
import org.dromara.wflow.bean.vo.ModelGroupVo;
import org.dromara.wflow.bean.vo.OrgTreeVo;
import org.dromara.wflow.bean.vo.UserVo;
import org.dromara.wflow.mapper.*;
import org.dromara.wflow.service.FileManagerService;
import org.dromara.wflow.service.OrgRepositoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

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

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

    @Autowired
    private WflowSysUserMapper userMapper;

    @Autowired
    private VSysRoleMapper roleMapper;

    @Autowired
    private WflowSysDeptMapper deptMapper;

    @Autowired
    private VSysUserRoleMapper userRoleMapper;

    @Autowired
    private WflowModelPermsMapper modelPermsMapper;

    @Qualifier("minioFileManagerServiceImpl")
    @Autowired
    private FileManagerService fileManagerService;


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

    @Override
    public UserDo getUserById(String userId) {
        SysUser sysUser = userMapper.selectById(userId);
        if (Objects.nonNull(sysUser)){
            UserDo userDo = new UserDo();
            BeanUtils.copyProperties(sysUser, userDo);
            return userDo;
        }
        return null;
    }

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

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

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

    @Override
    public List<DeptDo> getDeptBatch(Collection<String> deptIds) {
        try {
            return deptMapper.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 {
            return userMapper.selectList(
                    new LambdaQueryWrapper<SysUser>()
                            .select(SysUser::getUserId)
                            .in(SysUser::getDeptId, deptIds))
                    .stream().map(SysUser::getUserId)
                    .collect(Collectors.toSet());
        } catch (Exception e) {
            return Collections.emptySet();
        }
    }

    @Override
    public DeptDo getDeptById(String deptId) {
        SysDept sysDept = deptMapper.selectById(deptId);
        if (Objects.nonNull(sysDept)){
            DeptDo deptDo = new DeptDo();
            BeanUtils.copyProperties(sysDept, deptDo);
            return deptDo;
        }
        return null;
    }

    @Override
    public List<DeptDo> getSysAllDepts() {
        try {
            return deptMapper.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 userMapper.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 deptMapper.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 = deptMapper.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 roleMapper.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 userRoleMapper.selectList(new LambdaQueryWrapper<VSysUserRole>()
                        .select(VSysUserRole::getUserId)
                        .in(VSysUserRole::getRoleId, roles)).stream()
                .map(VSysUserRole::getUserId).collect(Collectors.toSet());
    }

    @Override
    public Set<String> getUsersByDeptRoles(String deptId, List<String> roles) {
        Set<String> res = userMapper.selectUsersByDeptRoles(deptId, roles);
        System.out.println(res);
        return res;
//        return userRoleMapper.selectList(new LambdaQueryWrapper<VSysUserRole>()
//                        .select(VSysUserRole::getUserId)
//                        .in(VSysUserRole::getRoleId, roles)).stream()
//                .map(VSysUserRole::getUserId).collect(Collectors.toSet());
    }

    @Override
    public String getUserSign(String userId) {
        SysUser sysUser = userMapper.selectById(userId);
        if (Objects.isNull(sysUser)){
            return null;
        }
        return sysUser.getRemark();
    }

    @Override
    public void updateUserSign(String userId, String signature) {
        //1.上传sign，2删除旧的sign，3.改为新的sign
        /*try {
            FileResourceVo fileResourceVo = fileManagerService.uploadFile(signature);

        } catch (IOException e) {
            e.printStackTrace();
        }*/
        userMapper.updateById(SysUser.builder().userId(userId).sign(signature).build());
    }

    @Override
    public UserVo getUserDetail(String userId) {
        SysUser user = userMapper.selectById(userId);
        List<DeptDo> depts = getDeptsByUser(userId);
        List<VSysRole> roles = roleMapper.getRolesByUser(userId);
        return UserVo.builder()
                .userId(userId)
                .username(user.getUserName())
                .nickName(user.getNickName())
                .sex(user.getSex())
                .deptId(user.getDeptId())
                .avatar(user.getAvatar())
                .positions(Collections.emptyList())
                .depts(depts.stream().map(DeptDo::getDeptName).collect(Collectors.toList()))
                .roles(roles.stream().map(VSysRole::getRoleName).collect(Collectors.toList()))
                .build();
    }

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