package com.rongwei.sfcommon.sys.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rongwe.scentity.domian.AspSafeAttachmentsDo;
import com.rongwe.scentity.domian.AspSpecialEquipmentCertificateDo;
import com.rongwe.scentity.domian.CheckItemsDo;
import com.rongwe.scentity.vo.SysNoticeVo;
import com.rongwe.scentity.vo.UserMailOrgVo;
import com.rongwei.rwadmincommon.system.domain.SysDictDo;
import com.rongwei.rwadmincommon.system.service.SysConfigFeignService;
import com.rongwei.rwadmincommon.system.service.SysDictService;
import com.rongwei.rwcommon.base.R;
import com.rongwei.rwcommon.vo.MailDo;
import com.rongwei.safecommon.utils.CXCommonUtils;
import com.rongwei.sfcommon.sys.dao.AspSpecialEquipmentCertificateDao;
import com.rongwei.sfcommon.sys.dao.SaveCheckCommonDao;
import com.rongwei.sfcommon.sys.service.AspSpecialEquipmentCertificateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import static com.rongwei.safecommon.utils.SaveConstans.*;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyContent.PERSONNEL_CERTIFICATES_CONTENT;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyTitle.PERSONNEL_CERTIFICATES_TITLE;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyType.PERSONNEL_CERTIFICATES;

/**
 *
 */
@Service
public class AspSpecialEquipmentCertificateServiceImpl extends ServiceImpl<AspSpecialEquipmentCertificateDao, AspSpecialEquipmentCertificateDo>
        implements AspSpecialEquipmentCertificateService {
    /**
     * 组织机构代码
     */
    public static final List<String> ROLE_CODE_LIST = new ArrayList<String>() {{
        add("code-safe");
        add("role031");
        add("produce");
    }};
    /**
     * 特种设备管理员
     */
    public static final String SPECIAL_EQUIPMENT_ADMINISTRATOR = "role031";

    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private SaveCheckCommonDao saveCheckCommonDao;
    @Autowired
    private SysDictService sysDictService;
    @Resource
    private SysConfigFeignService sysConfigFeignService;

    @Override
    public R stateUpdateScheduledTasks() {
        // 获取所有的特种设备证书
        List<AspSpecialEquipmentCertificateDo> safeAttachmentsDos = this.list();
        if (safeAttachmentsDos.isEmpty()) {
            return R.ok("暂无特种设备证书");
        }
        // 对数据按照租户ID 分组
        Map<String, List<AspSpecialEquipmentCertificateDo>> dataMap = safeAttachmentsDos.stream().collect(Collectors.groupingBy(AspSpecialEquipmentCertificateDo::getTenantid));
        List<AspSpecialEquipmentCertificateDo> saveData = new ArrayList<>();
        // 发送消息提醒的参数
        Map<AspSpecialEquipmentCertificateDo, List<String>> sendNotifyMap = new HashMap<>();
        // 发送邮件的集合《用户ID，List<设备信息>》
        Map<String, List<AspSpecialEquipmentCertificateDo>> sendMailMap = new HashMap<>();
        // 用户的信息集合
        Map<String, UserMailOrgVo> userMap = new HashMap<>();
        dataMap.forEach((k, v) -> {
            //获取工厂对应的 安全管理员和特种设备管理员 和生产副总
            List<UserMailOrgVo> userInfO = saveCheckCommonDao.getUserInfoByTenantIdAndRoleCode(k, ROLE_CODE_LIST);
            for (UserMailOrgVo userMailOrgVo : userInfO) {
                if (ObjectUtil.isNotEmpty(userMailOrgVo.getEmail())) {
                    sendMailMap.put(userMailOrgVo.getId(), new LinkedList<>());
                    userMap.put(userMailOrgVo.getId(), userMailOrgVo);
                }
            }
            Date manufacturedate;
            long daysBetween;
            List<String> alertUser;
            for (AspSpecialEquipmentCertificateDo data : v) {
                manufacturedate = data.getReviewdate();
                LocalDate date1 = manufacturedate.toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDate();
                daysBetween = ChronoUnit.DAYS.between(LocalDate.now(), date1);
                if (daysBetween <= 7) {
                    data.setReminderstate(HIGH);
                    alertUser = userInfO.stream().map(UserMailOrgVo::getId).collect(Collectors.toList());
                    sendNotifyMap.put(data, alertUser);
                    for (String userId : alertUser) {
                        if (sendMailMap.containsKey(userId)) {
                            List<String> dataIdList = sendMailMap.get(userId).stream().map(AspSpecialEquipmentCertificateDo::getId).collect(Collectors.toList());
                            if (!dataIdList.contains(data.getId())) {
                                sendMailMap.get(userId).add(data);
                            }
                        }
                    }
                } else if (daysBetween <= 90) {
                    alertUser = userInfO.stream().filter(user -> SPECIAL_EQUIPMENT_ADMINISTRATOR.equals(user.getRoleCode())).map(UserMailOrgVo::getId).collect(Collectors.toList());
                    data.setReminderstate(MIDDLE);
                    sendNotifyMap.put(data, alertUser);
                    for (String userId : alertUser) {
                        if (sendMailMap.containsKey(userId)) {
                            List<String> dataIdList = sendMailMap.get(userId).stream().map(AspSpecialEquipmentCertificateDo::getId).collect(Collectors.toList());
                            if (!dataIdList.contains(data.getId())) {
                                sendMailMap.get(userId).add(data);
                            }
                        }
                    }
                } else {
                    data.setReminderstate(LOW);
                }

                saveData.add(data);
            }
        });
        this.updateBatchById(saveData);
        sendNotify(sendNotifyMap);

        sendMail(sendMailMap, userMap);

        return R.ok();
    }

    private void sendMail(Map<String, List<AspSpecialEquipmentCertificateDo>> sendMailMap, Map<String, UserMailOrgVo> userMap) {
        if (ObjectUtil.isEmpty(sendMailMap)) {
            return;
        }
        // 获取数据字典-证书类别
        List<SysDictDo> aspCheckItemType = sysDictService.getDictsByType("zslb");
        sendMailMap.forEach((key, value) -> {
            if (ObjectUtil.isEmpty(value)) {
                return;
            }
            StringBuilder mailContent = new StringBuilder("您好！有如下特种设备人员证书即将年检到期，请及时处理！\n");
            for (int i = 0; i < value.size(); i++) {
                AspSpecialEquipmentCertificateDo item = value.get(i);

                //姓名
                String name = ObjectUtil.isNotEmpty(item.getName()) ? item.getName() : "";
                //所属部门
                String orgName = ObjectUtil.isNotEmpty(item.getOrgname()) ? item.getOrgname() : "";
                //证书类别
                String certificate = "";
                String certificatesort = item.getCertificatesort();
                if (ObjectUtil.isNotEmpty(certificatesort)) {
                    SysDictDo sysDictDo = aspCheckItemType.stream().filter(info -> info.getValue().equals(item.getCertificatesort())).findFirst().orElse(null);
                    if (ObjectUtil.isNotEmpty(sysDictDo)) {
                        certificate = sysDictDo.getName();
                    }
                }

                //复审日期
                Date reviewdate = item.getReviewdate();
                String reviewDate = "";
                if (ObjectUtil.isNotEmpty(reviewdate)) {
                    reviewDate = DateUtil.format(reviewdate, "yyyy-MM-dd");
                }
                mailContent.append((i + 1) + "、姓名:【" + name + "】,所属部门:【" + orgName + "】证书类别:【" + certificate + "】，复审日期：【" + reviewDate + "】\n");
            }
            mailContent.append("详见安全生产平台，如果无法点击请复制链接到浏览器中：http://192.168.100.77/#/page/s/76711fe45ac941efa3d58d43b28b4f39");

            //发送邮件
            MailDo mailDo = new MailDo();
            mailDo.setSubject("特种设备人员证书年检提醒");
            mailDo.setReceiveEmail(new String[]{userMap.get(key).getEmail()});
            mailDo.setNeedTransReceive(false);
            mailDo.setContent(mailContent.toString());
            try {
                sysConfigFeignService.sendTextMail(mailDo);
            } catch (Exception ignored) {
            }
        });

    }

    public void sendNotify(Map<AspSpecialEquipmentCertificateDo, List<String>> sendNotifyMap) {
        //查询所有该类型的、未读的 消息通知
        List<SysNoticeVo> sysNoticeVo = this.baseMapper.selectMyNoticeByType(Arrays.asList(PERSONNEL_CERTIFICATES));

        // 获取数据字典
        List<SysDictDo> aspCheckItemType = sysDictService.getDictsByType("zslb");
        sendNotifyMap.forEach((k, v) -> {
            SysDictDo sysDictDo = aspCheckItemType.stream()
                    .filter(info -> info.getValue().equals(k.getCertificatesort()))
                    .findFirst().orElse(null);
            String content = String.format(PERSONNEL_CERTIFICATES_CONTENT, k.getName() == null ? "" : k.getName(), k.getOrgname() == null ? "" : k.getOrgname(), sysDictDo == null ? "" : sysDictDo.getName(),
                    k.getReviewdate() == null ? "" : k.getReviewdate());
            List<String> userIdList = v.stream().distinct().collect(Collectors.toList());
            SysNoticeVo oldNoticeVo = sysNoticeVo.stream().filter(item -> item.getNotifycontent().equals(content) && item.getRoption().equals(k.getId())).distinct().findFirst().orElse(null);
            if (ObjectUtil.isNotEmpty(oldNoticeVo) && ObjectUtil.isNotEmpty(oldNoticeVo.getUserIds())) {
                userIdList.removeAll(oldNoticeVo.getUserIds());
            }

            // 发送消息提醒
            CXCommonUtils.sendNotify(PERSONNEL_CERTIFICATES_TITLE,
                    content, null, userIdList,
                    k.getId(), PERSONNEL_CERTIFICATES, false);
        });
    }
}




