package com.ningdatech.pmapi.meeting.helper;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.AbstractInviteRule;
import com.ningdatech.pmapi.meeting.entity.dto.AppointInviteRuleDTO;
import com.ningdatech.pmapi.meeting.entity.dto.AvoidRuleDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.service.IMeetingExpertService;
import com.ningdatech.pmapi.meeting.service.IMeetingService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * ExpertInviteHelper
 * </p>
 *
 * @author WendyYang
 * @since 16:35 2022/11/21
 */
@Slf4j
@Component
@AllArgsConstructor
public class ExpertInviteHelper {

    private final IMeetingService meetingService;
    private final IMeetingExpertService meetingExpertService;
    private final IExpertUserFullInfoService expertUserFullInfoService;

    /**
     * 获取时间段内被抽中的专家（通知中、确认参加）
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return java.util.List<java.lang.Long>
     * @author WendyYang
     **/
    public List<Long> listInvitedExpertByTime(LocalDateTime start, LocalDateTime end) {
        LambdaQueryWrapper<Meeting> meetingQuery = Wrappers.lambdaQuery(Meeting.class)
                .select(Meeting::getId)
                .and(wrapper -> wrapper.between(Meeting::getStartTime, start, end)
                        .or(wrapper1 -> wrapper1.between(Meeting::getEndTime, start, end)));
        List<Meeting> meetings = meetingService.list(meetingQuery);
        if (meetings.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> meetingIds = CollUtils.fieldList(meetings, Meeting::getId);
        LambdaQueryWrapper<MeetingExpert> meetingExpertQuery = Wrappers.lambdaQuery(MeetingExpert.class)
                .select(MeetingExpert::getExpertId)
                .in(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode(), ExpertAttendStatusEnum.NOTICING.getCode())
                .in(MeetingExpert::getMeetingId, meetingIds);
        List<MeetingExpert> meetingExperts = meetingExpertService.list(meetingExpertQuery);
        return CollUtils.fieldList(meetingExperts, MeetingExpert::getExpertId);
    }

    public Set<Long> listExpertLeaveOrInvited(LocalDateTime start, LocalDateTime end) {
        return new HashSet<>(listInvitedExpertByTime(start, end));
    }

    public Set<Long> getAvoidExpert(List<Long> appoints, AvoidRuleDTO avoid, LocalDateTime start, LocalDateTime end) {
        Set<Long> expertIds = new HashSet<>();
        Optional.ofNullable(appoints).ifPresent(expertIds::addAll);
        Optional.ofNullable(avoid)
                .flatMap(w -> Optional.ofNullable(w.getExpertIds()))
                .ifPresent(expertIds::addAll);
        // 过滤掉请假专家
        expertIds.addAll(listInvitedExpertByTime(start, end));
        return expertIds;
    }

    public Map<Long, ExpertUserFullInfo> checkAppointExpert(AppointInviteRuleDTO appointRule) {
        if (appointRule == null) {
            return Collections.emptyMap();
        }
        List<ExpertUserFullInfo> expertInfos = expertUserFullInfoService.listByUserId(appointRule.getExpertIdList());
        return CollUtils.listToMap(expertInfos, ExpertUserFullInfo::getUserId);
    }

    /**
     * 构建邀请规则
     *
     * @param rule      邀请规则
     * @param meetingId 会议ID
     * @return {@link ExpertInviteRule}
     * @author WendyYang
     **/
    public static ExpertInviteRule getExpertInviteRule(AbstractInviteRule rule, Long meetingId) {
        ExpertInviteRule result = new ExpertInviteRule();
        result.setInviteRule(JSONObject.toJSONString(rule));
        result.setInviteCount(rule.getCount());
        result.setInviteType(rule.getInviteType());
        result.setMeetingId(meetingId);
        return result;
    }

}
