package jnpf.cultivate.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.nacos.shaded.com.google.common.collect.ImmutableMap;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jnpf.base.UserInfo;
import jnpf.cultivate.mapper.FtbCultivateMessageInfoMapper;
import jnpf.cultivate.mapper.FtbCultivatePromotionMapper;
import jnpf.cultivate.mapper.FtbCultivatePromotionMemberMapper;
import jnpf.cultivate.service.FtbCultivatePositionService;
import jnpf.cultivate.service.FtbCultivatePromotionMemberService;
import jnpf.cultivate.utils.UserApiV2Util;
import jnpf.model.cultivate.dto.promotion.FtbCultivatePromotionDto;
import jnpf.model.cultivate.dto.promotion.FtbCultivatePromotionMemberDto;
import jnpf.model.cultivate.po.mesgg.CultivateMessageInfo;
import jnpf.model.cultivate.po.promotion.FtbCultivatePromotionMember;
import jnpf.model.cultivate.vo.promotion.FtbCultivateMeberVO;
import jnpf.model.cultivate.vo.promotion.FtbCultivatePromotionMemberVO;
import jnpf.model.cultivate.vo.promotion.FtbCultivatePromotionPostVO;
import jnpf.model.cultivate.vo.promotion.FtbCultivatePromotionVO;
import jnpf.permission.UserApi;
import jnpf.permission.UserRelationApi;
import jnpf.permission.model.position.PositionGradesInfoBoundVO;
import jnpf.permission.model.user.PartUserInfoVo;
import jnpf.permission.model.userrelation.UserRelationPositionGrades;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.util.Constants;
import jnpf.util.UserProvider;
import jnpf.utils.FeignHolder;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

@Service
public class FtbCultivatePromotionMemberServiceImpl extends ServiceImpl<FtbCultivatePromotionMemberMapper, FtbCultivatePromotionMember> implements FtbCultivatePromotionMemberService {

    @Resource
    FtbCultivatePromotionMemberMapper memberMapper;

    @Resource
    FtbCultivatePromotionMapper promotionMapper;

    @Autowired
    UserApi userApi;

    @Autowired
    UserApiV2Util userApiV2Util;

    @Autowired
    private Executor threadPoolExecutor;

    @Resource
    FtbCultivateMessageInfoMapper messageInfoMapper;

    @Autowired
    UserRelationApi userRelationApi;
    @Autowired
    FtbCultivatePositionService ftbCultivatePositionService;

    @Override
    @SneakyThrows
    public FtbCultivateMeberVO queryChannelMembers(String id) {
        // 通道层级
        FtbCultivatePromotionVO promotionChannel = promotionMapper.getPromotionChannel(id);
        if (ObjectUtil.isEmpty(promotionChannel)) {
            throw new RuntimeException("查询的通道id不存在,请核对后重新查询");
        }
        FtbCultivateMeberVO memberVO = new FtbCultivateMeberVO();
        memberVO.setPromotionId(promotionChannel.getId());
        memberVO.setPromotion(promotionChannel.getPromotion());
        memberVO.setPromotionBusinessId(promotionChannel.getPromotionBusinessId());
        memberVO.setChannelLevel(promotionChannel.getPostChannelLevel());
        // 查询组织结构用户列表
        List<PartUserInfoVo> userApiInfoByIds = userApi.getInfoByIds(new ArrayList<>());
        Map<String, PartUserInfoVo> userInfo = Maps.newHashMap();
        userApiInfoByIds.forEach(item -> userInfo.put(item.getUserId(), item));
        // 所有用户的信息id
        List<String> userIds = userApiInfoByIds.stream().map(PartUserInfoVo::getUserId).distinct().filter(userId -> userId.length() > 10).collect(Collectors.toList());
        // 异步数据优化
        List<List<String>> partition = partition(userIds, 20);
        List<PositionGradesInfoBoundVO> userList = aggregateData(partition);
//        ListIdDTO listIdDTO = new ListIdDTO();
//        listIdDTO.setIds(userIds);
//        List<PositionGradesInfoBoundVO> userList = positionApi.postOrgPositionInfoList(listIdDTO);
        // 过滤空的用户信息
        List<PositionGradesInfoBoundVO> infoBoundVOList = userList.stream().filter(item -> com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(item.getUserId())).collect(Collectors.toList());
        // 查询已启用成员列表
        Page<FtbCultivatePromotionMemberVO> mbeList = promotionMapper.getPromotionMbeList(new FtbCultivatePromotionDto().setPromotionId(id),
                new Page());
        List<FtbCultivatePromotionMemberVO> mbeListRecords = mbeList.getRecords();
        // 获取当前传入用户绑定信息
        // 已启用成员列表
        memberVO.setListOfMembers(mbeListRecords);
        // 进行数据剔除得到未启用成员列表
        List<PositionGradesInfoBoundVO> partUserInfoVos = infoBoundVOList.stream().filter(item -> mbeListRecords.parallelStream().noneMatch(mbe -> mbe.getUserId().equals(item.getUserId()))).collect(Collectors.toList());
        FtbCultivatePromotionPostVO promotionPostVO = promotionChannel.getPostChannelLevel().stream().filter(item -> 1 == item.getChannelLevel()).findFirst().orElse(new FtbCultivatePromotionPostVO());
        String postId = promotionPostVO.getPostId();
        // 只过滤该岗位的组织成员
        // 过滤当前岗位的成员
        List<PositionGradesInfoBoundVO> infoBoundVOS = partUserInfoVos.stream().filter(item -> postId.equals(item.getPositionId())).collect(Collectors.toList());
        // 获取到当前用户的岗位id
        List<FtbCultivatePromotionMemberVO> enabledListOfMembers = infoBoundVOS.stream().map(vo -> {
            FtbCultivatePromotionMemberVO promotionMemberVO = new FtbCultivatePromotionMemberVO();
            promotionMemberVO.setUserId(vo.getUserId());
            PartUserInfoVo partUserInfoVo = userInfo.get(vo.getUserId());
            promotionMemberVO.setUserName(partUserInfoVo.getRealName());
            promotionMemberVO.setOrgName(partUserInfoVo.getOrganizeName());
            promotionMemberVO.setOrgId(partUserInfoVo.getOrganizeId());
            promotionMemberVO.setPositionId(vo.getPositionId());
            promotionMemberVO.setPositionName(vo.getPositionName());
            promotionMemberVO.setPositionGradesId(vo.getPositionGradesId());
            promotionMemberVO.setPositionGradesName(vo.getPositionGradesName());
            return promotionMemberVO;
        }).collect(Collectors.toList());
        Map<String, List<FtbCultivatePromotionMemberVO>> stringListMap = enabledListOfMembers.stream().filter(
                        item -> !StringUtils.isEmpty(item.getOrgName()))
                .collect(Collectors.groupingBy(FtbCultivatePromotionMemberVO::getOrgName));
        memberVO.setNotEnabledListOfMembers(stringListMap);
        return memberVO;
    }

    /**
     * 数据分块
     *
     * @param list
     * @param size
     * @param <T>
     * @return
     */
    public <T> List<List<T>> partition(List<T> list, int size) {
        return list.stream()
                .collect(Collectors.groupingBy(it -> list.indexOf(it) / size))
                .values().stream()
                .map(listPart -> new ArrayList<>(listPart))
                .collect(Collectors.toList());
    }

    /**
     * 异步统计组织信息数据
     *
     * @param queries
     * @return
     * @throws InterruptedException
     */
    @SneakyThrows
    public List<PositionGradesInfoBoundVO> aggregateData(List<List<String>> queries) throws InterruptedException {
        int threadCount = queries.size();
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        List<List<PositionGradesInfoBoundVO>> results = Collections.synchronizedList(new ArrayList<>(400));
        final UserInfo userInfo = UserProvider.getUser();
        final String tenantId = userInfo.getTenantId();
        ;
        String token = userInfo.getToken();
        Map<String, String> headers = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
        for (List<String> query : queries) {
            threadPoolExecutor.execute(() -> {
                try {
                    // 执行查询并获取结果
                    List<PositionGradesInfoBoundVO> dataSummary = executeQuerys(query, tenantId, headers);
                    // 将结果添加到列表中
                    if (dataSummary != null) {
                        results.add(dataSummary);
                    }
                } finally {
                    // 计数器减一，表示一个任务已完成
                    countDownLatch.countDown();
                }
            });
        }
        // 主线程等待所有子线程完成
        countDownLatch.await();
        // 合并或汇总所有数据结果
        return mergeResults(results);
    }

    /**
     * 将多个查询结果合并成一个总的统计数据
     *
     * @param summaries
     * @return
     */
    private List<PositionGradesInfoBoundVO> mergeResults(List<List<PositionGradesInfoBoundVO>> summaries) {
        // 将多个查询结果合并成一个总的统计数据
        if (!summaries.isEmpty()) {
            return summaries.stream().flatMap(List::stream).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 实际查询接口
     *
     * @param query
     * @param tenantId
     * @param headers
     * @return
     */
    private List<PositionGradesInfoBoundVO> executeQuerys(List<String> query, String tenantId, Map<String, String> headers) {
        return FeignHolder.sendFeign(headers, () -> {
            try {
                Map<String, UserBoundVO> userPrimaryBoundBatchCompatible = userApiV2Util.getUserPrimaryBoundBatch(query, tenantId);
                if (CollUtil.isEmpty(userPrimaryBoundBatchCompatible)) {
                    return new ArrayList<>();
                }
                List<PositionGradesInfoBoundVO> list = new ArrayList<>();
                //遍历
                for (Map.Entry<String, UserBoundVO> entry : userPrimaryBoundBatchCompatible.entrySet()) {
                    PositionGradesInfoBoundVO vo = new PositionGradesInfoBoundVO();
                    vo.setUserId(entry.getKey());
                    UserBoundVO value = entry.getValue();
                    vo.setOrganizeIds(List.of(value.getOrganizeId()));
                    vo.setOrganizeNames(List.of(value.getOrganizeName()));
                    vo.setPositionId(value.getPositionId());
                    vo.setPositionName(value.getPositionName());
                    vo.setPositionGradesId(value.getGradeId());
                    vo.setPositionGradesName(value.getGradeName());
                    vo.setUserId(entry.getKey());
                    list.add(vo);
                }
                return list;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRelation(String organizeId, UserRelationPositionGrades userRelationPositionGrades) {
        List<String> userIds = userRelationApi.saveRelationReturn(organizeId, userRelationPositionGrades);
        // 删除用户对应岗位的启动的晋升通道
        if (ObjectUtil.isNotEmpty(userIds)) {
            deleteMembersToProChannel(userIds);
            // 删除对应的岗位学习职等开启的课程
            String positionGradesId = userRelationPositionGrades.getPositionGradesId();
            userIds.forEach(str -> {
                ftbCultivatePositionService.deleteMemberGrade(positionGradesId, str);
            });

        }
    }

    @Override
    public List<FtbCultivatePromotionVO> queryPromotionByUserOrPostId(String userId, String postId) {
        return memberMapper.queryPromotionByUserOrPostId(userId, postId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addMembersToProChannel(FtbCultivatePromotionMemberDto dto) {
        List<FtbCultivatePromotionMember> list = new ArrayList<>();
        // 原始新增数据
        List<FtbCultivatePromotionMemberDto.PromotionUser> userIdVos = dto.getUserIds();
        List<String> userIds = userIdVos.stream().map(FtbCultivatePromotionMemberDto.PromotionUser::getUserId).collect(Collectors.toList());
        LambdaQueryWrapper<FtbCultivatePromotionMember> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbCultivatePromotionMember::getUserId, userIds);
        List<FtbCultivatePromotionMember> members = memberMapper.selectList(queryWrapper);
        // 查询是否存在数据
        List<FtbCultivatePromotionMember> updateList = members.stream().filter(item -> userIds.contains(item.getUserId())).collect(Collectors.toList());
        // 存在数据进行晋升通道更新
        updateList.forEach(item -> item.setPromotionId(dto.getPromotionId()));
        // 同步更新
        boolean flag = this.updateBatchById(updateList);
        // 过滤不存在的晋升通道的用户进行更新
        List<FtbCultivatePromotionMemberDto.PromotionUser> collect = userIdVos.stream().filter(item -> !updateList.stream()
                .map(FtbCultivatePromotionMember::getUserId).collect(Collectors.toList()).contains(item.getUserId())).collect(Collectors.toList());
        // 新增用户为空且修改用户为true 直接为全部都是修改
        if (flag && CollUtil.isEmpty(collect)) {
            return;
        }
        // 进行新增条件构建
        collect.forEach(userInfoVo -> {
            FtbCultivatePromotionMember member = new FtbCultivatePromotionMember();
            member.setPromotionId(dto.getPromotionId());
            member.setUserId(userInfoVo.getUserId());
            //用户姓名
            member.setUserName(userInfoVo.getUserName());
            member.setOrgId(userInfoVo.getOrgId());
            member.setOrgName(userInfoVo.getOrgName());
            member.setPositionId(userInfoVo.getPositionId());
            member.setPositionName(userInfoVo.getPositionName());
            member.setGradeId(userInfoVo.getGradeId());
            member.setGradeName(userInfoVo.getGradeName());
            member.setEnableStatus(1);
            // 默认允许启动晋升通道
            member.setState(0);
            list.add(member);
        });
        this.saveBatch(list);
    }

    @Override
    public FtbCultivatePromotionVO queryPromotionByUser(String userId, String postId) {
        return memberMapper.queryPromotionByUser(userId, postId);
    }

    @Override
    public void deleteMembersToProChannel(List<String> userIds) {
        LambdaUpdateWrapper<FtbCultivatePromotionMember> wrapper = Wrappers.lambdaUpdate();
        wrapper.in(FtbCultivatePromotionMember::getUserId, userIds);
        int delete = memberMapper.delete(wrapper);
        // 删除成功后
        if (delete > 0) {
            userIds.forEach(userId -> {
                CultivateMessageInfo messageInfo = new CultivateMessageInfo();
                messageInfo.setUserId(userId);
                messageInfo.setBusinessId(userId);
                messageInfo.setSource(0);
                messageInfo.setState(0);
                messageInfoMapper.insert(messageInfo);
            });
        }
    }

}
