package com.ningdatech.pmapi.meeting.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.meeting.entity.domain.ExpertInviteRule;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert;
import com.ningdatech.pmapi.meeting.entity.dto.CountConfirmByMeetingIdDTO;
import com.ningdatech.pmapi.meeting.entity.dto.MeetingAndAttendStatusDTO;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.ningdatech.pmapi.meeting.mapper.ExpertInviteRuleMapper;
import com.ningdatech.pmapi.meeting.mapper.MeetingExpertMapper;
import com.ningdatech.pmapi.meeting.service.IMeetingExpertService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 事务专家表 服务实现类
 * </p>
 *
 * @author WendyYang
 * @since 2022-07-27
 */
@Service
@RequiredArgsConstructor
public class MeetingExpertServiceImpl extends ServiceImpl<MeetingExpertMapper, MeetingExpert> implements IMeetingExpertService {

    private final ExpertInviteRuleMapper inviteRuleMapper;

    @Override
    public List<MeetingAndAttendStatusDTO> listByExpertIdAndStatus(Long expertId, Integer status, List<Long> meetingIds) {
        return baseMapper.selectByExpertIdAndStatus(expertId, status, meetingIds);
    }

    @Override
    public Map<Long, CountConfirmByMeetingIdDTO> countConfirmedByMeetingIds(List<Long> meetingIds) {
        List<ExpertInviteRule> inviteRules = inviteRuleMapper.selectList(Wrappers.lambdaQuery(ExpertInviteRule.class)
                .eq(ExpertInviteRule::getInviteType, ExpertInviteTypeEnum.RANDOM.getCode())
                .in(ExpertInviteRule::getMeetingId, meetingIds));
        Map<Long, Integer> countByRandom = CollUtils.groupSumInt(inviteRules, ExpertInviteRule::getMeetingId, ExpertInviteRule::getInviteCount);
        Page<MeetingExpert> page = pageExpertByStatusAndMeetingIds(new Page<>(0, 500), meetingIds, null);
        return page.getRecords().stream().collect(Collectors.groupingBy(MeetingExpert::getMeetingId,
                Collectors.collectingAndThen(Collectors.toList(),
                        w -> {
                            Long meetingId = w.get(0).getMeetingId();
                            CountConfirmByMeetingIdDTO confirm = CountConfirmByMeetingIdDTO.builder()
                                    .confirmed(0)
                                    .total(countByRandom.getOrDefault(meetingId, 0))
                                    .meetingId(meetingId)
                                    .build();
                            w.forEach(item -> {
                                ExpertAttendStatusEnum attendStatus = ExpertAttendStatusEnum.getByCode(item.getStatus());
                                if (ExpertInviteTypeEnum.APPOINT.eq(item.getInviteType())) {
                                    confirm.setTotal(confirm.getTotal() + 1);
                                }
                                // 除通知中的均为已确认
                                if (attendStatus.equals(ExpertAttendStatusEnum.AGREED)) {
                                    confirm.setConfirmed(confirm.getConfirmed() + 1);
                                }
                            });
                            return confirm;
                        })));
    }

    @Override
    public List<MeetingExpert> listByMeetingId(Long meetingId) {
        LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class)
                .eq(MeetingExpert::getMeetingId, meetingId)
                .orderByDesc(MeetingExpert::getUpdateOn);
        return list(query);
    }

    @Override
    public List<MeetingExpert> listByMeetingIds(List<Long> meetingIds) {
        LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class)
                .in(MeetingExpert::getMeetingId, meetingIds)
                .orderByDesc(MeetingExpert::getUpdateOn);
        return list(query);
    }

    @Override
    public MeetingExpert getByMeetingIdAndExpertId(Long meetingId, Long expertId) {
        LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class)
                .eq(MeetingExpert::getExpertId, expertId)
                .eq(MeetingExpert::getMeetingId, meetingId)
                .orderByDesc(MeetingExpert::getUpdateOn)
                .last("limit 1");
        return getOne(query);
    }

    @Override
    public Page<MeetingExpert> pageExpertByStatusAndMeetingId(Page<MeetingExpert> page, Long meetingId, ExpertAttendStatusEnum status, Integer inviteType) {
        return baseMapper.selectExpertByStatusAndMeetingId(page, status.getCode(), meetingId, inviteType);
    }

    @Override
    public Page<MeetingExpert> pageExpertByStatusAndMeetingIds(Page<MeetingExpert> page, List<Long> meetingIds, ExpertAttendStatusEnum status) {
        return baseMapper.selectExpertByStatusAndMeetingIds(page, status == null ? null : status.getCode(), meetingIds);
    }

    @Override
    public int countExpertByStatusAndMeetingId(ExpertAttendStatusEnum status, Long meetingId, ExpertInviteTypeEnum inviteType) {
        Integer tempStatus = status == null ? null : status.getCode();
        Integer tempInviteType = inviteType == null ? null : inviteType.getCode();
        return baseMapper.countExpertByStatusAndMeetingId(tempStatus, meetingId, tempInviteType);
    }

    @Override
    public List<MeetingExpert> listAgreedExperts(Collection<Long> meetingIds) {
        LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class)
                .eq(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode())
                .in(MeetingExpert::getMeetingId, meetingIds);
        return baseMapper.selectList(query);
    }

    @Override
    public List<MeetingExpert> listExpertLastByMeetingIds(Collection<Long> meetingIds) {
        return baseMapper.listExpertLastByMeetingIds(meetingIds);
    }

}
