package com.cool.store.service.impl;

import cn.hutool.core.date.DateUtil;
import com.cool.store.constants.CommonConstants;
import com.cool.store.dao.*;
import com.cool.store.dto.message.RemindInterviewMsgDTO;
import com.cool.store.dto.message.SendCardMessageDTO;
import com.cool.store.dto.partner.PartnerInterviewInfoDTO;
import com.cool.store.entity.*;
import com.cool.store.enums.MessageTypeEnum;
import com.cool.store.enums.RoomStatus;
import com.cool.store.enums.WorkflowStageEnum;
import com.cool.store.enums.WorkflowStatusEnum;
import com.cool.store.exception.ApiException;
import com.cool.store.http.ISVHttpRequest;
import com.cool.store.mapper.HyPartnerInterviewMapper;
import com.cool.store.mapper.HyPartnerInterviewPlanMapper;
import com.cool.store.mapper.HyPartnerLineInfoMapper;
import com.cool.store.request.CloseFollowRequest;
import com.cool.store.request.GetInterviewListReq;
import com.cool.store.service.HyPartnerInterviewPlanService;
import com.cool.store.service.HyPartnerLineInfoService;
import com.cool.store.service.InterviewService;
import com.cool.store.utils.CoolDateUtils;
import com.cool.store.vo.InterviewDetailInfoVO;
import com.cool.store.vo.PartnerInterviewInfoVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author suzhuhong
 * @Date 2023/6/8 19:32
 * @Version 1.0
 */
@Slf4j
@Service
public class HyPartnerInterviewPlanServiceImpl implements HyPartnerInterviewPlanService {

    @Resource
    HyPartnerInterviewPlanDAO hyPartnerInterviewPlanDAO;
    @Resource
    HyPartnerUserInfoDAO hyPartnerUserInfoDAO;

    @Resource
    HyPartnerLineInfoDAO hyPartnerLineInfoDAO;

    @Autowired
    HyPartnerInterviewPlanMapper hyPartnerInterviewPlanMapper;

    @Autowired
    HyPartnerInterviewMapper hyPartnerInterviewMapper;

    @Autowired
    HyPartnerLineInfoService hyPartnerLineInfoService;

    @Autowired
    HyPartnerLineInfoMapper hyPartnerLineInfoMapper;

    @Autowired
    private HyInterviewDAO interviewDAO;
    @Resource
    EnterpriseUserDAO enterpriseUserDAO;

    @Autowired
    private InterviewService interviewService;


    @Value("${feishu.notice.link.url:null}")
    private String linkUrl;

    @Autowired
    private ISVHttpRequest isvHttpRequest;
    @Override
    public List<InterviewDetailInfoVO> getInterviewPlanList(String userId,Date dateTime) {
        String currentDay = DateUtil.format(dateTime,  CoolDateUtils.DATE_FORMAT_DAY);
        String currentTime = DateUtil.format(dateTime,  CoolDateUtils.DATE_FORMAT_SEC);
        List<HyPartnerInterviewPlanDO> interviewPlanList = hyPartnerInterviewPlanDAO.getInterviewPlanList(userId, currentTime,currentDay);
        if (CollectionUtils.isEmpty(interviewPlanList)){
            return Lists.newArrayList();
        }
        List<String> partnerIdList = interviewPlanList.stream().map(HyPartnerInterviewPlanDO::getPartnerId).collect(Collectors.toList());
        List<HyPartnerUserInfoDO> hyPartnerUserInfoDOS = hyPartnerUserInfoDAO.selectByPartnerIds(partnerIdList);
        Map<String, HyPartnerUserInfoDO> hyPartnerUserInfoDOMap = hyPartnerUserInfoDOS.stream().collect(Collectors.toMap(HyPartnerUserInfoDO::getPartnerId, data -> data));
        List<InterviewDetailInfoVO> result = new ArrayList<>();
        interviewPlanList.stream().forEach(x->{
            InterviewDetailInfoVO interviewDetailInfoVO = convertDoToInterviewDetailInfoVO(x);
            HyPartnerUserInfoDO userInfoDO = hyPartnerUserInfoDOMap.getOrDefault(x.getPartnerId(), new HyPartnerUserInfoDO());
            interviewDetailInfoVO.setUserId(userInfoDO.getPartnerId());
            interviewDetailInfoVO.setUserName(userInfoDO.getUsername());
            interviewDetailInfoVO.setUserPhone(userInfoDO.getMobile());
            result.add(interviewDetailInfoVO);
        });
        return result;
    }

    @Override
    public PageInfo<PartnerInterviewInfoVO> getPartnerInterviewInfoList(String userId ,String type,Integer pageSize,Integer pageNumber) {
        String workflowStatus = "";
        Boolean filter = Boolean.FALSE;
        if (CommonConstants.PENDING.equals(type)) {
            workflowStatus = WorkflowStatusEnum.RESERVATION_1.getCode();
            filter = Boolean.TRUE;
        }
        if (CommonConstants.FOLLOW.equals(type)) {
            workflowStatus = WorkflowStatusEnum.RESERVATION_0.getCode();
        }
        PageHelper.startPage(pageNumber,pageSize);
        //查询预约面试列表
        PageInfo partnerInterviewInfoList = new PageInfo(hyPartnerInterviewPlanDAO.getPartnerInterviewInfoList(userId, WorkflowStageEnum.RESERVATION.getCode(), workflowStatus,filter));
        List<PartnerInterviewInfoDTO> list = partnerInterviewInfoList.getList();
        if (CollectionUtils.isEmpty(list)){
            return partnerInterviewInfoList;
        }
        List<PartnerInterviewInfoVO> result = new ArrayList<>();
        List<String> partnerIds = list.stream().map(PartnerInterviewInfoDTO::getPartnerId).collect(Collectors.toList());
        List<HyPartnerUserInfoDO> hyPartnerUserInfoDOS = hyPartnerUserInfoDAO.selectByPartnerIds(partnerIds);
        List<String> interviewerUserIds = list.stream().filter(x-> StringUtils.isNotEmpty(x.getInterviewer())).map(PartnerInterviewInfoDTO::getInterviewer).collect(Collectors.toList());
        List<EnterpriseUserDO> userInfoByUserIds = enterpriseUserDAO.getUserInfoByUserIds(interviewerUserIds);
        Map<String, EnterpriseUserDO> interviewerUserMap = userInfoByUserIds.stream().collect(Collectors.toMap(EnterpriseUserDO::getUserId, data -> data));
        Map<String, HyPartnerUserInfoDO> userNameMap = hyPartnerUserInfoDOS.stream().collect(Collectors.toMap(HyPartnerUserInfoDO::getPartnerId, Data->Data));
        List<Long> lineIds = list.stream().map(PartnerInterviewInfoDTO::getPartnerLineId).collect(Collectors.toList());
        List<HyPartnerLineInfoDO> hyPartnerLineInfoDOS= hyPartnerLineInfoDAO.getHyPartnerLineInfoListByIds(lineIds);
        Map<Long, HyPartnerLineInfoDO> hyPartnerLineInfoDOMap = hyPartnerLineInfoDOS.stream().collect(Collectors.toMap(HyPartnerLineInfoDO::getId, data -> data));
        list.stream().forEach(x->{
            PartnerInterviewInfoVO partnerInterviewInfoVO = convertPartnerInterviewInfoDTOToVo(x);
            partnerInterviewInfoVO.setPartnerName(userNameMap.getOrDefault(x.getPartnerId(),new HyPartnerUserInfoDO()).getUsername());
            partnerInterviewInfoVO.setPartnerPhone(userNameMap.getOrDefault(x.getPartnerId(),new HyPartnerUserInfoDO()).getMobile());
            partnerInterviewInfoVO.setInterviewerName(interviewerUserMap.getOrDefault(x.getInterviewer(),new EnterpriseUserDO()).getName());
            partnerInterviewInfoVO.setInterviewerPhone(interviewerUserMap.getOrDefault(x.getInterviewer(),new EnterpriseUserDO()).getMobile());
            partnerInterviewInfoVO.setLineStatus(hyPartnerLineInfoDOMap.getOrDefault(x.getPartnerLineId(),new HyPartnerLineInfoDO()).getLineStatus());
            partnerInterviewInfoVO.setLineId(hyPartnerLineInfoDOMap.getOrDefault(x.getPartnerLineId(),new HyPartnerLineInfoDO()).getId());
            result.add(partnerInterviewInfoVO);
        });
        partnerInterviewInfoList.setList(result);
        return partnerInterviewInfoList;
    }

    @Override
    public PageInfo<PartnerInterviewInfoVO> getQualifiedInterviewList(String userId, String type, Integer pageSize, Integer pageNumber) {
        String workflowStatus = "";
        if (CommonConstants.PENDING.equals(type)) {
            workflowStatus = WorkflowStatusEnum.INTERVIEW_4.getCode();
        }
        if (CommonConstants.FOLLOW.equals(type)) {
            workflowStatus = WorkflowStatusEnum.INTERVIEW_5.getCode();
        }

        PageHelper.startPage(pageNumber,pageSize);
        //查询预约面试列表
        PageInfo partnerInterviewInfoList = new PageInfo(hyPartnerInterviewPlanDAO.getPartnerInterviewInfoList(userId, WorkflowStageEnum.INTERVIEW.getCode(),workflowStatus,Boolean.TRUE));
        List<PartnerInterviewInfoDTO> list = partnerInterviewInfoList.getList();
        if (CollectionUtils.isEmpty(list)){
            return partnerInterviewInfoList;
        }
        List<String> partnerIds = list.stream().map(PartnerInterviewInfoDTO::getPartnerId).collect(Collectors.toList());
        List<HyPartnerUserInfoDO> hyPartnerUserInfoDOS = hyPartnerUserInfoDAO.selectByPartnerIds(partnerIds);
        Map<String, HyPartnerUserInfoDO> userNameMap = hyPartnerUserInfoDOS.stream().collect(Collectors.toMap(HyPartnerUserInfoDO::getPartnerId, Data->Data));
        List<Long> lineIds = list.stream().map(PartnerInterviewInfoDTO::getPartnerLineId).collect(Collectors.toList());
        List<HyPartnerLineInfoDO> hyPartnerLineInfoDOS= hyPartnerLineInfoDAO.getHyPartnerLineInfoListByIds(lineIds);
        Map<Long, HyPartnerLineInfoDO> hyPartnerLineInfoDOMap = hyPartnerLineInfoDOS.stream().collect(Collectors.toMap(HyPartnerLineInfoDO::getId, data -> data));
        List<PartnerInterviewInfoVO> result = new ArrayList<>();
        list.stream().forEach(x->{
            PartnerInterviewInfoVO partnerInterviewInfoVO = convertPartnerInterviewInfoDTOToVo(x);
            partnerInterviewInfoVO.setPartnerName(userNameMap.getOrDefault(x.getPartnerId(),new HyPartnerUserInfoDO()).getUsername());
            partnerInterviewInfoVO.setPartnerPhone(userNameMap.getOrDefault(x.getPartnerId(),new HyPartnerUserInfoDO()).getMobile());
            partnerInterviewInfoVO.setLineStatus(hyPartnerLineInfoDOMap.getOrDefault(x.getPartnerLineId(),new HyPartnerLineInfoDO()).getLineStatus());
            partnerInterviewInfoVO.setLineId(hyPartnerLineInfoDOMap.getOrDefault(x.getPartnerLineId(),new HyPartnerLineInfoDO()).getId());
            result.add(partnerInterviewInfoVO);
        });
        partnerInterviewInfoList.setList(result);
        return partnerInterviewInfoList;
    }

    @Override
    @Transactional
    public void updateInterviewOverTime() throws ApiException {
        List<HyPartnerLineInfoDO> overTimeReserveLineList = hyPartnerLineInfoMapper.getOverTimeReserveLineList(new Date(), WorkflowStageEnum.RESERVATION.getCode(), WorkflowStatusEnum.RESERVATION_0.getCode());
        if(CollectionUtils.isEmpty(overTimeReserveLineList)){
            return;
        }
        List<Long> lineIds = overTimeReserveLineList.stream().map(o -> o.getId()).collect(Collectors.toList());
        for (Long lineId : lineIds) {
            CloseFollowRequest closeFollowRequest = new CloseFollowRequest();
            closeFollowRequest.setRejectPublicReason("超时未预约");
            closeFollowRequest.setRejectRealReason("超时未预约");
            closeFollowRequest.setLineId(lineId);
            closeFollowRequest.setType("overtime_interview");
            hyPartnerLineInfoService.closeOrPassFollow(null,closeFollowRequest);
        }
    }

    @Override
    @Transactional
    public void openInterviewRoom() {
        //更新会议开始时间为5分钟之内的房间状态为开启,会议状态变为已开始
        Date startTime = new Date();

        List<HyPartnerLineInfoDO> waitForOpenInterviewLineList = hyPartnerLineInfoMapper.getWaitForOpenInterviewLineList(DateUtil.offsetDay(startTime,-2), DateUtil.offsetMinute(startTime, 5));
        if(CollectionUtils.isEmpty(waitForOpenInterviewLineList)){
            return;
        }
        //更新房间状态为开启
        List<Long> lineIds = waitForOpenInterviewLineList.stream().map(HyPartnerLineInfoDO::getId).collect(Collectors.toList());
        hyPartnerInterviewPlanMapper.openInterviewRoom(lineIds,RoomStatus.OPEN.getCode());
        interviewDAO.batchUpdateInterviewWorkflowStatus(lineIds,Integer.parseInt(WorkflowStatusEnum.INTERVIEW_3.getCode()));
    }

    @Override
    @Transactional
    public void updateAbsentInterview() throws ApiException {
        Date now = new Date();
        //查询当天未参加的面试
        String startTime = DateUtil.formatDateTime(DateUtil.offsetHour(now,-6));
        String endTime = DateUtil.formatDateTime(now);
        GetInterviewListReq getInterviewListReq = new GetInterviewListReq();
        getInterviewListReq.setStartTime(startTime);
        getInterviewListReq.setEndTime(endTime);
        getInterviewListReq.setStatus(Integer.valueOf(WorkflowStatusEnum.INTERVIEW_3.getCode()));
        getInterviewListReq.setIsPartnerInterview(0);
        List<HyPartnerInterviewDO> interviewBaseInfoList = hyPartnerInterviewMapper.getInterviewBaseInfoList(getInterviewListReq);
        if(CollectionUtils.isEmpty(interviewBaseInfoList)){
            return;
        }
        handleOverTimeInterview(interviewBaseInfoList,"超时未面试");
    }

    @Override
    public void approvalReminder() throws ApiException {
        //查询即将超时但未审批的面试
        Date startTime = new Date();
        Date endTime = DateUtil.offsetMinute(startTime,30);
        List<RemindInterviewMsgDTO> remindInterviewMsgDTOS = hyPartnerInterviewPlanMapper.selectRemindInterviewPlan(startTime, endTime, WorkflowStageEnum.RESERVATION.getCode(), WorkflowStatusEnum.RESERVATION_1.getCode());
        if(CollectionUtils.isEmpty(remindInterviewMsgDTOS)){
            return;
        }
        //发送消息
        remindInterviewMsgDTOS.stream().forEach(interviewMsgDTO->{
            try {
                List<String> userIds = new ArrayList<>();
                userIds.add(interviewMsgDTO.getInterviewerId());
                SendCardMessageDTO sendCardMessageDTO = new SendCardMessageDTO();
                sendCardMessageDTO.setUserIds(userIds);
                sendCardMessageDTO.setMessageType(MessageTypeEnum.SCHEDULE_REMINDER);
                sendCardMessageDTO.setMessageUrl(linkUrl);
                sendCardMessageDTO.setTitle("面试预约申请");
                sendCardMessageDTO.setContent(interviewService.generateFeiShuInterviewMsg(interviewMsgDTO.getPartnerName(), interviewMsgDTO.getPartnerMobile(), interviewMsgDTO.getStartTime()));
                isvHttpRequest.sendFeiShuCardMessage(sendCardMessageDTO);
            } catch (ApiException e) {
                log.error("发送面试提醒消息失败",e);
            }
        });
    }

    /**
     * 统一处理面试超时情况，包括超时未预约和超时未面试
     * @param interviewBaseInfoList
     * @param rejectPublicReason
     */
    public void handleOverTimeInterview(List<HyPartnerInterviewDO> interviewBaseInfoList,String rejectPublicReason) throws ApiException {
        //1.更新面试信息表中超时的面试信息
        List<Long> interviewIds = interviewBaseInfoList.stream().map(HyPartnerInterviewDO::getId).distinct().collect(Collectors.toList());
        hyPartnerInterviewMapper.batchUpdateInterviewStatus(interviewIds,Integer.valueOf(WorkflowStatusEnum.RESERVATION_8.getCode()),1);
        //2.更新面试计划表中超时的信息
        List<Long> interviewPlanIds = interviewBaseInfoList.stream().map(HyPartnerInterviewDO::getInterviewPlanId).distinct().collect(Collectors.toList());
        hyPartnerInterviewPlanMapper.batchDeleteInterviewPlans(interviewPlanIds);
        //3.更新线索表中超时未预约的线路信息
        List<Long> lineIds = interviewBaseInfoList.stream().map(HyPartnerInterviewDO::getPartnerLineId).distinct().collect(Collectors.toList());
        for (Long lineId : lineIds) {
            CloseFollowRequest closeFollowRequest = new CloseFollowRequest();
            closeFollowRequest.setRejectPublicReason(rejectPublicReason);
            closeFollowRequest.setRejectRealReason(rejectPublicReason);
            closeFollowRequest.setLineId(lineId);
            closeFollowRequest.setType("overtime_interview");
            hyPartnerLineInfoService.closeOrPassFollow(null,closeFollowRequest);
        }
    }
    /**
     * convertDoToInterviewDetailInfoVO
     * @param hyPartnerInterviewPlanDO
     * @return
     */
    private InterviewDetailInfoVO convertDoToInterviewDetailInfoVO(HyPartnerInterviewPlanDO hyPartnerInterviewPlanDO){
        InterviewDetailInfoVO interviewDetailInfoVO = new InterviewDetailInfoVO();
        if (hyPartnerInterviewPlanDO==null){
            return interviewDetailInfoVO;
        }
        interviewDetailInfoVO.setLineId(hyPartnerInterviewPlanDO.getPartnerLineId());
        interviewDetailInfoVO.setStartTime(hyPartnerInterviewPlanDO.getStartTime());
        interviewDetailInfoVO.setInterviewPlanId(hyPartnerInterviewPlanDO.getId());
        return interviewDetailInfoVO;
    }

    /**
     * PartnerInterviewInfoDTOToVo
     * @param partnerInterviewInfoDTO
     * @return
     */
    private PartnerInterviewInfoVO convertPartnerInterviewInfoDTOToVo(PartnerInterviewInfoDTO partnerInterviewInfoDTO){
        PartnerInterviewInfoVO partnerInterviewInfoVO = new PartnerInterviewInfoVO();
        partnerInterviewInfoVO.setInterviewId(partnerInterviewInfoDTO.getInterviewId());
        partnerInterviewInfoVO.setInterviewPlanId(partnerInterviewInfoDTO.getId());
        partnerInterviewInfoVO.setPartnerId(partnerInterviewInfoDTO.getPartnerId());
        partnerInterviewInfoVO.setInterviewerId(partnerInterviewInfoDTO.getInterviewer());
        partnerInterviewInfoVO.setProcessInfo(partnerInterviewInfoDTO.getProcessInfo());
        partnerInterviewInfoVO.setCreateTime(DateUtil.format(partnerInterviewInfoDTO.getCreateTime(),CoolDateUtils.DATE_FORMAT_SEC_2));
        partnerInterviewInfoVO.setRoomId(partnerInterviewInfoDTO.getRoomId());
        partnerInterviewInfoVO.setDeadline(DateUtil.format(partnerInterviewInfoDTO.getDeadline(),CoolDateUtils.DATE_FORMAT_SEC_2));
        partnerInterviewInfoVO.setStartTime(DateUtil.format(partnerInterviewInfoDTO.getStartTime(),CoolDateUtils.DATE_FORMAT_SEC_2));
        partnerInterviewInfoVO.setStatus(partnerInterviewInfoDTO.getStatus());
        partnerInterviewInfoVO.setAuthCode(partnerInterviewInfoDTO.getIntentionContractNo());
        partnerInterviewInfoVO.setEndTime(DateUtil.format(partnerInterviewInfoDTO.getEndTime(),CoolDateUtils.DATE_FORMAT_SEC_2));
        partnerInterviewInfoVO.setApproveTime(DateUtil.format(partnerInterviewInfoDTO.getApproveTime(),CoolDateUtils.DATE_FORMAT_SEC_2));
        return partnerInterviewInfoVO;
    }

}
