package com.usky.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.system.domain.SysDept;
import com.usky.system.domain.SysPerson;
import com.usky.system.domain.SysPost;
import com.usky.system.domain.SysUser;
import com.usky.system.domain.SysUserPerson;
import com.usky.system.mapper.SysPersonMapper;
import com.usky.system.service.ISysDeptService;
import com.usky.system.service.ISysPostService;
import com.usky.system.service.ISysUserService;
import com.usky.system.service.SysPersonService;
import com.usky.system.service.SysUserPersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 人员信息 服务实现类
 * </p>
 *
 * @author JCB
 * @since 2022-08-22
 */
@Service
public class SysPersonServiceImpl extends AbstractCrudService<SysPersonMapper, SysPerson> implements SysPersonService {
    @Autowired
    private SysUserPersonService sysUserPersonService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ISysPostService sysPostService;

    @Override
    public SysPerson getsysPerson(Long userid) {
        LambdaQueryWrapper<SysUserPerson> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SysUserPerson::getUserId, userid);
        List<SysUserPerson> userPersonList = sysUserPersonService.list(queryWrapper);
        SysPerson sysPerson = new SysPerson();
        if (CollectionUtils.isNotEmpty(userPersonList)) {
            LambdaQueryWrapper<SysPerson> query = Wrappers.lambdaQuery();
            query.eq(SysPerson::getId, userPersonList.get(0).getPersonId());
            sysPerson = this.getOne(query);
            if (sysPerson != null) {
                fillDeptAndPostFromUser(sysPerson, userid);
            }
        }
        return sysPerson;
    }

    @Override
    public void fillDeptAndPostFromUser(SysPerson person, Long userId) {
        if (person == null) {
            return;
        }
        if (userId == null) {
            clearPersonDeptPost(person);
            return;
        }
        SysUser user = sysUserService.selectUserById(userId);
        if (user == null) {
            clearPersonDeptPost(person);
            return;
        }
        person.setDeptId(user.getDeptId());
        if (user.getDeptId() != null) {
            SysDept dept = sysDeptService.selectDeptById(user.getDeptId());
            person.setDeptName(dept != null ? dept.getDeptName() : null);
        } else {
            person.setDeptName(null);
        }
        List<Integer> postIds = sysPostService.selectPostListByUserId(userId);
        if (postIds == null || postIds.isEmpty()) {
            person.setPostId(null);
            person.setPostName(null);
        } else {
            Long pid = postIds.get(0).longValue();
            person.setPostId(pid);
            SysPost post = sysPostService.selectPostById(pid);
            person.setPostName(post != null ? post.getPostName() : null);
        }
    }

    @Override
    public void fillDeptAndPostForList(List<SysPerson> list, Map<Integer, Long> personIdToUserId) {
        if (list == null || list.isEmpty()) {
            return;
        }
        if (personIdToUserId == null || personIdToUserId.isEmpty()) {
            list.forEach(this::clearPersonDeptPost);
            return;
        }
        Set<Long> userIds = new HashSet<>(personIdToUserId.values());
        if (userIds.isEmpty()) {
            list.forEach(this::clearPersonDeptPost);
            return;
        }
        List<SysUser> users = sysUserService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds));
        Map<Long, SysUser> userById = users.stream()
                .collect(Collectors.toMap(SysUser::getUserId, u -> u, (a, b) -> a));

        List<Long> deptIdList = users.stream()
                .map(SysUser::getDeptId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> deptNameMap = new HashMap<>();
        if (!deptIdList.isEmpty()) {
            List<SysDept> depts = sysDeptService.selectDeptByIds(deptIdList);
            if (depts != null) {
                for (SysDept d : depts) {
                    deptNameMap.put(d.getDeptId(), d.getDeptName());
                }
            }
        }

        Map<Long, Long> userFirstPostId = new HashMap<>();
        for (Long uid : userIds) {
            List<Integer> pids = sysPostService.selectPostListByUserId(uid);
            if (pids != null && !pids.isEmpty()) {
                userFirstPostId.put(uid, pids.get(0).longValue());
            }
        }
        Set<Long> postIdSet = new HashSet<>(userFirstPostId.values());
        Map<Long, String> postNameMap = new HashMap<>();
        for (Long pid : postIdSet) {
            SysPost post = sysPostService.selectPostById(pid);
            if (post != null) {
                postNameMap.put(pid, post.getPostName());
            }
        }

        for (SysPerson p : list) {
            Long uid = personIdToUserId.get(p.getId());
            if (uid == null) {
                clearPersonDeptPost(p);
                continue;
            }
            SysUser u = userById.get(uid);
            if (u == null) {
                clearPersonDeptPost(p);
                continue;
            }
            p.setDeptId(u.getDeptId());
            p.setDeptName(u.getDeptId() != null ? deptNameMap.get(u.getDeptId()) : null);
            Long pid = userFirstPostId.get(uid);
            p.setPostId(pid);
            p.setPostName(pid != null ? postNameMap.get(pid) : null);
        }
    }

    private void clearPersonDeptPost(SysPerson person) {
        person.setDeptId(null);
        person.setDeptName(null);
        person.setPostId(null);
        person.setPostName(null);
    }
}
