package com.hz.pm.api.meeting.helper;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.CollUtils;
import com.hz.pm.api.meeting.constant.MeetingMsgTemplateConst;
import com.hz.pm.api.meeting.entity.domain.Meeting;
import com.hz.pm.api.meeting.entity.domain.MeetingExpert;
import com.hz.pm.api.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.hz.pm.api.meeting.entity.enumeration.MeetingReviewTypeEnum;
import com.hz.pm.api.organization.model.entity.DingEmployeeInfo;
import com.hz.pm.api.organization.model.entity.DingOrganization;
import com.hz.pm.api.organization.service.IDingEmployeeInfoService;
import com.hz.pm.api.organization.service.IDingOrganizationService;
import com.hz.pm.api.sms.constant.VoiceSmsTemplateConst;
import com.hz.pm.api.sms.utils.DateUtil;
import com.hz.pm.api.staging.enums.MsgTypeEnum;
import com.hz.pm.api.staging.service.INdWorkNoticeStagingService;
import com.hz.pm.api.sys.model.entity.Notify;
import com.hz.pm.api.sys.service.INotifyService;
import com.hz.pm.api.todocenter.bean.entity.WorkNoticeInfo;
import com.hz.pm.api.user.model.entity.UserInfo;
import com.hz.pm.api.user.service.IUserInfoService;
import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.SubmitTaskCallContext;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * MeetingMsgHelper
 * </p>
 *
 * @author WendyYang
 * @since 2023/4/20
 **/
@Component
@AllArgsConstructor
public class MeetingCallOrMsgHelper {

    private final IUserInfoService userInfoService;
    private final YxtCallOrSmsHelper yxtCallOrSmsHelper;
    private final INdWorkNoticeStagingService workNoticeStagingService;
    private final IDingEmployeeInfoService dingEmployeeInfoService;
    private final IDingOrganizationService dingOrganizationService;
    private final INotifyService notifyService;

    private static String officialTime(LocalDateTime time) {
        return time.format(DateUtil.DTF_YMD_HM);
    }

    private Notify getNotify(Long userId, String msg, MsgTypeEnum type, Map<String, Object> extraPara) {
        Notify notify = new Notify();
        notify.setUserId(userId);
        notify.setContent(msg);
        notify.setType(type.name());
        notify.setReaded(Boolean.FALSE);
        notify.setCreateTime(LocalDateTime.now());
        String extraJson = JSON.toJSONString(extraPara);
        notify.setExtraInfo(extraJson);
        return notify;
    }

    private WorkNoticeInfo getSendWorkNoticeInfo(Long accountId) {
        WorkNoticeInfo workNoticeInfo = new WorkNoticeInfo();
        workNoticeInfo.setAccountId(accountId);
        // 根据浙政钉用户ID获取部门code
        DingEmployeeInfo employeeInfo = dingEmployeeInfoService.getOne(Wrappers.lambdaQuery(DingEmployeeInfo.class)
                .eq(DingEmployeeInfo::getAccountId, accountId)
                .eq(DingEmployeeInfo::getMainJob, String.valueOf(Boolean.TRUE))
                .last("limit 1"));
        String organizationCode = employeeInfo.getOrganizationCode();
        workNoticeInfo.setOrganizationCode(organizationCode);
        // 根据部门code获取部门名称
        DingOrganization dingOrganization = dingOrganizationService.getOne(Wrappers.lambdaQuery(DingOrganization.class)
                .eq(DingOrganization::getOrganizationCode, organizationCode));
        String organizationName = dingOrganization.getOrganizationName();
        workNoticeInfo.setOrganizationName(organizationName);
        // 构建唯一的消息ID
        String bizMsgId = "ZD_WORK_NOTICE_" + StrUtil.UNDERLINE + organizationCode + StrUtil.UNDERLINE
                + organizationName + accountId + StrUtil.UNDERLINE + System.currentTimeMillis();
        workNoticeInfo.setBizMsgId(bizMsgId);
        String receiverUserId = String.valueOf(accountId);
        workNoticeInfo.setReceiverUserId(receiverUserId);
        return workNoticeInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    public void sendInviteStopMsg(Long userId, Long meetingId, String meetingName) {
        UserInfo info = userInfoService.getById(userId);
        String msgContent = String.format(MeetingMsgTemplateConst.INVITE_END, meetingName);
        // 音信通消息
        SendSmsContext yxtContent = new SendSmsContext();
        yxtContent.setContent(msgContent);
        yxtContent.setReceiveNumber(info.getMobile());
        yxtCallOrSmsHelper.sendSms(yxtContent);
        // 发送工作通知
        if (info.getAccountId() != null) {
            WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
            swn.setMsg(msgContent);
            workNoticeStagingService.addByWorkNotice(swn, MsgTypeEnum.REVIEW_MEETING);
            Map<String, Object> map = new HashMap<>(2);
            map.put("meetingId", meetingId);
            Notify notify = getNotify(userId, msgContent, MsgTypeEnum.REVIEW_MEETING, map);
            notifyService.save(notify);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void sendConfirmedRosterMsg(List<MeetingExpert> experts, Meeting meeting) {
        List<Long> userIds = CollUtils.fieldList(experts, MeetingExpert::getExpertId);
        List<UserInfo> userInfos = userInfoService.listByIds(userIds);
        Map<Long, UserInfo> userMap = CollUtils.listToMap(userInfos, UserInfo::getId);
        String sTime = officialTime(meeting.getStartTime());
        String eTime = officialTime(meeting.getEndTime());
        String meetingTime = sTime + "至" + eTime;
        List<SendSmsContext> yxtContents = new ArrayList<>();
        List<Notify> notifies = new ArrayList<>();
        List<WorkNoticeInfo> workingNotices = new ArrayList<>();
        experts.forEach(w -> {
            String msgContent = String.format(MeetingMsgTemplateConst.CONFIRMED_ROSTER,
                    w.getExpertName(), officialTime(w.getCreateOn()), meetingTime, meeting.getMeetingAddress(),
                    meeting.getConnecter(), meeting.getContact());
            // 音信通消息
            SendSmsContext yxtContent = new SendSmsContext();
            yxtContent.setContent(msgContent);
            yxtContent.setReceiveNumber(w.getMobile());
            yxtContents.add(yxtContent);
            UserInfo info = userMap.get(w.getExpertId());
            // 发送工作通知
            if (info.getAccountId() != null) {
                WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
                swn.setMsg(msgContent);
                workingNotices.add(swn);
                Map<String, Object> map = new HashMap<>(2);
                map.put("meetingId", meeting.getId());
                Notify notify = getNotify(info.getId(), msgContent, MsgTypeEnum.EXPERT_REVIEW, map);
                notifies.add(notify);
            }
        });
        notifyService.saveBatch(notifies);
        yxtCallOrSmsHelper.sendSms(yxtContents);
        workNoticeStagingService.addByWorkNotice(workingNotices, MsgTypeEnum.EXPERT_REVIEW);
    }


    public void sendCancelMeetingMsg(List<MeetingExpert> experts, Meeting meeting) {
        String startTime = officialTime(meeting.getStartTime());
        String meetingType = MeetingReviewTypeEnum.getValue(meeting.getType());
        List<SendSmsContext> contexts = experts.stream().map(w -> {
            String content = String.format(MeetingMsgTemplateConst.MEETING_CANCEL,
                    w.getExpertName(), startTime, meetingType, meeting.getContact());
            SendSmsContext context = new SendSmsContext();
            context.setReceiveNumber(w.getMobile());
            context.setContent(content);
            return context;
        }).collect(Collectors.toList());
        yxtCallOrSmsHelper.sendSms(contexts);
    }

    /**
     * 提交专家通知音信通任务
     *
     * @param meeting 会议信息
     * @param experts 待通知专家
     * @author WendyYang
     **/
    public void callExpertByMeeting(Meeting meeting, List<MeetingExpert> experts) {
        String voiceContent = String.format(VoiceSmsTemplateConst.OFFLINE_TEMPLATE,
                meeting.getHoldOrg(), meeting.getName(), officialTime(meeting.getStartTime()),
                meeting.getMeetingAddress());
        List<SubmitTaskCallContext> callContexts = CollUtils.convert(experts, w -> {
            SubmitTaskCallContext context = new SubmitTaskCallContext();
            context.setContent(voiceContent);
            context.setReceiveNumber(w.getMobile());
            return context;
        });
        String submitKey = yxtCallOrSmsHelper.submitCallTask(callContexts);
        experts.forEach(w -> w.setSubmitKey(submitKey));
    }

    public void sendExpertLeaveMsg(MeetingExpert expert, Meeting meeting) {
        Long userId = meeting.getCreateBy();
        String msgContent;
        if (ExpertInviteTypeEnum.RANDOM.eq(meeting.getInviteType())) {
            msgContent = String.format(MeetingMsgTemplateConst.EXPERT_LEAVE_RANDOM, meeting.getName());
        } else {
            msgContent = String.format(MeetingMsgTemplateConst.EXPERT_LEAVE_APPOINT, meeting.getName(), expert.getExpertName());
        }
        UserInfo info = userInfoService.getById(userId);
        SendSmsContext yxtContent = new SendSmsContext();
        yxtContent.setContent(msgContent);
        yxtContent.setReceiveNumber(info.getMobile());
        yxtCallOrSmsHelper.sendSms(yxtContent);
        // 发送工作通知
        if (info.getAccountId() != null) {
            WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
            swn.setMsg(msgContent);
            workNoticeStagingService.addByWorkNotice(swn, MsgTypeEnum.REVIEW_MEETING);
            Map<String, Object> map = new HashMap<>(2);
            map.put("meetingId", meeting.getId());
            Notify notify = getNotify(userId, msgContent, MsgTypeEnum.REVIEW_MEETING, map);
            notifyService.save(notify);
        }
    }

}
