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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
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.common.ResultBean;
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.EduNoticeBuy;
import com.yida.data.common.core.entity.notice.EduNoticeBuyProduct;
import com.yida.data.common.core.entity.notice.EduNoticeBuyReceiver;
import com.yida.data.common.core.entity.notice.EduNoticeSystemUser;
import com.yida.data.common.core.entity.notice.qywx.TextSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.inside.Text;
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.user.EduStudent;
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.news.mapper.EduNoticeBuyMapper;
import com.yida.data.school.news.mapper.EduNoticeBuyProductMapper;
import com.yida.data.school.news.mapper.EduNoticeBuyReceiverMapper;
import com.yida.data.school.news.service.EduNoticeBuyProductService;
import com.yida.data.school.news.service.EduNoticeBuyReceiverService;
import com.yida.data.school.news.service.EduNoticeBuyService;
import com.yida.data.school.news.service.EduNoticeSystemUserService;
import com.yida.data.school.transaction.mapper.EduProductMapper;
import com.yida.data.school.vo.news.BuyNoticePageVO;
import com.yida.data.system.feign.RemoteDeptService;
import com.yida.data.user.dto.ListStudentDTO;
import com.yida.data.user.feign.RemoteStudentService;
import java.util.Map;
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 org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Transactional
@Service
@RefreshScope
@RequiredArgsConstructor
public class EduNoticeBuyServiceImpl extends ServiceImpl<EduNoticeBuyMapper, EduNoticeBuy> implements EduNoticeBuyService {

    private static final String JOB_BEAN_NAME = "noticeUpdateTask";
    private static final String JOB_METHOD_NAME = "noticeUpdate";
    private final EduNoticeSystemUserService eduNoticeSystemUserService;
    private final EduNoticeBuyReceiverService eduNoticeBuyReceiverService;
    private final EduNoticeBuyProductService eduNoticeBuyProductService;
    private final EduNoticeBuyReceiverMapper eduNoticeBuyReceiverMapper;
    private final EduNoticeBuyProductMapper eduNoticeBuyProductMapper;
    private final RemoteDeptService remoteDeptService;
    private final RemoteJobService remoteJobService;
    private final EduProductMapper eduProductMapper;
    private final RemoteStudentService remoteStudentService;
    private final WxUtil wxUtil;
    private final CommonService commonService;
    @Value("${febs.pageUrl}")
    private String pageUrl;

    @Override
    public IPage<BuyNoticePageVO> listBuyNoticePage(Page page, Long areaId, Long schoolId, Long campsId,
        Integer status, String title, String sendDate,
        CurrentUser currentUser) {
        List<Long> schoolIds = new ArrayList<>();
        if (Objects.nonNull(schoolId)) {
            schoolIds.add(schoolId);
        } else {
            List<Dept> deptList = remoteDeptService.getSchoolByArea(null, null).getData();
            if (CollUtil.isNotEmpty(deptList)) {
                schoolIds = deptList.stream().map(Dept::getDeptId).collect(Collectors.toList());
            }
        }

        IPage<BuyNoticePageVO> pageVO = baseMapper
            .selectBuyNoticePage(page, schoolIds, new ArrayList<>(), status, title, sendDate);
        List<BuyNoticePageVO> records = pageVO.getRecords();
        for (BuyNoticePageVO record : records) {

            List<EduNoticeBuyProduct> eduNoticeBuyProducts = eduNoticeBuyProductMapper
                .selectList(Wrappers.lambdaQuery(new EduNoticeBuyProduct())
                    .eq(EduNoticeBuyProduct::getNoticeId, record.getId()));
            record.setEduNoticeBuyProduct(eduNoticeBuyProducts);
        }

        return pageVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBuyNotice(EduNoticeBuy eduNoticeBuy) {
        //删除该通知关联的商品
        if (eduNoticeBuy.getId() != null) {
            saveOrUpdate(eduNoticeBuy);
            Long id = eduNoticeBuy.getId();
            eduNoticeBuyProductService.remove(Wrappers.lambdaQuery(new EduNoticeBuyProduct())
                .eq(EduNoticeBuyProduct::getNoticeId, id));
        }
        //保存对应通知
        saveOrUpdate(eduNoticeBuy);
        Long id = eduNoticeBuy.getId();
        EduNoticeBuyProduct eduNoticeBuyProduct = eduNoticeBuy.getEduNoticeBuyProducts();
        eduNoticeBuyProduct.setNoticeId(id);

        //新增定时任务，定时发送通知
        if (eduNoticeBuy.getSendDate().isAfter(LocalDateTime.now())) {
            Job job = new Job();
            job.setBeanName(JOB_BEAN_NAME);
            job.setMethodName(JOB_METHOD_NAME);
            job.setParams(eduNoticeBuy.getId().toString());
            job.setStatus(Job.ScheduleStatus.NORMAL.getValue());
            LocalDateTime sendDate = eduNoticeBuy.getSendDate();
            StringBuilder cron = new StringBuilder();
            // cron表达式
            cron.append("0")
                .append(" ")
                .append(sendDate.getMinute())
                .append(" ")
                .append(sendDate.getHour())
                .append(" ")
                .append(sendDate.getDayOfMonth())
                .append(" ")
                .append(sendDate.getMonthValue())
                .append(" ")
                .append("?")
                .append(" ")
                .append(sendDate.getYear());
            job.setCronExpression(cron.toString());
            remoteJobService.saveJob(job);
        } else if (eduNoticeBuy.getSendDate().isBefore(LocalDateTime.now())) {
            //立即发送
            EduApp app = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null,
                eduNoticeBuy.getSchoolId());
            String accessToken = wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret());
            Text text = new Text();
            // 消息内容
            StringBuilder content = new StringBuilder();
            String url = pageUrl + "/campusService/index.html?&corpId=" + app.getWxCorpId() + "&detail=" + eduNoticeBuyProduct
                .getProductId();
            content.append("<a href='").append(url).append("'>").append(eduNoticeBuy.getContent().replaceAll("\n", ""))
                .append("</a>");
            text.setContent(content.toString());
            TextSchoolNotice textSchoolNotice = new TextSchoolNotice();
            textSchoolNotice.setText(text);
            textSchoolNotice.setAgentid(app.getWxAgentId());
            List<Long> studentId = new ArrayList<>();

            for (EduNoticeBuyReceiver receiver : eduNoticeBuy.getEduNoticeBuyReceivers()) {
                studentId.add(receiver.getStudentId());
            }
            List<EduStudent> students =
                remoteStudentService.listStudent(ListStudentDTO.builder().studentIds(studentId).build()).getData();
            List<String> list = new ArrayList<>();
            for (EduStudent student : students) {
                list.add(student.getWxId());
            }
            if (list.size() > 900) {
                // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
                for (int i = 0; i < list.size(); i += 900) {
                    int end = Math.min(i + 900, list.size());
                    textSchoolNotice.setTo_student_userid(list.subList(i, end));
                    wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
                }
            } else {
                textSchoolNotice.setTo_student_userid(list);
                wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
            }
            eduNoticeBuy.setStatus(1);
            saveOrUpdate(eduNoticeBuy);
        }

        //保存通知对应学生id
        eduNoticeBuyProductService.saveOrUpdate(eduNoticeBuyProduct);
        List<EduNoticeBuyReceiver> eduNoticeBuyReceivers = eduNoticeBuy.getEduNoticeBuyReceivers();

        for (EduNoticeBuyReceiver eduNoticeBuyReceiver : eduNoticeBuyReceivers) {
            eduNoticeBuyReceiver.setNoticeId(id);
        }

        eduNoticeBuyReceiverService.remove(Wrappers.lambdaQuery(new EduNoticeBuyReceiver())
            .eq(EduNoticeBuyReceiver::getNoticeId, id));
        eduNoticeBuyReceiverService.saveOrUpdateBatch(eduNoticeBuyReceivers);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delBuyNotice(Long id) {

        removeById(id);
        eduNoticeBuyProductService
            .remove(Wrappers.lambdaQuery(new EduNoticeBuyProduct()).eq(EduNoticeBuyProduct::getNoticeId, id));
        eduNoticeSystemUserService
            .remove(Wrappers.lambdaQuery(new EduNoticeSystemUser()).eq(EduNoticeSystemUser::getNoticeId, id));
    }

    @Override
    public EduNoticeBuy getBuyNoticeById(Long id) {
        List<EduNoticeBuyReceiver> eduNoticeBuyReceivers = eduNoticeBuyReceiverMapper
            .selectList(Wrappers.lambdaQuery(new EduNoticeBuyReceiver())
                .eq(EduNoticeBuyReceiver::getNoticeId, id));

        List<Long> studentIds = eduNoticeBuyReceivers.stream().map(EduNoticeBuyReceiver::getStudentId)
            .collect(Collectors.toList());

        Map<Long, EduStudent> collect = remoteStudentService.getStudentDeptByIds(studentIds).getData().stream()
            .collect(Collectors.toMap(EduStudent::getId, student -> student));

        for (EduNoticeBuyReceiver eduNoticeBuyReceiver : eduNoticeBuyReceivers) {
            eduNoticeBuyReceiver
                .setClassName(CollUtil.isEmpty(collect) ? null : collect.get(eduNoticeBuyReceiver.getStudentId()).getClassName());
            eduNoticeBuyReceiver
                .setGradeName(CollUtil.isEmpty(collect) ? null : collect.get(eduNoticeBuyReceiver.getStudentId()).getGradeName());
            eduNoticeBuyReceiver.setSchoolName(
                CollUtil.isEmpty(collect) ? null : collect.get(eduNoticeBuyReceiver.getStudentId()).getSchoolName());
            eduNoticeBuyReceiver.setCampusName(
                CollUtil.isEmpty(collect) ? null : collect.get(eduNoticeBuyReceiver.getStudentId()).getCampusName());
            eduNoticeBuyReceiver.setSectionName(
                CollUtil.isEmpty(collect) ? null : collect.get(eduNoticeBuyReceiver.getStudentId()).getSectionName());
        }

        EduNoticeBuy eduNoticeBuy = baseMapper.selectById(id);
        EduNoticeBuyProduct eduNoticeBuyProducts =
            eduNoticeBuyProductMapper
                .selectOne(Wrappers.lambdaQuery(new EduNoticeBuyProduct()).eq(EduNoticeBuyProduct::getNoticeId, id));

        eduNoticeBuy.setEduNoticeBuyReceivers(eduNoticeBuyReceivers);
        eduNoticeBuy.setEduNoticeBuyProducts(eduNoticeBuyProducts);

        return eduNoticeBuy;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBuyNoticeById(Long eduNoticeBuyId) {
        EduNoticeBuy eduNoticeBuy = getById(eduNoticeBuyId);

        EduApp app = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null,
            eduNoticeBuy.getSchoolId());
        String accessToken = wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret());
        EduNoticeBuyProduct eduNoticeBuyProduct = eduNoticeBuyProductService
            .getOne(Wrappers.lambdaQuery(new EduNoticeBuyProduct())
                .eq(EduNoticeBuyProduct::getNoticeId, eduNoticeBuyId));
        Text text = new Text();

        TextSchoolNotice textSchoolNotice = new TextSchoolNotice();
        StringBuilder content = new StringBuilder();
        String url =
            pageUrl + "/campusService/index.html?&corpId=" + app.getWxCorpId() + "&detail=" + eduNoticeBuyProduct.getProductId();
        content.append("<a href='").append(url).append("'>").append(eduNoticeBuy.getContent().replaceAll("\n", ""))
            .append("</a>");
        text.setContent(content.toString());
        textSchoolNotice.setText(text);
        textSchoolNotice.setAgentid(app.getWxAgentId());
        List<EduNoticeBuyReceiver> list1 = eduNoticeBuyReceiverService.list(Wrappers.lambdaQuery(new EduNoticeBuyReceiver())
            .eq(EduNoticeBuyReceiver::getNoticeId, eduNoticeBuyId));

        ArrayList<String> list = new ArrayList<>();
        ArrayList<Long> studentId = new ArrayList<>();
        for (EduNoticeBuyReceiver eduNoticeBuyReceiver : list1) {
            studentId.add(eduNoticeBuyReceiver.getStudentId());
        }
        List<EduStudent> students =
            remoteStudentService.listStudent(ListStudentDTO.builder().studentIds(studentId).build()).getData();

        for (EduStudent student : students) {
            list.add(student.getWxId());
        }

        if (list.size() > 900) {
            // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
            for (int i = 0; i < list.size(); i += 900) {
                int end = Math.min(i + 900, list.size());
                textSchoolNotice.setTo_student_userid(list.subList(i, end));
                wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
            }
        } else {
            textSchoolNotice.setTo_student_userid(list);
            wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
        }
        eduNoticeBuy.setStatus(1);
        updateById(eduNoticeBuy);
    }


    @Override
    public void sendBuyNoticeAgain(Long eduNoticeBuyId) {
        EduNoticeBuy eduNoticeBuy = getById(eduNoticeBuyId);

        EduApp app = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null,
            eduNoticeBuy.getSchoolId());
        String accessToken = wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret());
        EduNoticeBuyProduct eduNoticeBuyProduct = eduNoticeBuyProductService
            .getOne(Wrappers.lambdaQuery(new EduNoticeBuyProduct())
                .eq(EduNoticeBuyProduct::getNoticeId, eduNoticeBuyId));
        Text text = new Text();

        TextSchoolNotice textSchoolNotice = new TextSchoolNotice();
        StringBuilder content = new StringBuilder();
        String url =
            pageUrl + "/campusService/index.html?&corpId=" + app.getWxCorpId() + "&detail=" + eduNoticeBuyProduct.getProductId();
        content.append("<a href='").append(url).append("'>").append(eduNoticeBuy.getContent().replaceAll("\n", ""))
            .append("</a>");
        text.setContent(content.toString());
        textSchoolNotice.setText(text);
        textSchoolNotice.setAgentid(app.getWxAgentId());

        List<EduNoticeBuyReceiver> buyReceiverList = this.eduNoticeBuyReceiverService
            .list(Wrappers.lambdaQuery(new EduNoticeBuyReceiver())
                .eq(EduNoticeBuyReceiver::getNoticeId, eduNoticeBuyId));

        if (CollectionUtils.isEmpty(buyReceiverList)) {
            log.error("没有查找到再次发送的接受人数据, noticeId: {}", eduNoticeBuyId);
            return;
        }
        // 处理学生id集合
        List<Long> studentIds = buyReceiverList.stream().map(EduNoticeBuyReceiver::getStudentId).collect(Collectors.toList());
        // 查询范围内已购买学生
        List<Long> buyStudentIds = eduProductMapper.findNotBuyStudent(studentIds, eduNoticeBuyProduct.getProductId());
        // 移除已购买学生，得到未购买学生集合
        for (Long buyStudentId : buyStudentIds) {
            studentIds.remove(buyStudentId);
        }

        // 查询家长企业微信id
        List<String> parentWxId = remoteStudentService.findParentWxId(studentIds).getData();
        log.info("再次发送的家长企业微信id数据: {}", parentWxId);

        if (CollectionUtils.isEmpty(parentWxId)) {
            log.error("发送的企业微信家长数据为空，不用发送, parentWxId: {}", parentWxId);
            return;
        }
        if (parentWxId.size() > 900) {
            // 家长列表大于1000 只可能是再次提醒操作  接收部门必为空  不需要处理
            for (int i = 0; i < parentWxId.size(); i += 900) {
                int end = Math.min(i + 900, parentWxId.size());
                textSchoolNotice.setTo_parent_userid(parentWxId.subList(i, end));
                wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
            }
        } else {
            textSchoolNotice.setTo_parent_userid(parentWxId);
            wxUtil.pushSchoolNotice(accessToken, textSchoolNotice);
        }
        eduNoticeBuy.setStatus(1);
        updateById(eduNoticeBuy);
    }
}
