package com.ningdatech.pmapi.meeting.helper;

import cn.hutool.core.util.RandomUtil;
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.RandomUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 专家抽取算法
 * </p>
 *
 * @author WendyYang
 * @since 2023/4/14
 **/
public class ExpertRandomInviteAlgorithm {

    private static boolean expertMatchNone(List<MeetingExpert> experts, ExpertUserFullInfo userInfo) {
        return experts.stream().noneMatch(w -> w.getExpertId().equals(userInfo.getUserId()));
    }

    /**
     * 每个单位只抽取一人
     *
     * @param expertGroupByUnit      需要抽取的人
     * @param expertsByRecentMeeting 最近会议抽取到的专家
     * @param count                  抽取数量
     * @return 抽取到的专家信息
     * @author WendyYang
     **/
    public static List<ExpertUserFullInfo> inviteGroupByCompany(Map<String, List<ExpertUserFullInfo>> expertGroupByUnit,
                                                                List<List<MeetingExpert>> expertsByRecentMeeting,
                                                                Integer count) {
        if (MapUtils.isEmpty(expertGroupByUnit)) {
            return Collections.emptyList();
        }
        if (expertsByRecentMeeting.isEmpty()) {
            return expertGroupByUnit.values().stream()
                    .map(RandomUtil::randomEle)
                    .limit(count).collect(Collectors.toList());
        } else {
            List<ExpertUserFullInfo> result = new ArrayList<>();
            List<String> keySet = new ArrayList<>(expertGroupByUnit.keySet());
            for (int i = 0; i < count; i++) {
                String company = keySet.get(RandomUtils.nextInt(0, keySet.size()));
                List<ExpertUserFullInfo> expertsByCompany = expertGroupByUnit.get(company);
                for (int j = 0; j < expertsByRecentMeeting.size(); j++) {
                    List<MeetingExpert> experts = expertsByRecentMeeting.get(j);
                    List<ExpertUserFullInfo> notInvitedUsers = expertsByCompany.stream()
                            .filter(w -> expertMatchNone(experts, w))
                            .collect(Collectors.toList());
                    if (!notInvitedUsers.isEmpty()) {
                        result.add(RandomUtil.randomEle(notInvitedUsers));
                        break;
                    } else if (j == (expertsByRecentMeeting.size() - 1)) {
                        result.add(RandomUtil.randomEle(expertsByCompany));
                    }
                }
                if (result.size() < count) {
                    keySet.remove(company);
                    if (keySet.isEmpty()) {
                        break;
                    }
                }
            }
            return result;
        }
    }

    /**
     * 随机抽取专家
     *
     * @param userFullInfos          可抽取的所有专家
     * @param expertsByRecentMeeting 最近会议抽取到的专家
     * @param count                  抽取数量
     * @return 抽取到的专家信息
     * @author WendyYang
     **/
    public static List<ExpertUserFullInfo> inviteWithoutCompany(List<ExpertUserFullInfo> userFullInfos,
                                                                List<List<MeetingExpert>> expertsByRecentMeeting,
                                                                Integer count) {
        List<ExpertUserFullInfo> result;
        if (expertsByRecentMeeting.isEmpty()) {
            result = RandomUtil.randomEleList(userFullInfos, count);
        } else {
            result = new ArrayList<>();
            for (List<MeetingExpert> experts : expertsByRecentMeeting) {
                List<ExpertUserFullInfo> notInvitedUsers = userFullInfos.stream()
                        .filter(w -> expertMatchNone(experts, w))
                        .collect(Collectors.toList());
                if (!notInvitedUsers.isEmpty()) {
                    result.addAll(notInvitedUsers);
                    if (result.size() >= count) {
                        return result.subList(0, count);
                    }
                    userFullInfos.removeAll(notInvitedUsers);
                }
            }
            if (userFullInfos.size() == 0) {
                return result;
            }
            int restCnt = Math.min(count - result.size(), userFullInfos.size());
            if (userFullInfos.size() > restCnt) {
                result.addAll(RandomUtil.randomEleList(userFullInfos, restCnt));
            } else {
                result.addAll(userFullInfos);
            }
        }
        return result;
    }

}
