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

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.rongwe.scentity.domian.AspCheckDiscoveryItemDo;
import com.rongwe.scentity.domian.HiddenDangerTrackDo;
import com.rongwe.scentity.domian.ThemeCheckDo;
import com.rongwe.scentity.domian.ThemeCheckItemDo;
import com.rongwe.scentity.vo.UserMailOrgVo;
import com.rongwei.commonservice.serial.service.SysSerialNumberService;
import com.rongwei.rwadmincommon.system.domain.SysDictDo;
import com.rongwei.rwadmincommon.system.domain.SysUserDo;
import com.rongwei.rwadmincommon.system.service.SysConfigFeignService;
import com.rongwei.rwadmincommon.system.service.SysDictService;
import com.rongwei.rwadmincommon.system.service.SysUserService;
import com.rongwei.rwadmincommon.system.vo.SysUserVo;
import com.rongwei.rwcommon.base.BaseDo;
import com.rongwei.rwcommon.base.R;
import com.rongwei.rwcommon.utils.SecurityUtil;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.rwcommon.vo.MailDo;
import com.rongwei.safecommon.utils.JSCommonUtils;
import com.rongwei.sfcommon.sys.dao.SaveCheckCommonDao;
import com.rongwei.sfcommon.sys.service.SaveCheckItemService;
import com.rongwei.sfcommon.sys.service.ThemeCheckItemService;
import com.rongwei.sfcommon.sys.service.ThemeCheckService;
import com.rongwei.sfcommon.utils.MlConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.rongwei.sfcommon.utils.CommonUtil.streamCodeGeneration;
import static com.rongwei.sfcommon.utils.MlConstants.*;

@Service
public class SaveCheckItemServiceImpl implements SaveCheckItemService {
    private static final String SPECIALCHECK_MAIL_SUBJECT = "周五专项检查结果";
    private static final String TYPE_DAYCHECK_MAIL_SUBJECT = "主管经理检查结果";
    private static final String DISCOVERY_ITEM_MAIL_CONTENT = "检查主题：【%s】 \n组长：【%s】\n组员：【%s】\n检查工段：【%s】\n" +
            "检查时间：【%tF %tT】至【%tF %tT】\n发现项：\n【%s】\n   ";
    private static final String DISCOVERY_ITEM_CONTENT = "%s、%s %s %s %s %s；\n";
    private static final String HIDDEN_DANGER_CLASSIFY = "hidden_danger_classify";
    private static final String DANGER_WORKPARK = "%s/%s";
    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private ThemeCheckItemService themeCheckItemService;
    @Autowired
    private ThemeCheckService themeCheckService;
    @Autowired
    private AspCheckDiscoveryItemServiceImpl aspCheckDiscoveryItemService;
    @Autowired
    private SaveCheckCommonDao saveCheckCommonDao;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private SysConfigFeignService sysConfigFeignService;
    @Autowired
    private SysSerialNumberService sysSerialNumberService;
    @Autowired
    private HiddenDangerTrackServiceImpl hiddenDangerTrackService;
    @Autowired
    private SafeCheckSendNotifyServiceImpl sendNotifyService;

    @Override
    public R checkItemSave(Map<String, String> parameter) {
        String id = parameter.getOrDefault("id", "");
        if (StringUtils.isBlank(id)) {
            log.error("日常检查ID为空");
            return R.ok();
        }
        // 获取日产检查信息
        ThemeCheckItemDo checkItemDo = themeCheckItemService.getById(id);
        if (null == checkItemDo) {
            log.error("通过id:{}无法获取到日常检查信息", id);
            return R.ok();
        }
//        if ("2".equals(checkItemDo.getSaved())) {
//            log.error("当前日常检查已生成任务.");
//            return R.ok();
//        }
        ThemeCheckDo themeCheck = themeCheckService.getById(checkItemDo.getThemecheckid());
        if (themeCheck == null) {
            log.error("无法通过ID：{}获取asp_theme_check", checkItemDo.getThemecheckid());
        }
        // 获取所有的检查项
        List<AspCheckDiscoveryItemDo> aspCheckDiscoveryItemDos = aspCheckDiscoveryItemService.list(new LambdaQueryWrapper<AspCheckDiscoveryItemDo>()
                .eq(AspCheckDiscoveryItemDo::getThemecheckitemid, id)
                .eq(AspCheckDiscoveryItemDo::getCreatetask, 0)
                .eq(BaseDo::getDeleted, "0"));
        if (aspCheckDiscoveryItemDos.isEmpty()) {
            log.error("无法通过ID：{}获取到检查项信息", id);
        }

        SysUserVo currentUser = JSCommonUtils.getCurrentUser();
        // 任务生成
        List<HiddenDangerTrackDo> sendNotifyData = generateHiddenDangerTrack(checkItemDo, themeCheck,
                aspCheckDiscoveryItemDos,  currentUser);
        // 更新任务状态
        List<String> discoverIds = aspCheckDiscoveryItemDos.stream().map(AspCheckDiscoveryItemDo::getId).collect(Collectors.toList());
        aspCheckDiscoveryItemService.update(new LambdaUpdateWrapper<AspCheckDiscoveryItemDo>()
                .set(AspCheckDiscoveryItemDo::getCreatetask, 1)
                .in(AspCheckDiscoveryItemDo::getId, discoverIds));
        sendNotifyService.sendDangerTasksNotify(sendNotifyData);
//        ThreadPoolExecutor threadPool = ExecutorBuilder.create()
//                .setCorePoolSize(1)
//                .setMaxPoolSize(3)
//                .setKeepAliveTime(0)
//                .build();
//        threadPool.submit(() -> {
//            log.info("异步邮件发送");
//            this.sendDiscoveryMail(checkItemDo, themeCheck, aspCheckDiscoveryItemDos);
//        });
//        threadPool.shutdown();
        return R.ok();
    }


    /**
     * 生成隐患跟踪任务
     * 每一个检查项生成一个隐患跟踪任务
     *
     * @return
     */
    public List<HiddenDangerTrackDo> generateHiddenDangerTrack(ThemeCheckItemDo checkItemDo, ThemeCheckDo themeCheck,
                                                               List<AspCheckDiscoveryItemDo> aspCheckDiscoveryItemDos,
                                                               SysUserVo currentUser) {
        if (MlConstants.CHECK_RESULT_TRACK.equals(checkItemDo.getCheckresult()) || aspCheckDiscoveryItemDos.isEmpty()) {
            log.debug("检查结果为正常或无发现项,无需生成检查任务");
        }
        // 获取所有部门ID
//        List<String> deptIdList = aspCheckDiscoveryItemDos.stream().map(AspCheckDiscoveryItemDo::getDeptid).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
        // 获取安全管理员
        SysUserDo safetyManager = saveCheckCommonDao.getSafetyManager();
        // 获取车间安全促进员
//        List<UserMailOrgVo> safetyPromoter = saveCheckCommonDao.getSafetyPromoter(deptIdList);
        // 获取安全管理员
        List<HiddenDangerTrackDo> addList = new ArrayList<>();
        aspCheckDiscoveryItemDos.forEach(info -> {
            HiddenDangerTrackDo hiddenDangerTrack = new HiddenDangerTrackDo();
            hiddenDangerTrack.setId(SecurityUtil.getUUID());
            //风险分析对象编码
            hiddenDangerTrack.setRiskanalysisobjectcode(info.getRiskunitcode());
            //隐患等级hazardlevel
            hiddenDangerTrack.setHazardlevel(info.getGrade());
            //隐患来源
            hiddenDangerTrack.setDangersource(MlConstants.DANGER_SOURCE_THEMECHECK);
            //治理类型
            hiddenDangerTrack.setGovernancetype(info.getGovernancetype());
            //隐患类别
            hiddenDangerTrack.setHiddendangerleibie(info.getClassification());
            //隐患类型
            hiddenDangerTrack.setHiddendangertype(info.getType());
            //隐患状态 默认待评级
            hiddenDangerTrack.setHazardstate("3");
            //隐患名称
            hiddenDangerTrack.setHazardname(info.getName());
            //隐患描述
            if (StringUtils.isNotBlank(info.getHazarddescription())) {
                hiddenDangerTrack.setHazarddescription(info.getHazarddescription());
            }
            //整改责任人
            hiddenDangerTrack.setResponsiblepersonforrectification(info.getTrackuser());
            //责任人 id
            hiddenDangerTrack.setTrackuserid(info.getTrackuserid());
            //检查任务id
            hiddenDangerTrack.setCheckid(info.getId());
            hiddenDangerTrack.setTenantid(checkItemDo.getTenantid());
            JSCommonUtils.setBaseDetail(hiddenDangerTrack,currentUser);
            //隐患图片
            hiddenDangerTrack.setHazardphoto(info.getFileinfo());

//
//            hiddenDangerTrack.setThemecheckid(checkItemDo.getThemecheckid());
//            hiddenDangerTrack.setThemecheckname(checkItemDo.getThemecheckname());
//            hiddenDangerTrack.setRelationid(checkItemDo.getId());
//
//            hiddenDangerTrack.setFindtime(checkItemDo.getCreatedate());
//            hiddenDangerTrack.setActualchecktime(checkItemDo.getActualchecktime());
//            hiddenDangerTrack.setStatus(MlConstants.HIDDEN_DANGER_STATUS_NOTCLOSE);
//            hiddenDangerTrack.setTenantid(checkItemDo.getTenantid());

//            String pointcheckcode = streamCodeGeneration("asp_hidden_danger_track_code_aq",
//                    "@{date:yyyyMMdd}@{serialNumber:#000000}", "date:yyyy", themeCheck.getTenantid());

//            hiddenDangerTrack.setCode(pointcheckcode);

//            hiddenDangerTrack.setHiddendangertype(info.getType());
//            hiddenDangerTrack.setTrackuserid(info.getTrackuserid());
//            hiddenDangerTrack.setTrackusername(info.getTrackuser());
//            hiddenDangerTrack.setRectificationdate(info.getDeadline());
//            hiddenDangerTrack.setHiddendangercontent(info.getHazarddescription());
//            hiddenDangerTrack.setCheckphoto(checkItemDo.getCheckphoto());
//            hiddenDangerTrack.setStatus(MlConstants.HIDDEN_DANGER_STATUS_NOTCLOSE);
//            hiddenDangerTrack.setDiscoveryitemid(info.getId());
//            hiddenDangerTrack.setCreatedate(new Date());
//            hiddenDangerTrack.setCreateusername("日常检查自动生成");
//            hiddenDangerTrack.setModifyusername("日常检查自动生成");
//            hiddenDangerTrack.setModifydate(new Date());
//
//            hiddenDangerTrack.setRectificationfund(info.getRectificationfund());
//            hiddenDangerTrack.setMeasure(info.getMeasure());
            // 安全管理员
//            hiddenDangerTrack.setSafetypromoter(safetyManager == null ? "" : safetyManager.getName());
//            hiddenDangerTrack.setSafetypromoterid(safetyManager == null ? "" : safetyManager.getId());
            addList.add(hiddenDangerTrack);
        });
        hiddenDangerTrackService.saveBatch(addList);
        checkItemDo.setSaved("1");
        themeCheckItemService.saveOrUpdate(checkItemDo);
        return addList;
    }


    /**
     * 发送检查项邮件
     *
     * @return
     */
//    @Async
//    public void sendDiscoveryMail(ThemeCheckItemDo checkItemDo, ThemeCheckDo themeCheck,
//                                  List<AspCheckDiscoveryItemDo> aspCheckDiscoveryItemDos) {
//        log.info("开始执行异步邮件发送方法");
//        if (aspCheckDiscoveryItemDos.isEmpty()) {
//            return;
//        }
//        // 获取拥有领导角色的员工
//        // 获取安全管理员
//        List<UserMailOrgVo> leaderUserMialList = saveCheckCommonDao.getUserInfoByDeptCode("code-leader");
//        // 获取邮件发送人
//        List<String> mailsenduserids = StringUtils.isBlank(checkItemDo.getMailsenduserids()) ? new ArrayList<String>()
//                : Arrays.asList(checkItemDo.getMailsenduserids().split(","));
//        // 邮件发送人信息
//        List<SysUserDo> mailSender = mailsenduserids.isEmpty() ? new ArrayList<SysUserDo>() :
//                sysUserService.list(new LambdaQueryWrapper<SysUserDo>().in(SysUserDo::getId, mailsenduserids));
//        // 获取检查项中对应部门的部门经理
//        List<String> deptIds = aspCheckDiscoveryItemDos.stream()
//                .map(AspCheckDiscoveryItemDo::getDeptid)
//                .filter(StringUtils::isNotBlank)
//                .distinct()
//                .collect(Collectors.toList());
//        // 部门经理以及邮箱信息
//        List<UserMailOrgVo> deptUserList = saveCheckCommonDao.getUserInfoByOrgIdAndRoleCode(deptIds, DEPT_MANAGE_CODE);
//        // 获取所有的工段主管
//        List<String> sectionIds = aspCheckDiscoveryItemDos.stream()
//                .map(AspCheckDiscoveryItemDo::getSectionid)
//                .filter(StringUtils::isNotBlank)
//                .distinct()
//                .collect(Collectors.toList());
//        List<UserMailOrgVo> sectionUserList = saveCheckCommonDao.getUserInfoByOrgIdAndRoleCode(sectionIds, SECTION_SUPERVISOR_CODE);
//        // 获取所有的指派跟踪人
//        List<String> trackUserIds = aspCheckDiscoveryItemDos.stream()
//                .map(AspCheckDiscoveryItemDo::getTrackuserid)
//                .filter(StringUtils::isNotBlank)
//                .distinct()
//                .collect(Collectors.toList());
//        List<SysUserDo> trackUserInfo = sysUserService.list(new LambdaQueryWrapper<SysUserDo>().in(SysUserDo::getId, trackUserIds));
//        // 邮件发送人 整改所有发现项发出
//        List<UserMailOrgVo> senderMailUser = mailSender.stream().map(info -> {
//            UserMailOrgVo userMailOrgVo = new UserMailOrgVo();
//            userMailOrgVo.setId(info.getId());
//            userMailOrgVo.setEmail(info.getEmail());
//            return userMailOrgVo;
//        }).collect(Collectors.toList());
//        // 部门经理 需要将已在邮件发送人中存在的部门经理踢出
//        deptUserList = userMailDistinct(senderMailUser, deptUserList);
//        // 工段主管的邮箱 需要排除部门经理和邮件发送人
//        List<UserMailOrgVo> sectionUserMail = userMailDistinct(Stream.of(deptUserList, senderMailUser)
//                .flatMap(Collection::stream)
//                .collect(Collectors.toList()), sectionUserList);
//        // 指派跟踪人邮箱 需要排除部门经理和邮件发送人和工段主管
//        List<UserMailOrgVo> trackUserMail = userDistinct(Stream.of(senderMailUser, deptUserList, sectionUserMail)
//                .flatMap(Collection::stream)
//                .collect(Collectors.toList()), trackUserInfo);
//        /*******************邮件相关信息**************************************/
//        String mailSubject = THEMECHECK_TYPE_SPECIALCHECK.equals(themeCheck.getChecktype()) ? SPECIALCHECK_MAIL_SUBJECT : TYPE_DAYCHECK_MAIL_SUBJECT;
//        String checkSubject = checkItemDo.getThemecheckname();
//        String groupLeaderName = checkItemDo.getGroupleadername();
//        String groupUserNames = checkItemDo.getGroupusernames();
//        Date startTime = checkItemDo.getPlanstarttime();
//        Date endTime = checkItemDo.getPlanendtime();
//        String inspectionStation = checkItemDo.getChargeorgname();
//        List<SysDictDo> sysDictDos = sysDictService.getDictsByType(HIDDEN_DANGER_CLASSIFY);
//        /********************开始发送对应的邮件信息*****************************/
//        log.info("开始发送检查结构邮件,邮件发送人:{},部门经理:{},工段主管:{},指派跟踪人:{}", senderMailUser, deptUserList, sectionUserMail, trackUserMail);
//        sendDiscoveryItemMail(leaderUserMialList, aspCheckDiscoveryItemDos, 0
//                , sysDictDos, mailSubject, checkSubject, groupLeaderName, groupUserNames, startTime, endTime, inspectionStation);
//        sendDiscoveryItemMail(senderMailUser, aspCheckDiscoveryItemDos, 0
//                , sysDictDos, mailSubject, checkSubject, groupLeaderName, groupUserNames, startTime, endTime, inspectionStation);
//        sendDiscoveryItemMail(deptUserList, aspCheckDiscoveryItemDos, 1
//                , sysDictDos, mailSubject, checkSubject, groupLeaderName, groupUserNames, startTime, endTime, inspectionStation);
//        sendDiscoveryItemMail(sectionUserMail, aspCheckDiscoveryItemDos, 2
//                , sysDictDos, mailSubject, checkSubject, groupLeaderName, groupUserNames, startTime, endTime, inspectionStation);
//        sendDiscoveryItemMail(trackUserMail, aspCheckDiscoveryItemDos, 3
//                , sysDictDos, mailSubject, checkSubject, groupLeaderName, groupUserNames, startTime, endTime, inspectionStation);
//    }

    /**
     * 发送发现项邮件
     *
     * @param trackUserMail            收件人信息
     * @param aspCheckDiscoveryItemDos 发现项
     * @param type                     区分 1 部门经理邮件 2 工段主管邮件 3 工段主管邮件 0 邮件发送人
     * @param mailSubject              邮件主题
     */
//    public void sendDiscoveryItemMail(List<UserMailOrgVo> trackUserMail,
//                                      List<AspCheckDiscoveryItemDo> aspCheckDiscoveryItemDos,
//                                      int type,
//                                      List<SysDictDo> sysDictDos,
//                                      String mailSubject,
//                                      String checkSubject,
//                                      String groupLeaderName,
//                                      String groupUserNames,
//                                      Date startTime,
//                                      Date endTime,
//                                      String inspectionStation) {
//        // 为空直接返回
//        if (trackUserMail.isEmpty()) {
//            log.debug("邮件接收人为空");
//            return;
//        }
//        // 筛选出邮箱不为空的数据
//        trackUserMail = trackUserMail.stream().filter(info -> StringUtils.isNotBlank(info.getEmail())).collect(Collectors.toList());
//        if (trackUserMail.isEmpty()) {
//            log.debug("邮件接收人:{}邮箱为空", trackUserMail);
//            return;
//        }
//        // 按照邮箱分组
//        Map<String, List<UserMailOrgVo>> groupByEmail = trackUserMail.stream().collect(Collectors.groupingBy(UserMailOrgVo::getEmail));
//        // 根据不同的邮箱发送
//        groupByEmail.forEach((k, v) -> {
//            List<AspCheckDiscoveryItemDo> mailCkeckItem;
//            StringBuffer discoveryItems = new StringBuffer();
//            if (type == 0) {
//                mailCkeckItem = aspCheckDiscoveryItemDos;
//            } else if (type == 1) {
//                List<String> orgIds = v.stream().map(UserMailOrgVo::getOrgId).collect(Collectors.toList());
//                mailCkeckItem = aspCheckDiscoveryItemDos.stream()
//                        .filter(data -> orgIds.contains(data.getDeptid())).
//                        collect(Collectors.toList());
//            } else if (type == 2) {
//                List<String> orgIds = v.stream().map(UserMailOrgVo::getOrgId).collect(Collectors.toList());
//                mailCkeckItem = aspCheckDiscoveryItemDos.stream()
//                        .filter(data -> orgIds.contains(data.getSectionid())).
//                        collect(Collectors.toList());
//            } else {
//                List<String> orgIds = v.stream().map(UserMailOrgVo::getId).collect(Collectors.toList());
//                mailCkeckItem = aspCheckDiscoveryItemDos.stream()
//                        .filter(data -> orgIds.contains(data.getTrackuserid())).
//                        collect(Collectors.toList());
//            }
//            int index = 1;
//            for (int i = 0; i < mailCkeckItem.size(); i++) {
//                AspCheckDiscoveryItemDo aspCheckDiscoveryItemDo = mailCkeckItem.get(i);
//                discoveryItems.append(String.format(DISCOVERY_ITEM_CONTENT, index++, emptyStrReplace(aspCheckDiscoveryItemDo.getDept()),
//                        emptyStrReplace(aspCheckDiscoveryItemDo.getSection()),
//                        emptyStrReplace(aspCheckDiscoveryItemDo.getContent()),
//                        getDictNameByDictValue(aspCheckDiscoveryItemDo.getClassification(), sysDictDos),
//                        DateUtil.format(aspCheckDiscoveryItemDo.getDeadline(), "yyyy-MM-dd")));
//            }
//            // 邮件发送
//            MailDo mail = new MailDo();
//            mail.setSubject(mailSubject);
//            mail.setReceiveEmail(new String[]{k});
//            mail.setNeedTransReceive(false);
//            mail.setContent(String.format(DISCOVERY_ITEM_MAIL_CONTENT, emptyStrReplace(checkSubject),
//                    emptyStrReplace(groupLeaderName), emptyStrReplace(groupUserNames), emptyStrReplace(inspectionStation),
//                    startTime, startTime, endTime, endTime, emptyStrReplace(discoveryItems.toString())));
//            try {
//                // 邮件发送服务调用
//                sysConfigFeignService.sendTextMail(mail);
//            } catch (Exception e) {
//                log.error("邮件发送失败！类型：{}( 1.部门经理邮件 2.工段主管邮件 3.工段主管邮件 0.邮件发送人)", type);
//                e.printStackTrace();
//            }
//        });

//    }

    /**
     * 对于用户信息进行去重
     *
     * @param primaryUser   主要的用户数据
     * @param secondaryUser 待去重的数据
     * @return
     */
    public List<UserMailOrgVo> userMailDistinct(List<UserMailOrgVo> primaryUser, List<UserMailOrgVo> secondaryUser) {
        if (primaryUser.isEmpty()) {
            return secondaryUser;
        }
        List<String> primaryUserIds = primaryUser.stream().map(UserMailOrgVo::getId).collect(Collectors.toList());
        return secondaryUser.stream()
                .filter(user -> !primaryUserIds.contains(user.getId()))
                .collect(Collectors.toList());
    }

    public List<UserMailOrgVo> userDistinct(List<UserMailOrgVo> primaryUser, List<SysUserDo> trackUserInfo) {
        List<String> primaryUserIds = primaryUser.stream().map(UserMailOrgVo::getId).collect(Collectors.toList());
        return trackUserInfo.stream()
                .filter(user -> primaryUserIds.isEmpty() || !primaryUserIds.contains(user.getId()))
                .map(info -> {
                    UserMailOrgVo userMailOrgVo = new UserMailOrgVo();
                    userMailOrgVo.setId(info.getId());
                    userMailOrgVo.setEmail(info.getEmail());
                    return userMailOrgVo;
                }).collect(Collectors.toList());

    }

    public String getDictNameByDictValue(String value, List<SysDictDo> sysDictDos) {
        if (StringUtils.isBlank(value)) {
            return "";
        }
        SysDictDo sysDictDo = sysDictDos.stream().filter(info -> info.getValue().equals(value)).findFirst().orElse(null);
        return sysDictDo == null ? "" : sysDictDo.getName();
    }

    public String emptyStrReplace(String a) {
        return StringUtils.isBlank(a) ? "" : a;
    }
}
