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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rongwe.scentity.domian.*;
import com.rongwe.scentity.vo.CheckTemplateItemsVo;
import com.rongwe.scentity.vo.CheckTemplateVo;
import com.rongwei.commonservice.serial.service.CommonDictService;
import com.rongwei.commonservice.serial.service.SysSerialNumberService;
import com.rongwei.rwadmincommon.system.dao.SysUserDao;
import com.rongwei.rwadmincommon.system.domain.SysDictDo;
import com.rongwei.rwcommon.base.BaseDo;
import com.rongwei.rwcommon.utils.SecurityUtil;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.rwcommon.vo.generalsql.GeneralApiParameter;
import com.rongwei.rwcommon.vo.generalsql.SlaveDMLVo;
import com.rongwei.safecommon.utils.CXCommonUtils;
import com.rongwei.sfcommon.sys.dao.CheckTemplateDao;
import com.rongwei.sfcommon.sys.service.*;
import com.rongwei.sfcommon.utils.MlConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static com.rongwei.safecommon.utils.CXCommonUtils.streamCodeGeneration;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyContent.INSPECTION_CONTENT;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyTitle.INSPECTION_TITLE;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyType.INSPECTION;

@Service("checkTemplateService")
public class CheckTemplateServiceImpl extends ServiceImpl<CheckTemplateDao, CheckTemplateDo> implements CheckTemplateService {

    private static final Logger logger = LoggerFactory.getLogger(CheckTemplateServiceImpl.class);

    @Autowired
    private CheckTemplateItemsService checkTemplateItemsService;
    @Autowired
    private CommonDictService commonDictService;
    @Autowired
    private SysSerialNumberService sysSerialNumberService;
    @Autowired
    private CheckItemsService checkItemsService;
    @Autowired
    private CheckItemsDutyuserService checkItemsDutyuserService;
    @Autowired
    private PointCheckService pointCheckService;
    @Autowired
    private PointCheckItemService pointCheckItemService;
    @Autowired
    private CheckItemContentService checkItemContentService;
    @Autowired
    private SysUserDao sysUserDao;
    public static final List<String> MONTH_ENG = new ArrayList<String>() {{
        add("january");
        add("february");
        add("march");
        add("april");
        add("may");
        add("june");
        add("july");
        add("august");
        add("september");
        add("october");
        add("november");
        add("december");
    }};

    /**
     * 通用Map转自定义业务实体类
     *
     * @param map
     * @return
     */
    public CheckTemplateVo mapToCheckTemplateVo(Map<String, Object> map) {
        GeneralApiParameter generalApiParameter = BeanUtil.mapToBeanIgnoreCase(map, GeneralApiParameter.class, true);
        CheckTemplateVo checkTemplateVo = BeanUtil.mapToBeanIgnoreCase(generalApiParameter.getMasterPar(), CheckTemplateVo.class, true);
        List<SlaveDMLVo> slaveDMLVos = generalApiParameter.getSlaveDMLVos();
        if (slaveDMLVos != null && slaveDMLVos.size() > 0) {
            for (SlaveDMLVo slaveDMLVo : slaveDMLVos) {
                //字段明细表处理
                if ("asp_check_template_items".equalsIgnoreCase(slaveDMLVo.getTableName())) {
                    //新增数据
                    slaveDMLVo.getSlaveInsert().forEach(item -> {
                        CheckTemplateItemsVo checkTemplateItemsVo = BeanUtil.mapToBeanIgnoreCase(item.getInsertcolumns(), CheckTemplateItemsVo.class, true);
                        checkTemplateVo.getCheckTemplateItems().add(checkTemplateItemsVo);
                    });
                    //更新数据
                    slaveDMLVo.getSlaveUpdate().forEach(item -> {
                        CheckTemplateItemsVo checkTemplateItemsVo = BeanUtil.mapToBeanIgnoreCase(item.getUpdatecolumns(),CheckTemplateItemsVo.class,true);
                        checkTemplateVo.getCheckTemplateItems().add(checkTemplateItemsVo);
                    });
                }
            }
        }
        return checkTemplateVo;
    }

    /**
     * 根据版本号保存，即做更改操作时录入新数据、原数据状态置为禁用
     * @param checkTemplateVo
     */
    public void saveByVersion(CheckTemplateVo checkTemplateVo){
        if(StringUtils.isEmpty(checkTemplateVo.getId())){
            checkTemplateVo.setId(SecurityUtil.getUUID());
        }
        // 根据ID查询是否已存在当前数据
        CheckTemplateDo checkTemplateDo = this.getById(checkTemplateVo.getId());
        if(checkTemplateDo != null){
            // 如存在历史记录，则更新历史记录为禁用状态
            checkTemplateDo.setEnablestatus("disable");
            this.updateById(checkTemplateDo);
        }else{
            // 保存模板记录
            this.save(checkTemplateVo);
            // 保存模板明细记录
            if(checkTemplateVo.getCheckTemplateItems() != null && checkTemplateVo.getCheckTemplateItems().size()>0){
                checkTemplateItemsService.saveBatch(checkTemplateVo.getCheckTemplateItems());
            }
        }
    }

    /**
     * 定时调度(每天)创建点检任务
     */
    public void pointCheckCreate(Map<String, Object> map) {
        logger.info("点检定时任务生成开始.....");
        if (map == null) {
            map = new HashMap<>();
        }
        // 是否为定时任务
        boolean runTask = false;
        // 如果参数为空则为定时任务
        if (map.isEmpty()) {
            //map.put("TEMPLATETYPE",MlConstants.TEMPLATETYPE_POINT_CHECK);
            // 模板状态
            map.put("ENABLESTATUS", MlConstants.TEMPLATE_STATUS_OPEM);
            // 任务生成类型
            map.put("JOBSTARTTYPE", MlConstants.JOB_START_TYPE_AUTO);
            runTask = true;
        } else {
            String checkTemplateId = map.getOrDefault("ID", "").toString();
            if (StringUtils.isBlank(checkTemplateId)) {
                log.error("参数异常");
                return;
            }
        }
        // 查询所有点检类型的检查模板
        List<CheckTemplateDo> list = (List<CheckTemplateDo>) this.listByMap(map);
        if (list.size() == 0) {
            // 根据点检模板定时生成点检任务
            return;
        }
        for (CheckTemplateDo checkTemplate : list) {
            logger.info("点检模板编号：" + checkTemplate.getTemplatecode());
            // 检查模板的检查项
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("CHECKTEMPLATEID", checkTemplate.getId());
            List<CheckTemplateItemsDo> items = (List<CheckTemplateItemsDo>) checkTemplateItemsService.listByMap(itemMap);
            // 根据检查模板和相应的检查项生成点检任务
            pointCheckCreateByItems(checkTemplate, items, runTask);
        }
        // 检查是否有延期点检任务，如有则发邮件提醒
        //pointCheckService.pintCheckDelayReminder();
    }

    // 根据检查模板和相应的检查项生成点检任务
    private void pointCheckCreateByItems(CheckTemplateDo checkTemplate, List<CheckTemplateItemsDo> items, boolean runTask) {
        /**
         * 根据检查模板所有检查项的频次决定最终生成多少点检任务
         * 通过对需求分析总结模型如下：
         * 点检任务总共有三种：白班、中班、夜班
         * 此三种任务的任务个数不限定，但针对目前需求简化考虑频次类型为数据字典选择，所以任务个数为：1、2 两种
         */
        // 白班检查项
        List<List<CheckTemplateItemsDo>> dayItems = new ArrayList<>();
        // 中班检查项
        List<List<CheckTemplateItemsDo>> middleItems = new ArrayList<>();
        // 夜班检查项
        List<List<CheckTemplateItemsDo>> nightItems = new ArrayList<>();
        // 长白班检查项
        List<List<CheckTemplateItemsDo>> changbaiClassItems = new ArrayList<>();
        if (items == null || items.size() == 0) {
            return;
        }
        // 循环处理检查内容到白、中、夜三班任务里
        for (CheckTemplateItemsDo checkTemplateItem : items) {
            // 频次
            String frequency = checkTemplateItem.getFrequencyids();
            // 班次
            String shift = checkTemplateItem.getShift();
            // 次数
            Integer shiftcount = checkTemplateItem.getShiftcount();
            if (shiftcount == null) {
                shiftcount = 1;
            }
            // 如果是定时任务 (频次为空或者根据频次判断不应该生产任务时 直接返回)
            if (runTask && (StringUtils.isBlank(frequency) || !isNowCreateByFrequency(frequency))) {
                continue;
            }

            // 白班
            if (MlConstants.CHECK_SHIFT_EVERY_SHIFT.equals(shift) || MlConstants.CHECK_SHIFT_EVERY_DAY_SHIFT.equals(shift)) {
                addCheckItems(dayItems, shiftcount, checkTemplateItem);
            }
            // 夜班
            if (MlConstants.CHECK_SHIFT_EVERY_SHIFT.equals(shift) || MlConstants.CHECK_SHIFT_EVERY_NIGHT_SHIFT.equals(shift)) {
                addCheckItems(nightItems, shiftcount, checkTemplateItem);
            }
            // 中班
            if (MlConstants.CHECK_SHIFT_EVERY_SHIFT.equals(shift) || MlConstants.CHECK_SHIFT_EVERY_MIDDLE_SHIFT.equals(shift)) {
                addCheckItems(middleItems, shiftcount, checkTemplateItem);
            }
            // 长白班 每班数据不需要生成长白班
            if (MlConstants.CHECK_SHIFT_EVERY_CHANGBAI_CLASS_SHIFT.equals(shift)) {
                addCheckItems(changbaiClassItems, shiftcount, checkTemplateItem);
            }
        }
        // 生成点检任务
        System.out.println("dayItems:" + dayItems.size() + "***" + "middleItems:" + middleItems.size() + "***" + "nightItems:" + nightItems.size());
        // 白班任务
        createPointCheckByTemplate(checkTemplate, dayItems, MlConstants.CHECK_SHIFT_EVERY_DAY_SHIFT);
        // 中班任务
        createPointCheckByTemplate(checkTemplate, middleItems, MlConstants.CHECK_SHIFT_EVERY_MIDDLE_SHIFT);
        // 夜班任务
        createPointCheckByTemplate(checkTemplate, nightItems, MlConstants.CHECK_SHIFT_EVERY_NIGHT_SHIFT);
        // 长白班任务
        createPointCheckByTemplate(checkTemplate, changbaiClassItems, MlConstants.CHECK_SHIFT_EVERY_CHANGBAI_CLASS_SHIFT);
    }

    /**
     * 根据频次判断当前检查项是否生成点检任务
     *
     * @param frequency
     * @return 是否可以生成任务
     */
    private boolean isNowCreateByFrequency(String frequency) {
        boolean isCreate = true;
        String[] frequencys = frequency.split("/");
        if (frequencys != null && frequencys.length > 0) {
            // 每天
            if ("day".equals(frequencys[0])) {
                isCreate = true;
            }
            // 每周
            else if ("week".equals(frequencys[0])) {
                String weekday = frequencys[1];
                // 当前时间是星期几
                String w = DateUtil.dayOfWeek(new Date())+"";
                if(!w.equals(weekday)){
                    isCreate = false;
                }
            }
            // 每月
            else if("month".equals(frequencys[0])){
                String monthday = frequencys[1];
                // 判断是否最后一天
                if("32".equals(monthday)){
                    String nowDay = DateUtil.format(new Date(),"yyyy-MM-dd");
                    String lastDay = DateUtil.format(DateUtil.endOfMonth(new Date()),"yyyy-MM-dd");
                    if(!nowDay.equals(lastDay)){
                        isCreate = false;
                    }
                }else {
                    if(!(DateUtil.dayOfMonth(new Date())+"").equals(monthday)){
                        isCreate = false;
                    }
                }
            }
            // 每年
            else if("year".equals(frequencys[0])){
                String monthday = frequencys[1];
                String day = frequencys[2];
                if (monthday.equals(MONTH_ENG.get(DateUtil.thisMonth())) && day.equals(String.valueOf(DateUtil.thisDayOfMonth()))) {
                    isCreate = true;
                } else {
                    isCreate = false;
                }
            }else{
                isCreate = false;
            }
        }
        return isCreate;
    }

    // 根据次数添加检查内容
    private void addCheckItems(List<List<CheckTemplateItemsDo>> items,Integer shiftcount,CheckTemplateItemsDo checkTemplateItem){
        if(items.size()<shiftcount){
            for(int j = items.size()+1;j <= shiftcount;j++){
                items.add(new ArrayList<>());
            }
        }
        for(int m = 0;m < shiftcount;m++){
            items.get(m).add(checkTemplateItem);
        }
    }

    /**
     * 根据模板生成点检任务
     * @param checkTemplate 检查模板
     * @param items         检查模板明细（检查内容）
     * @param shift         班次
     */
    private void createPointCheckByTemplate(CheckTemplateDo checkTemplate,List<List<CheckTemplateItemsDo>> items,String shift) {
        if (items.isEmpty()) {
            return;
        }
        List<PointCheckDo> pointChecks = new ArrayList<>();
        List<PointCheckItemDo> pointCheckItems = new ArrayList<>();
        Map<PointCheckNewsVo,List<String>> notifyType = new HashMap<>();
        // 每班几次就生成几个任务
        for(List<CheckTemplateItemsDo> checkItems:items){
            // 点检名称 班次+模板名称+当前日期
            String poName = commonDictService.getDictNameByValue("check-shift",shift)+"-"+checkTemplate.getTemplatename()+"-"+DateUtil.format(new Date(),"yyyy-MM-dd");
            // 设备表IDS
            String checkitemsids = checkTemplate.getCheckitemids();
            // 获取模板的检查分类
            String templatetype = checkTemplate.getTemplatetype();
            if(StringUtils.isNotEmpty(checkitemsids)){
                String[] checkitemsidArray = checkitemsids.split(",");
                for (String checkitemsid : checkitemsidArray) {
                    // 每个设备生成一条点检任务
                    CheckItemsDo checkItemsdo = checkItemsService.getById(checkitemsid);
                    // 如当前设备未禁用状态则不生成点检任务
                    if (checkItemsdo == null || MlConstants.CHECKITEM_STATUS_DISABLE.equals(checkItemsdo.getEnabled())) {
                        continue;
                    }
                    // 点检编号
                    String pointcheckcode =  streamCodeGeneration("asp_point_check_POINTCHECKCODE","@{date:yyyyMMdd}@{serialNumber:#0000000}","date:yyyy", checkTemplate.getTenantid());;

                    // 点检生成
                    PointCheckDo pointCheckDo = new PointCheckDo();
                    PointCheckNewsVo pointCheckVo = new PointCheckNewsVo();
                    pointCheckDo.setId(SecurityUtil.getUUID());
                    pointCheckDo.setPointcheckname(poName);
                    pointCheckDo.setPointcheckcode(pointcheckcode);
                    pointCheckDo.setWorkshopid(checkTemplate.getYjorgid());
                    pointCheckDo.setWorkshopname(checkTemplate.getYjorgname());
                    //设备ID
                    pointCheckDo.setCheckitemid(checkItemsdo.getId());
                    //班次
                    pointCheckDo.setShift(shift);
                    //点检状态默认待点检
                    pointCheckDo.setCheckstatus(MlConstants.POINT_CHECK_STATUS_WAIT);
                    // 点检预警状态默认正常
                    pointCheckDo.setCheckwarnstatus(MlConstants.POINTCEHCK_WARNSTATUS_NORMAL);
                    pointCheckDo.setTenantid(checkTemplate.getTenantid());
                    pointCheckDo.setSource("1");
                    pointCheckDo.setTemplatetype(templatetype);
                    BeanUtil.copyProperties(pointCheckDo,pointCheckVo);
                    //添加设备名称和设备编号
                    pointCheckVo.setCheckitemname(checkItemsdo.getCheckitemname());
                    pointCheckVo.setCheckitemcode(checkItemsdo.getCheckitemcode());
                    //设备负责人
                    List<CheckItemsDutyuserDo> checkItemsDutyusers =checkItemsDutyuserService.list(new LambdaQueryWrapper<CheckItemsDutyuserDo>()
                            .eq(BaseDo::getDeleted,"0")
                            .eq(CheckItemsDutyuserDo::getCheckitemid,checkItemsdo.getId())
                            .like(CheckItemsDutyuserDo::getDutyuserattribute,templatetype));

                    // 组织需要发送德消息
                    if (!checkItemsDutyusers.isEmpty()){
                        notifyType.put(pointCheckVo,checkItemsDutyusers.stream().map(CheckItemsDutyuserDo::getDutyuserid).distinct().collect(Collectors.toList()));
                    }
                    //设置点检人
//                    String pcids = null;
//                    String pcnames = null;
//                    if (checkItemsDutyusers != null && checkItemsDutyusers.size() > 0) {
//                        for (CheckItemsDutyuserDo checkItemsDutyuser : checkItemsDutyusers) {
//                            // 生产属性的员工为点检人
//                            if (MlConstants.USER_ATTR_PRODUCTION.equals(checkItemsDutyuser.getDutyuserattribute())) {
//                                if (pcids == null) {
//                                    pcids = checkItemsDutyuser.getDutyuserid();
//                                    pcnames = checkItemsDutyuser.getDutyusername();
//                                } else {
//                                    pcids = pcids + "," + checkItemsDutyuser.getDutyuserid();
//                                    pcnames = pcnames + "," + checkItemsDutyuser.getDutyusername();
//                                }
//                            }
//                        }
//                    }
                    //有设备负责人则设置点检人为设备负责人
                        /*if(pcids != null){
                            pointCheckDo.setCheckuserid(pcids);
                            pointCheckDo.setCheckusername(pcnames);
                        }else{
                            //如果没有设备负责人则设置为所属工段所有员工
                            String orgid = checkItemsdo.getChargeorgid();
                            if(StringUtils.isNotEmpty(orgid)){
                                SysUserVo sysUserVo = new SysUserVo();
                                sysUserVo.setMainorgid(orgid);
                                List<SysUserVo> us = sysUserDao.getSameDept(sysUserVo);
                                if(us != null && us.size()>0){
                                    for(SysUserVo sysUser:us){
                                        if(pcids == null){
                                            pcids = sysUser.getId();
                                            pcnames = sysUser.getName();
                                        }else{
                                            if(pcids.indexOf(sysUser.getId()) == -1){
                                                pcids = pcids+","+sysUser.getId();
                                                pcnames = pcnames+","+sysUser.getName();
                                            }
                                        }
                                    }
                                }
                                // 设置归属工段的所有员工为点检人
                                if(pcids != null){
                                    pointCheckDo.setCheckuserid(pcids);
                                    pointCheckDo.setCheckusername(pcnames);
                                }
                            }
                        }*/

                    //点检明细生成
                    if(checkItems != null && checkItems.size()>0){
                        checkItems.forEach(v -> {
                            PointCheckItemDo pointCheckItemDo = new PointCheckItemDo();
                            pointCheckItemDo.setId(SecurityUtil.getUUID());
                            pointCheckItemDo.setPointcheckid(pointCheckDo.getId());
                            pointCheckItemDo.setTenantid(checkTemplate.getTenantid());
                            // 检查内容模板
                            CheckItemContentDo checkItemContent = checkItemContentService.getById(v.getCheckitemcontentid());
                            pointCheckItemDo.setCheckitemcontentid(v.getCheckitemcontentid());
                            if(checkItemContent != null){
                                pointCheckItemDo.setCheckitemcontentman(checkItemContent.getManagement());
                            }
                            pointCheckItemDo.setCheckposition(v.getCheckposition());
                            pointCheckItemDo.setCheckcontent(v.getCheckcontent());
                            pointCheckItemDo.setChecktype(v.getChecktype());
                            pointCheckItemDo.setCheckstandard(v.getCheckstandard());
                            pointCheckItemDo.setFrequencyids(v.getFrequencyids());
                            pointCheckItemDo.setFrequency(v.getFrequency());
                            pointCheckItemDo.setShift(v.getShift());
                            pointCheckItemDo.setShiftcount(v.getShiftcount());
                            // 排序字段
                            pointCheckItemDo.setItemsort(v.getItemsort());
                            pointCheckItemDo.setSource("1");
                            pointCheckItems.add(pointCheckItemDo);
                        });
                    }
                    pointChecks.add(pointCheckDo);
                }
            }else{
                logger.error("点检定时任务生成时，检查模板（ID："+checkTemplate.getId()+"）没有设备");
            }
        }

        if(!notifyType.isEmpty()){
            List<SysDictDo> dictsByType = commonDictService.getDictsByType("template-type");
            notifyType.forEach((k,v)-> {
                String pointcheckname = k.getPointcheckname();
                String templatetype = k.getTemplatetype();
                //发送消息提醒添加设备名称和设备编号拼接
                String checkitemname = k.getCheckitemname();
                String checkitemcode = k.getCheckitemcode();
                SysDictDo sysDictDo = dictsByType.stream().filter(info -> info.getValue().equals(templatetype)).findFirst().orElse(null);
                CXCommonUtils.sendNotify(INSPECTION_TITLE, String.format(INSPECTION_CONTENT, pointcheckname,checkitemname,checkitemcode, sysDictDo == null ? "" : sysDictDo.getName()),
                        null, v, k.getId(), INSPECTION + "-" + shift, false);
            });
        }
        // 批量保存点检任务
        pointCheckService.saveBatch(pointChecks);
        pointCheckItemService.saveBatch(pointCheckItems);
    }

    /**
     * 更新历史版本的模板状态为关闭
     * @param map
     */
    @Override
    public void updateStatusByHiId(Map<String,Object> map){
        if(map.get("oldId") != null){
            String oldId = map.get("oldId").toString();
            CheckTemplateDo checkTemplate = new CheckTemplateDo();
            checkTemplate.setId(oldId);
            checkTemplate.setEnablestatus(MlConstants.TEMPLATE_STATUS_CLOSE);
            this.updateById(checkTemplate);
        }
    }
}
