package com.yeejoin.amos.boot.module.tzs.flc.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.module.tzs.api.dto.LicScheduleDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.WarningMsgDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.EquScheduleDto;
import com.yeejoin.amos.boot.module.tzs.api.entity.MsgLog;
import com.yeejoin.amos.boot.module.tzs.api.entity.TzBaseUnitLicence;
import com.yeejoin.amos.boot.module.tzs.api.entity.TzsJgRegistrationInfo;
import com.yeejoin.amos.boot.module.tzs.api.enums.EarlyWarningLevelEnum;
import com.yeejoin.amos.boot.module.tzs.api.enums.WarningTypeEnum;
import com.yeejoin.amos.boot.module.tzs.api.mapper.ScheduleMapper;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.MsgLogServiceImpl;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.TzBaseUnitLicenceServiceImpl;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.TzsAuthServiceImpl;
import com.yeejoin.amos.boot.module.tzs.biz.service.impl.TzsJgRegistrationInfoServiceImpl;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.CylinderInfoDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.entity.CylinderInfo;
import com.yeejoin.amos.boot.module.tzs.flc.api.mapper.CylinderInfoMapper;
import com.yeejoin.amos.component.rule.RuleTrigger;
import com.yeejoin.amos.feign.rule.Rule;
import com.yeejoin.amos.feign.rule.model.FactBaseModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author Zhang Yingbin
 */
@Service
@Slf4j
public class ScheduleService {

    @Autowired
    private ScheduleMapper scheduleMapper;

    @Autowired
    MsgLogServiceImpl msgLogServiceImpl;

    @Autowired
    TzsAuthServiceImpl tzsAuthService;

    @Autowired
    private RuleTrigger ruleTrigger;

    @Autowired
    private CylinderInfoServiceImpl cylinderInfoService;

    @Autowired
    private TzsJgRegistrationInfoServiceImpl RegistrationInfoService;

    @Autowired
    private TzBaseUnitLicenceServiceImpl baseUnitLicenceService;

    @Autowired
    CylinderInspectionServiceImpl cylinderInspectionService;

    @Value("${cylinder-early-warning-packageId:预警消息/cylWarningMsg}")
    private String cylPackageId;

    @Value("${cylinder-early-warning-packageId:预警消息/equWarningMsg}")
    private String equPackageId;

    @Value("${cylinder-early-warning-packageId:预警消息/licWarningMsg}")
    private String licPackageId;


    public void calEarlyWarningLevel() {
        if (log.isDebugEnabled()) {
            log.debug("超期预警时间调用规则开始");
        }
        // 1.批量分组大小
        int size = 500;
        int cylTotal = cylinderInspectionService.count();
        int equTotal = RegistrationInfoService.count();
        int licTotal = baseUnitLicenceService.count();
        int cylGroupNumber = cylTotal / size + 1;
        int equGroupNumber = equTotal / size + 1;
        int licGroupNumber = licTotal / size + 1;

    // 2.批量小分组处理数据，调用规则
        // 气瓶
        for (int i = 0; i < cylGroupNumber; i++) {

            Page<CylinderInfo> cylPage = new Page<>();
            cylPage.setCurrent(i);
            cylPage.setSize(size);
//            LambdaQueryWrapper<CylinderInfo> cylWrapper = new LambdaQueryWrapper<>();
//            cylWrapper.select(CylinderInfo::getSequenceCode, CylinderInfo::getSequenceNbr).orderByDesc(CylinderInfo::getSequenceNbr);
            IPage<CylinderInfo> cylresult = scheduleMapper.cylinderInfoPage(cylPage);
            for (CylinderInfo r : cylresult.getRecords()) {
                // 设置token
                tzsAuthService.setRequestContext();
                // 调用规则
                this.clyTouchRuleToCalLevel(r);
            }
        }

        //设备
        for (int i = 0; i < equGroupNumber; i++) {
            Page<TzsJgRegistrationInfo> equPage = new Page<>();
            equPage.setCurrent(i);
            equPage.setSize(size);
            LambdaQueryWrapper<TzsJgRegistrationInfo> equWrapper = new LambdaQueryWrapper<>();
            equWrapper.select(TzsJgRegistrationInfo::getSequenceCode, TzsJgRegistrationInfo::getSequenceNbr).orderByDesc(TzsJgRegistrationInfo::getSequenceNbr);
            IPage<TzsJgRegistrationInfo> equResult = RegistrationInfoService.page(equPage, equWrapper);
            for (TzsJgRegistrationInfo r : equResult.getRecords()) {
                // 设置token
                tzsAuthService.setRequestContext();
                // 调用规则
                this.equTouchRuleToCalLevel(r);
            }
        }

        //许可
        for (int i = 0; i < licGroupNumber; i++) {
            Page<TzBaseUnitLicence> licPage = new Page<>();
            licPage.setCurrent(i);
            licPage.setSize(size);
            LambdaQueryWrapper<TzBaseUnitLicence> LicWrapper = new LambdaQueryWrapper<>();
            LicWrapper.select(TzBaseUnitLicence::getCertNo,TzBaseUnitLicence::getSequenceNbr).orderByDesc(TzBaseUnitLicence::getSequenceNbr);
            IPage<TzBaseUnitLicence> licResult = baseUnitLicenceService.page(licPage, LicWrapper);
            for (TzBaseUnitLicence r : licResult.getRecords()) {
                // 设置token
                tzsAuthService.setRequestContext();
                // 调用规则
                this.licTouchRuleToCalLevel(r);
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("超期预警时间调用规则完成");
        }

        //检查msgLog中的消息,若下次检验日期已延续 则更新消息状态
        List<MsgLog> msgLogList = msgLogServiceImpl.list(new LambdaQueryWrapper<MsgLog>().eq(MsgLog::getIsDelete,false));
        Date now = new Date();
        for(MsgLog msgLog:msgLogList){
            msgLog.getRelationCode();
            try {
                CylinderInfoDto cylinderInfoDto = this.getCylDetail(msgLog.getRelationCode());
                int interval = DateUtils.dateBetweenIncludeToday(now, cylinderInfoDto.getNextInspectionDate()) - 1;
                if(interval>30){
                    msgLog.setIsDelete(true);
                    msgLog.setMsgTypeName("已延期");
                    msgLogServiceImpl.updateById(msgLog);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 气瓶预警规则
     * @param r
     */
    private void clyTouchRuleToCalLevel(CylinderInfo r) {
        Date now = new Date();
        String dateStr;
        try {
            dateStr = DateUtils.dateFormat(now,DateUtils.DATE_TIME_PATTERN);
        } catch (ParseException e) {
            throw  new RuntimeException("日期个时候失败");
        }
        //1.气瓶详情
        CylinderInfoDto cylinderInfoDto = this.getCylDetail(r.getSequenceCode());
        try {
            WarningMsgDto warningMsgDto = new WarningMsgDto();
            //没有下次检验日期的气瓶默认正常
            if(ValidationUtil.isEmpty(cylinderInfoDto.getNextInspectionDate())){
                System.out.println("气瓶编号为："+cylinderInfoDto.getSequenceCode()+"的气瓶，没有下次检验日期数据");
                return;
            }
            int interval = DateUtils.dateBetweenIncludeToday(now, cylinderInfoDto.getNextInspectionDate()) - 1;

            if(interval<30 && interval>=0){
                warningMsgDto.setOverType("即将超期");
            }else if(interval<0){
                warningMsgDto.setOverType("已超期");
            }else{
                //正常的气瓶不需要发消息
                warningMsgDto.setOverType("正常");
                return;
            }
            warningMsgDto.setNextInspectDate(new SimpleDateFormat("yyyy-MM-dd").format(cylinderInfoDto.getNextInspectionDate()));
            warningMsgDto.setType("气瓶");
            warningMsgDto.setWarningType(WarningTypeEnum.getEumByLevel("1").getName());
            warningMsgDto.setNum(String.valueOf(interval));
            warningMsgDto.setFactoryNum(cylinderInfoDto.getFactoryNum());
//            warningMsgDto.setUserType(cylinderInfoDto.getCustomType());
//            warningMsgDto.setUserPeople(cylinderInfoDto.getCustomName());
//            warningMsgDto.setUserPeoplePhone(cylinderInfoDto.getContactPhone());
            warningMsgDto.setCode(cylinderInfoDto.getSequenceCode());
            warningMsgDto.setCompanyName(cylinderInfoDto.getUnitName());
            warningMsgDto.setPhone(cylinderInfoDto.getPersonMobilePhone());
            warningMsgDto.setPeople(cylinderInfoDto.getUnitPerson());
            warningMsgDto.setCurrentTime(dateStr);
            // 2.循环调用规则 触发计算等级及发送消息
            if (log.isInfoEnabled()) {
                log.info("调用气瓶规则对象！+：{}", JSON.toJSONString(warningMsgDto));
            }
            String[] test = new String[]{};
            this.rulePublish(warningMsgDto,cylPackageId);
            System.out.println("----------------------------------tzs服务调用了规则--------------------------------------");
        } catch (Exception e) {
            log.error("调用气瓶规则失败！:{},{}", JSON.toJSONString(cylinderInfoDto),e);
        }
    }

    /**
     * 调用规则公用方法
     */
    public void rulePublish(WarningMsgDto warningMsgDto,String packageId){
        FactBaseModel factBaseModel = new FactBaseModel();
        factBaseModel.setPackageId(packageId);
        factBaseModel.setProcessIds(new String[0]);
        HashMap<String,byte[]> map = new HashMap();
        map.put("com.yeejoin.amos.boot.module.tzs.api.dto.WarningMsgDto",JSONObject.toJSONString(warningMsgDto).getBytes());
        factBaseModel.setFactMap(map);
        Rule.ruleClient.fireRule(factBaseModel);
    }

    /**
     * 气瓶规则调用
     * @param sequenceCode
     * @return
     */
    public CylinderInfoDto getCylDetail(String sequenceCode) {
        CylinderInfoDto dto = scheduleMapper.getCylDetail(sequenceCode);
        dto.setInspectionStatusDesc(StringUtils.isNotEmpty(dto.getEarlyWarningLevel()) ? EarlyWarningLevelEnum.getEumByLevel(dto.getEarlyWarningLevel()).getStatus() : "");
        return dto;
    }


    /**
     * 设备预警规则
     * @param r
     */
    private void equTouchRuleToCalLevel(TzsJgRegistrationInfo r) {
        Date now = new Date();
        String dateStr;
        try {
            dateStr = DateUtils.dateFormat(now,DateUtils.DATE_TIME_PATTERN);
        } catch (ParseException e) {
            throw  new RuntimeException("日期个时候失败");
        }
        //1.设备详情
        EquScheduleDto equScheduleDto = this.getEquDetail(r.getSequenceCode());
        try {
            WarningMsgDto warningMsgDto = new WarningMsgDto();
            int interval = DateUtils.dateBetweenIncludeToday(now, equScheduleDto.getNextInspectDate()) - 1;
            if(interval<30 && interval>=0){
                warningMsgDto.setOverType("即将超期");
            }else if(interval<0){
                warningMsgDto.setOverType("已超期");
            }else{
                warningMsgDto.setOverType("正常");
            }
            warningMsgDto.setNextInspectDate(new SimpleDateFormat("yyyy-MM-dd").format(equScheduleDto.getNextInspectDate()));
            warningMsgDto.setType(equScheduleDto.getEquDefine());
            warningMsgDto.setWarningType(WarningTypeEnum.getEumByLevel("2").getName());
            warningMsgDto.setNum(String.valueOf(interval));
            warningMsgDto.setFactoryNum(equScheduleDto.getUseOrgCode());
//            warningMsgDto.setUserType(cylinderInfoDto.getCustomType());
//            warningMsgDto.setUserPeople(cylinderInfoDto.getCustomName());
//            warningMsgDto.setUserPeoplePhone(cylinderInfoDto.getContactPhone());
            warningMsgDto.setCode(equScheduleDto.getSequenceCode());
            warningMsgDto.setCompanyName(equScheduleDto.getSafetyManageDt());
            warningMsgDto.setPhone(equScheduleDto.getPhone());
            warningMsgDto.setPeople(equScheduleDto.getSafetyManager());
            warningMsgDto.setCurrentTime(dateStr);
            // 2.循环调用规则 触发计算等级及发送消息
            if (log.isInfoEnabled()) {
                log.info("调用设备规则对象！+：{}", JSON.toJSONString(warningMsgDto));
            }
            this.rulePublish(warningMsgDto,equPackageId);
        } catch (Exception e) {
            log.error("调用设备规则失败！:{},{}", JSON.toJSONString(equScheduleDto),e);
        }
    }

    /**
     * 装备规则调用
     * @param sequenceCode
     * @return
     */
    public EquScheduleDto getEquDetail(String sequenceCode) {
        EquScheduleDto dto = scheduleMapper.getEquDetail(sequenceCode);
        return dto;
    }


    /**
     * 许可预警规则
     * @param r
     */
    private void licTouchRuleToCalLevel(TzBaseUnitLicence r) {
        Date now = new Date();
        String dateStr;
        try {
            dateStr = DateUtils.dateFormat(now,DateUtils.DATE_TIME_PATTERN);
        } catch (ParseException e) {
            throw  new RuntimeException("日期个时候失败");
        }
        //1.许可详情
        LicScheduleDto licScheduleDto = this.getLicDetail(String.valueOf(r.getSequenceNbr()));
        try {
            WarningMsgDto warningMsgDto = new WarningMsgDto();
            int interval = DateUtils.dateBetweenIncludeToday(now, licScheduleDto.getExpiryDate()) - 1;
            if(interval<200 && interval>=0){
                warningMsgDto.setOverType("即将超期");
            }else if(interval<0){
                warningMsgDto.setOverType("已超期");
            }else{
                warningMsgDto.setOverType("正常");
            }
            warningMsgDto.setNextInspectDate(new SimpleDateFormat("yyyy-MM-dd").format(licScheduleDto.getExpiryDate()));
            warningMsgDto.setType("许可");
            warningMsgDto.setWarningType(WarningTypeEnum.getEumByLevel("3").getName());
            warningMsgDto.setNum(String.valueOf(interval));
            warningMsgDto.setFactoryNum(licScheduleDto.getApprovedOrganCode());
            warningMsgDto.setCode(licScheduleDto.getCertNo());
            warningMsgDto.setCompanyName(licScheduleDto.getUnitName());
            warningMsgDto.setPhone(licScheduleDto.getPhone());
            warningMsgDto.setPeople(licScheduleDto.getPeople());
            warningMsgDto.setCurrentTime(dateStr);
            // 2.循环调用规则 触发计算等级及发送消息
            if (log.isInfoEnabled()) {
                log.info("调用许可规则对象！+：{}", JSON.toJSONString(warningMsgDto));
            }
            this.rulePublish(warningMsgDto,licPackageId);
        } catch (Exception e) {
            log.error("调用许可规则失败！:{},{}", JSON.toJSONString(licScheduleDto),e);
        }
    }

    /**
     * 许可规则调用
     * @param sequenceNbr
     * @return
     */
    public LicScheduleDto getLicDetail(String sequenceNbr) {
        LicScheduleDto dto = scheduleMapper.getLicDetail(sequenceNbr);
        return dto;
    }

}
