package com.yida.data.school.news.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.job.Job;
import com.yida.data.common.core.entity.notice.EduNoticeSchool;
import com.yida.data.common.core.entity.notice.EduNoticeSchoolRead;
import com.yida.data.common.core.entity.notice.EduNoticeSchoolReceiveStudent;
import com.yida.data.common.core.entity.notice.EduNoticeSchoolReceiver;
import com.yida.data.common.core.entity.notice.app.AppNotice;
import com.yida.data.common.core.entity.notice.app.inside.PushMessage;
import com.yida.data.common.core.entity.notice.qywx.ImageSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.NewsSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.TextSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.VideoSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.inside.*;
import com.yida.data.common.core.entity.school.EduSchoolHomeAnnouncement;
import com.yida.data.common.core.entity.school.EduSchoolManuscript;
import com.yida.data.common.core.entity.school.EduYidaAppAccount;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduApp;
import com.yida.data.common.core.entity.system.EduYidaApp;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.utils.AppUtil;
import com.yida.data.common.core.utils.FileUtil;
import com.yida.data.common.core.utils.RegexUtil;
import com.yida.data.common.core.utils.WxUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.job.feign.RemoteJobService;
import com.yida.data.school.dto.news.ListNoticeDTO;
import com.yida.data.school.index.mapper.EduSchoolHomeAnnouncementMapper;
import com.yida.data.school.news.mapper.EduNoticeSchoolMapper;
import com.yida.data.school.news.service.*;
import com.yida.data.school.vo.news.*;
import com.yida.data.user.dto.ListStudentDTO;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
@Slf4j
@RefreshScope
@Transactional(rollbackFor = Exception.class)
public class EduNoticeSchoolServiceImpl extends ServiceImpl<EduNoticeSchoolMapper, EduNoticeSchool> implements
    EduNoticeSchoolService {

    private static final String SCHOOL_NOTICE_DETAIL = "/attendance/news/details.html";
    private static final String NOTICE_JOB_METHOD = "sendSchoolNotice";
    private static final String NOTICE_JOB_BEAN = "schoolNoticeTask";
    private static final Integer NOTICE_CONTENT_LENGTH = 54;
    private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setNamePrefix("publish-school-notice-")
        .build();
    private static final ExecutorService PUBLISH_THREAD_POOL =
        new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), THREAD_FACTORY);
    private final EduNoticeSchoolReceiverService eduNoticeSchoolReceiverService;
    private final EduNoticeSchoolReceiveStudentService eduNoticeSchoolReceiveStudentService;
    private final EduNoticeSchoolReadService eduNoticeSchoolReadService;
    private final EduSchoolManuscriptService eduSchoolManuscriptService;
    private final EduSchoolHomeAnnouncementMapper eduSchoolHomeAnnouncementMapper;

    private final WxUtil wxUtil;
    private final CommonService commonService;
    private final RemoteJobService remoteJobService;
    private final RemoteStudentService remoteStudentService;
    @Value("${febs.pageUrl}")
    private String pageUrl;

    @Value("${febs.uploadUrl}")
    private String uploadUrl;

    @Override
    public void saveNotice(EduNoticeSchool noticeSchool, CurrentUser currentUser) {
        noticeSchool.setSchoolId(currentUser.getDeptId());
        noticeSchool.setSchoolName(currentUser.getDeptName());
        noticeSchool.setDelFlag(0);
        if (noticeSchool.getId() != null) {
            EduNoticeSchool existNotice = getById(noticeSchool.getId());
            // 删除原有接收人
            eduNoticeSchoolReceiverService.remove(Wrappers.lambdaQuery(new EduNoticeSchoolReceiver())
                .eq(EduNoticeSchoolReceiver::getNoticeId, noticeSchool.getId()));
            // 删除原有未确认名单
            eduNoticeSchoolReceiveStudentService.remove(Wrappers.lambdaQuery(new EduNoticeSchoolReceiveStudent())
                .eq(EduNoticeSchoolReceiveStudent::getNoticeId, noticeSchool.getId()));
            // 删除原有的定时任务
            if (noticeSchool.getIsTiming() == 1 && existNotice.getIsTiming() == 0) {
                remoteJobService.delJobByMethod(NOTICE_JOB_BEAN, NOTICE_JOB_METHOD,
                    noticeSchool.getId().toString());
            }
        }
        noticeSchool.setStatus(0);
        if (noticeSchool.getType() == 0) {
            Matcher matcher1 = RegexUtil.BASE64_IMG_HEAD_PATTERN.matcher(noticeSchool.getContent());
            Matcher matcher2 = RegexUtil.BASE64_IMG_PATTERN.matcher(noticeSchool.getContent());
            if (matcher1.find()) {
                matcher2.find();
                for (int i = 0; i < matcher1.groupCount(); i++) {
                    String base64 = matcher1.group(i);
                    if (base64 == null || base64.length() < 22 || matcher2.group(i) == null || StrUtil
                        .isBlankIfStr(matcher2.group(i))) {
                        continue;
                    }
                    String path = FileUtil.uploadBase64Img(matcher2.group(i), "png");
                    String url = FileUtil.uploadFileToMediaServer(uploadUrl, path).split(",")[0];
                    noticeSchool.setContent(noticeSchool.getContent().replace(base64, url));
                }
            }
        }
        // 保存学校通知
        saveOrUpdate(noticeSchool);
        noticeSchool.getReceiverList().forEach(x -> x.setNoticeId(noticeSchool.getId()));
        noticeSchool.getReceiveStudentList().forEach(x -> x.setNoticeId(noticeSchool.getId()));
        // 保存实际接收的学生名单数据
        eduNoticeSchoolReceiveStudentService.saveBatch(noticeSchool.getReceiveStudentList());
        noticeSchool.setReceiverNum(
            (int) noticeSchool.getReceiveStudentList().stream().map(EduNoticeSchoolReceiveStudent::getParentId).distinct()
                .count());
        updateById(noticeSchool);
        // 保存接收对象数据
        eduNoticeSchoolReceiverService.saveBatch(noticeSchool.getReceiverList());
        // 非草稿处理通知发送
        if (noticeSchool.getIsDraft() == null || noticeSchool.getIsDraft() == 0) {
            if (noticeSchool.getIsTiming() == 1) {
                // 立即发送
                this.sendNotice(noticeSchool);
            } else {
                // 延时发送,添加定时任务
                LocalDateTime sendDate = noticeSchool.getSendDate();
                Job job = new Job();
                job.setBeanName(NOTICE_JOB_BEAN);
                job.setMethodName(NOTICE_JOB_METHOD);
                job.setParams(noticeSchool.getId().toString());
                // cron表达式
                String cron = sendDate.getSecond()
                    + " "
                    + sendDate.getMinute()
                    + " "
                    + sendDate.getHour()
                    + " "
                    + sendDate.getDayOfMonth()
                    + " "
                    + sendDate.getMonthValue()
                    + " ? "
                    + sendDate.getYear();
                job.setCronExpression(cron);
                job.setRemark(String.format("学校公告定时发送[%s]", noticeSchool.getSchoolName()));
                job.setStatus(Job.ScheduleStatus.NORMAL.getValue());
                remoteJobService.saveJob(job);
            }
        }
    }

    @Override
    @Transactional
    public void removeNotice(List<Long> noticeIds) {
        List<EduNoticeSchool> list = list(Wrappers.<EduNoticeSchool>lambdaQuery()
            .in(EduNoticeSchool::getId, noticeIds)
            .eq(EduNoticeSchool::getIsTiming, 0));
        if (CollUtil.isNotEmpty(list)) {
            // 删除定时任务
            list.forEach(
                x -> remoteJobService.delJobByMethod(NOTICE_JOB_BEAN, NOTICE_JOB_METHOD, x.getId().toString()));
        }
        removeByIds(noticeIds);
        eduNoticeSchoolReceiverService
            .remove(Wrappers.lambdaQuery(new EduNoticeSchoolReceiver()).in(EduNoticeSchoolReceiver::getNoticeId, noticeIds));
        eduNoticeSchoolReceiveStudentService
            .remove(Wrappers.lambdaQuery(new EduNoticeSchoolReceiveStudent())
                .in(EduNoticeSchoolReceiveStudent::getNoticeId, noticeIds));
    }

    @Override
    public void sendNotice(EduNoticeSchool notice) {
        Dept school = commonService.getDept(notice.getSchoolId());
        // 接收家长列表去重
        notice.setReceiveStudentList(notice.getReceiveStudentList().stream().peek(x -> {
            x.setId(null);
            x.setStudentId(null);
        }).distinct().collect(Collectors.toList()));
        PUBLISH_THREAD_POOL.execute(() -> {
            // 易达app进行消息推送
            if (school.getSchoolType().contains(Dept.TYPE_YIDA_APP)) {
                // 易达app端发送消息
                List<EduNoticeSchoolReceiveStudent> receiverList = notice.getReceiveStudentList();
                EduYidaApp yidaApp = commonService.getYidaApp(notice.getSchoolId());
                if (CollUtil.isNotEmpty(receiverList)) {
                    EduYidaAppAccount account = commonService.getYidaAppAccount(notice.getSchoolId(), 0);
                    List<String> parentYidaUserIdList = receiverList.stream().map(
                        EduNoticeSchoolReceiveStudent::getParentYidaAppId)
                        .collect(Collectors.toList());
                    AppNotice appNotice = new AppNotice();
                    appNotice.setUserIds(parentYidaUserIdList);
                    List<PushMessage> msgList = new ArrayList<>();
                    if (notice.getType() == 0) {
                        PushMessage pushMessage = new PushMessage();
                        pushMessage.setTitle(notice.getTitle());
                        pushMessage.setImgUrl(notice.getCoverUrl());
                        pushMessage.setAccountId(account.getYidaAppAccountId());
                        pushMessage.setHtmlUrl(
                            pageUrl + SCHOOL_NOTICE_DETAIL
                                + "?schoolId=" + notice.getSchoolId().toString()
                                + "&type=1"
                                + "&contentId=" + notice.getId().toString()
                        );
                        pushMessage.setMsgType(PushMessage.ARTICLE);
                        String cleanHtmlTag =
                            HtmlUtil.cleanHtmlTag(HtmlUtil.unescape(notice.getContent()));
                        pushMessage.setContent(cleanHtmlTag.length() > 54 ? cleanHtmlTag.substring(0, 54) + "..." :
                            cleanHtmlTag);
                        msgList.add(pushMessage);
                    } else if (notice.getType() == 1) {
                        PushMessage pushMessage = new PushMessage();
                        pushMessage.setContent(notice.getContent());
                        pushMessage.setAccountId(account.getYidaAppAccountId());
                        pushMessage.setMsgType(PushMessage.TEXT);
                        msgList.add(pushMessage);
                    } else if (notice.getType() == 2) {
                        for (String picUrl : notice.getContentUrl().split(",")) {
                            PushMessage pushMessage = new PushMessage();
                            pushMessage.setImgUrl(picUrl);
                            pushMessage.setAccountId(account.getYidaAppAccountId());
                            pushMessage.setMsgType(PushMessage.IMAGE);
                            msgList.add(pushMessage);
                        }
                    } else if (notice.getType() == 3) {
                        PushMessage pushMessage = new PushMessage();
                        pushMessage.setSrcUrl(notice.getContentUrl());
                        pushMessage.setTitle(notice.getTitle());
                        pushMessage.setAccountId(account.getYidaAppAccountId());
                        pushMessage.setMsgType(PushMessage.VIDEO);
                        msgList.add(pushMessage);
                    }
                    appNotice.setMsgList(msgList);
                    appNotice.setPushMessage(new PushMessage(school.getDeptName(),
                        account.getYidaAppAccountId()));
                    AppUtil.sendMsg(appNotice, yidaApp);
                }
                // 保存消息到学校栏目公告区
                if (notice.getIsPublic() == 1) {
                    EduSchoolHomeAnnouncement announcement = eduSchoolHomeAnnouncementMapper.selectOne(
                        Wrappers.<EduSchoolHomeAnnouncement>lambdaQuery()
                            .eq(EduSchoolHomeAnnouncement::getSchoolId, school.getDeptId()));
                    if (announcement != null && StrUtil.isNotBlank(announcement.getYidaAppRegionId())) {
                        EduSchoolManuscript manuscript = new EduSchoolManuscript();
                        manuscript.setTitle(notice.getTitle());
                        manuscript.setSchoolId(notice.getSchoolId());
                        manuscript.setCoverType(1);
                        manuscript.setCoverUrl(notice.getCoverUrl());
                        manuscript.setContent(notice.getContent());
                        manuscript.setNoticeSchoolId(notice.getId());
                        manuscript.setStatus(3);
                        manuscript.setIsTiming(0);
                        manuscript.setType(0);
                        eduSchoolManuscriptService.saveManuscriptToYidaApp(manuscript, school, yidaApp);
                    }
                }
            }
            // 微信进行消息推送
            if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                EduApp eduApp = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null,
                    notice.getSchoolId());
                String token = wxUtil.getAccessToken(eduApp.getWxCorpId(), eduApp.getWxSecret());
                switch (notice.getType()) {
                    case 0:
                        sendNewsNotice(notice, token, eduApp);
                        break;
                    case 1:
                        sendTextNotice(notice, token, eduApp.getWxAgentId());
                        break;
                    case 2:
                        sendImageNotice(notice, token, eduApp.getWxAgentId());
                        break;
                    case 3:
                        sendVideoNotice(notice, token, eduApp.getWxAgentId());
                        break;
                    default:
                }
            }
        });
        notice.setStatus(1);
        notice.setSendDate(LocalDateTime.now());
        updateById(notice);
    }

    @Override
    public void sendNotice(Long noticeId) {
        EduNoticeSchool noticeSchool = baseMapper.getNoticeSchool(noticeId);
        List<EduNoticeSchoolReceiveStudent> notConfirmList =
            eduNoticeSchoolReceiveStudentService.list(Wrappers.lambdaQuery(new EduNoticeSchoolReceiveStudent())
                .eq(EduNoticeSchoolReceiveStudent::getNoticeId, noticeId)
                .eq(EduNoticeSchoolReceiveStudent::getIsConfirm, 0));
        noticeSchool.setReceiveStudentList(notConfirmList);
        sendNotice(noticeSchool);
    }

    @Override
    public IPage<SchoolNoticePageVO> listNoticePage(ListNoticeDTO dto) {
        Page<SchoolNoticePageVO> page = dto.toPage();
        page.setRecords(baseMapper.listNotice(page, dto));
        // 学校通知正文保留54个字
        for (SchoolNoticePageVO record : page.getRecords()) {
            if (StrUtil.isNotBlank(record.getContent())) {
                String content = HtmlUtil.cleanHtmlTag(HtmlUtil.unescape(record.getContent()));
                if (content != null && content.length() > NOTICE_CONTENT_LENGTH) {
                    content = content.substring(0, NOTICE_CONTENT_LENGTH);
                }
                record.setContent(content);
            }
        }
        return page;
    }

    @Override
    public EduNoticeSchool getNoticeInfo(Long id) {
        EduNoticeSchool eduNoticeSchool = baseMapper.getNoticeSchool(id);
        // 查询未确认人员
        List<EduNoticeSchoolReceiveStudent> notConfirmList = eduNoticeSchoolReceiveStudentService
            .list(Wrappers.lambdaQuery(new EduNoticeSchoolReceiveStudent())
                .eq(EduNoticeSchoolReceiveStudent::getNoticeId, id));
        eduNoticeSchool.setReceiveStudentList(notConfirmList);
        return eduNoticeSchool;
    }

    @Override
    public SchoolNoticeInfoByParentVO getNoticeInfoByParent(Long id, Long parentId) {
        EduNoticeSchool notice = baseMapper.getNoticeSchool(id);
        if (notice == null || ObjectUtil.equal(notice.getIsDraft(), 1) || !ObjectUtil.equal(notice.getStatus(), 1)) {
            return null;
        }
        // 返回数据
        SchoolNoticeInfoByParentVO res = new SchoolNoticeInfoByParentVO();
        res.setTitle(notice.getTitle());
        res.setContent(notice.getContent());
        res.setType(notice.getType());
        res.setContentUrl(notice.getContentUrl());
        res.setSendDate(notice.getSendDate());
        res.setIsConfirm(notice.getIsConfirm());
        res.setStatus(notice.getStatus());
        // 未确认家长列表是否保存该家长
        if (res.getIsConfirm() == 0) {
            res.setConfirmStatus(
                eduNoticeSchoolReceiveStudentService.count(Wrappers.lambdaQuery(new EduNoticeSchoolReceiveStudent())
                    .eq(EduNoticeSchoolReceiveStudent::getNoticeId, id)
                    .eq(EduNoticeSchoolReceiveStudent::getIsConfirm, 0)
                    .eq(EduNoticeSchoolReceiveStudent::getParentId, parentId)) > 0 ? 0 : 1);
        }
        // 保存阅读记录
        EduNoticeSchoolRead read = new EduNoticeSchoolRead();
        read.setNoticeId(notice.getId());
        read.setParentId(parentId);
        eduNoticeSchoolReadService.save(read);
        return res;
    }

    @Override
    public void retrySendNotice(Long id) {
        // 查询未确认人员
        List<EduNoticeSchoolReceiveStudent> notConfirmList =
            eduNoticeSchoolReceiveStudentService.list(Wrappers.lambdaQuery(new EduNoticeSchoolReceiveStudent())
                .eq(EduNoticeSchoolReceiveStudent::getNoticeId, id)
                .eq(EduNoticeSchoolReceiveStudent::getIsConfirm, 0));
        // 根据未确认人员 填充接收者信息
        EduNoticeSchool noticeSchool = baseMapper.getNoticeSchool(id);
        noticeSchool.setReceiveStudentList(notConfirmList);
        sendNotice(noticeSchool);
    }

    @Override
    public void confirmNotice(Long parentId, Long noticeId) {
        eduNoticeSchoolReceiveStudentService.confirmNotice(parentId, noticeId);
    }

    @Override
    public IPage<SchoolNoticePageVO> listShowNoticePage(Long schoolId, Long parentId, Integer isPublic, Integer pageNum,
        Integer pageSize) {
        return baseMapper.listShowSchoolPage(Page.of(pageNum, pageSize), schoolId, parentId, isPublic);
    }

    @Override
    public List<SchoolNoticePageVO> listNotice(ListNoticeDTO dto) {
        return baseMapper.listNotice(null, dto);
    }

    @Override
    public IPage<SchollNoticeTeacherPublishVO> listPublishNoticeByStaffPage(Long schoolId, Long userId, String title,
        Integer pageNum, Integer pageSize) {
        return baseMapper.listPublishNoticeByStaffPage(Page.of(pageNum, pageSize), schoolId, userId, title);
    }

    @Override
    public IPage<SchollNoticeTeacherDraftVO> listDraftNoticeByStaffPage(Long schoolId, Long userId, String title, Integer pageNum,
        Integer pageSize) {
        // 构造查询条件
        LambdaQueryWrapper<EduNoticeSchool> condition = Wrappers.<EduNoticeSchool>lambdaQuery()
            .eq(EduNoticeSchool::getType, 0)
            .eq(EduNoticeSchool::getIsDraft, 1)
            .eq(EduNoticeSchool::getSchoolId, schoolId)
            .eq(EduNoticeSchool::getCreateId, userId)
            .orderByDesc(EduNoticeSchool::getLastEditTime);
        if (StrUtil.isNotBlank(title)) {
            condition.like(EduNoticeSchool::getTitle, title);
        }
        Page<EduNoticeSchool> rowRes = page(Page.of(pageNum, pageSize), condition);
        // 制作返回数据
        Page<SchollNoticeTeacherDraftVO> res = new Page<>();
        res.setTotal(rowRes.getTotal());
        res.setSize(rowRes.getSize());
        res.setCurrent(rowRes.getCurrent());
        res.setPages(rowRes.getPages());
        if (CollUtil.isNotEmpty(rowRes.getRecords())) {
            // 处理返回数据
            res.setRecords(rowRes.getRecords().stream().map(x -> {
                SchollNoticeTeacherDraftVO draft = new SchollNoticeTeacherDraftVO();
                draft.setId(x.getId());
                draft.setTitle(x.getTitle());
                // 只取正文前100
                String content = HtmlUtil.cleanHtmlTag(x.getContent());
                draft.setContent(content.substring(0, Math.min(content.length(), 100)));
                draft.setLastEditTime(x.getLastEditTime());
                return draft;
            }).collect(Collectors.toList()));
        }
        return res;
    }

    @Override
    public IPage<SchoolNoticeReceiveParentVO> listReceiveParent(Long noticeId, String name, Integer pageNum, Integer pageSize) {
        // 分页查询
        LambdaQueryWrapper<EduNoticeSchoolReceiveStudent> condition = Wrappers.<EduNoticeSchoolReceiveStudent>lambdaQuery()
            .eq(EduNoticeSchoolReceiveStudent::getNoticeId, noticeId);
        if (StrUtil.isNotBlank(name)) {
            condition.like(EduNoticeSchoolReceiveStudent::getParentName, name);
        }
        IPage<EduNoticeSchoolReceiveStudent> data = eduNoticeSchoolReceiveStudentService
            .page(Page.of(pageNum, pageSize), condition);
        // 实际返回的数据
        Page<SchoolNoticeReceiveParentVO> page = new Page<>();
        page.setTotal(data.getTotal());
        page.setCurrent(data.getCurrent());
        page.setSize(data.getSize());
        page.setPages(data.getPages());
        if (CollUtil.isNotEmpty(data.getRecords())) {
            // 查询学生信息列表
            List<EduStudent> studentList = remoteStudentService
                .listStudent(ListStudentDTO.builder().studentIds(data.getRecords().stream().map(
                    EduNoticeSchoolReceiveStudent::getStudentId).collect(
                    Collectors.toList())).isQueryParent(false).isQuerySchoolName(false).build()).getData();
            // 重做数据
            Map<Long, List<EduStudent>> studentIdMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
            page.setRecords(data.getRecords().stream().filter(x -> studentIdMap.containsKey(x.getStudentId())).map(x -> {
                EduStudent studentData = studentIdMap.get(x.getStudentId()).get(0);
                SchoolNoticeReceiveParentVO vo = new SchoolNoticeReceiveParentVO();
                vo.setName(x.getParentName());
                vo.setStudentNumber(studentData.getStuNumber());
                vo.setConfirmStatus(x.getIsConfirm());
                vo.setClassName(studentData.getClassName());
                return vo;
            }).collect(Collectors.toList()));
        }
        return page;
    }

    @Override
    public Long recallNotice(Long noticeId) {
        // 更新发布状态
        EduNoticeSchool notice = new EduNoticeSchool();
        notice.setId(noticeId);
        notice.setStatus(2);
        updateById(notice);
        EduNoticeSchool oldNotice = getById(noticeId);
        List<EduNoticeSchoolReceiveStudent> oldReceiveStudentList = eduNoticeSchoolReceiveStudentService
            .list(Wrappers.<EduNoticeSchoolReceiveStudent>lambdaQuery()
                .eq(EduNoticeSchoolReceiveStudent::getNoticeId, noticeId));
        List<EduNoticeSchoolReceiver> oldReceiverList = eduNoticeSchoolReceiverService
            .list(Wrappers.<EduNoticeSchoolReceiver>lambdaQuery()
                .eq(EduNoticeSchoolReceiver::getNoticeId, noticeId));
        // 保存新通知
        oldNotice.setId(null);
        oldNotice.setCreateDate(null);
        oldNotice.setCreateId(null);
        oldNotice.setUpdateId(null);
        oldNotice.setUpdateDate(null);
        oldNotice.setStatus(0);
        oldNotice.setIsDraft(1);
        save(oldNotice);
        // 保存接收对象与学生
        oldReceiveStudentList = oldReceiveStudentList.stream().peek(x -> {
            x.setNoticeId(oldNotice.getId());
            x.setIsConfirm(0);
            x.setId(null);
        }).collect(Collectors.toList());
        oldReceiverList = oldReceiverList.stream().peek(x -> {
            x.setNoticeId(oldNotice.getId());
            x.setId(null);
        }).collect(Collectors.toList());
        eduNoticeSchoolReceiverService.saveBatch(oldReceiverList);
        eduNoticeSchoolReceiveStudentService.saveBatch(oldReceiveStudentList);
        // 返回新通知id
        return oldNotice.getId();
    }

    private void sendImageNotice(EduNoticeSchool eduNoticeSchool, String token, String agentId) {
        ImageSchoolNotice notice = new ImageSchoolNotice();
        notice.setAgentid(agentId);
        Image image = new Image();
        notice.setImage(image);
        List<String> parentList = new ArrayList<>();
        // 发送人员
        for (EduNoticeSchoolReceiveStudent receiver : eduNoticeSchool.getReceiveStudentList()) {
            if (StrUtil.isNotBlank(receiver.getParentWxId())) {
                parentList.add(receiver.getParentWxId());
            }
        }
        int j = 1;
        // 上传图片 发送消息
        for (String picUrl : eduNoticeSchool.getContentUrl().split(",")) {
            image.setMedia_id(wxUtil.uploadTempFile(token, "image", new File(FileUtil.downloadToLocal(picUrl))));
            if (parentList.size() > 1000) {
                // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
                for (int i = 0; i < parentList.size(); i += 1000) {
                    int end = Math.min(i + 1000, parentList.size());
                    notice.setTo_parent_userid(parentList.subList(i, end));
                    wxUtil.pushSchoolNotice(token, notice);
                }
            } else {
                notice.setTo_parent_userid(parentList);
                wxUtil.pushSchoolNotice(token, notice);
            }
            log.info("发送第[{}]次，notice:[{}]", j, notice);
        }
    }

    private void sendTextNotice(EduNoticeSchool eduNoticeSchool, String token, String agentId) {
        TextSchoolNotice notice = new TextSchoolNotice();
        notice.setAgentid(agentId);
        Text text = new Text();
        notice.setText(text);
        List<String> parentList = new ArrayList<>();
        // 发送人员
        for (EduNoticeSchoolReceiveStudent receiver : eduNoticeSchool.getReceiveStudentList()) {
            if (StrUtil.isNotBlank(receiver.getParentWxId())) {
                parentList.add(receiver.getParentWxId());
            }
        }
        // 发送消息
        text.setContent(eduNoticeSchool.getContent());
        if (parentList.size() > 1000) {
            // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
            for (int i = 0; i < parentList.size(); i += 1000) {
                int end = Math.min(i + 1000, parentList.size());
                notice.setTo_parent_userid(parentList.subList(i, end));
                wxUtil.pushSchoolNotice(token, notice);
            }
        } else {
            notice.setTo_parent_userid(parentList);
            wxUtil.pushSchoolNotice(token, notice);
        }
    }

    private void sendVideoNotice(EduNoticeSchool eduNoticeSchool, String token, String agentId) {
        VideoSchoolNotice notice = new VideoSchoolNotice();
        notice.setAgentid(agentId);
        Video video = new Video();
        notice.setVideo(video);
        List<String> parentList = new ArrayList<>();
        // 发送人员
        for (EduNoticeSchoolReceiveStudent receiver : eduNoticeSchool.getReceiveStudentList()) {
            if (StrUtil.isNotBlank(receiver.getParentWxId())) {
                parentList.add(receiver.getParentWxId());
            }
        }
        // 视频标题与描述
        video.setTitle(eduNoticeSchool.getTitle());
        video.setDescription(eduNoticeSchool.getContent());
        // 上传视频 发送消息
        video.setMedia_id(
            wxUtil.uploadTempFile(token, "video", new File(FileUtil.downloadToLocal(eduNoticeSchool.getContentUrl()))));
        if (parentList.size() > 1000) {
            // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
            for (int i = 0; i < parentList.size(); i += 1000) {
                int end = Math.min(i + 1000, parentList.size());
                notice.setTo_parent_userid(parentList.subList(i, end));
                wxUtil.pushSchoolNotice(token, notice);
            }
        } else {
            notice.setTo_parent_userid(parentList);
            wxUtil.pushSchoolNotice(token, notice);
        }
    }

    private void sendNewsNotice(EduNoticeSchool eduNoticeSchool, String token, EduApp app) {
        NewsSchoolNotice notice = new NewsSchoolNotice();
        notice.setAgentid(app.getWxAgentId());
        Article article = new Article();
        List<String> parentList = new ArrayList<>();
        // 发送人员
        for (EduNoticeSchoolReceiveStudent receiver : eduNoticeSchool.getReceiveStudentList()) {
            if (StrUtil.isNotBlank(receiver.getParentWxId())) {
                parentList.add(receiver.getParentWxId());
            }
        }
        // 图文 封面、标题与描述
        article.setPicurl(eduNoticeSchool.getCoverUrl());
        if (eduNoticeSchool.getIsConfirm() == 0) {
            article.setDescription("点击查看详情，看完后请点击确认收到该通知");
        } else {
            String content = HtmlUtil.cleanHtmlTag(HtmlUtil.unescape(eduNoticeSchool.getContent()));
            if (content.length() > 54) {
                content = content.substring(0, 54) + "......";
            }
            article.setDescription(content);
        }
        article.setTitle(eduNoticeSchool.getTitle());
        // TODO: 2021/6/10
        String detailUrl = pageUrl + SCHOOL_NOTICE_DETAIL
            + "?schoolId=" + eduNoticeSchool.getSchoolId().toString()
            + "&corpId=" + app.getWxCorpId().toString()
            + "&type=1"
            + "&contentId=" + eduNoticeSchool.getId().toString();
        article.setUrl(detailUrl);
        notice.setNews(new News(Collections.singletonList(article)));
        if (parentList.size() > 1000) {
            // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
            for (int i = 0; i < parentList.size(); i += 1000) {
                int end = Math.min(i + 1000, parentList.size());
                notice.setTo_parent_userid(parentList.subList(i, end));
                wxUtil.pushSchoolNotice(token, notice);
            }
        } else {
            notice.setTo_parent_userid(parentList);
            wxUtil.pushSchoolNotice(token, notice);
        }
    }
}
