package com.huatek.busi.service.impl.gis;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huatek.busi.common.BusiConstant;
import com.huatek.busi.common.CacMonitorTypeCode;
import com.huatek.busi.common.DateUtils;
import com.huatek.busi.common.SiteConstants;
import com.huatek.busi.common.SiteConstants.ExternalTypeEnum;
import com.huatek.busi.common.SiteConstants.GisTreeEnum;
import com.huatek.busi.common.SiteConstants.SiteTreeEnum;
import com.huatek.busi.common.util.DecimalUtil;
import com.huatek.busi.common.util.TimeUtil;
import com.huatek.busi.common.util.Tools;
import com.huatek.busi.dao.*;
import com.huatek.busi.dto.*;
import com.huatek.busi.dto.curve.BaseCurveQueryDto;
import com.huatek.busi.dto.curve.PointItemDto;
import com.huatek.busi.entity.*;
import com.huatek.busi.mapper.GisSf6IncreaseRateCacheMapper;
import com.huatek.busi.mapper.GisSf6PressureMapper;
import com.huatek.busi.mapper.Sf6EnvMapper;
import com.huatek.busi.service.BusiSiteTreeService;
import com.huatek.busi.service.IecBydworkParamService;
import com.huatek.busi.service.gis.*;
import com.huatek.busi.service.impl.cac.AbstractCacEtlService;
import com.huatek.busi.service.threshold.CwzzThresholdService;
import com.huatek.busi.service.threshold.Sf6EnvThresholdService;
import com.huatek.busi.util.CalcUtil;
import com.huatek.busi.vo.*;
import com.huatek.busi.vo.curve.PointItemVo;
import com.huatek.busi.vo.monitor.BusiOnlineMonitorDataVo;
import com.huatek.busi.vo.warning.BusiWcgVo;
import com.huatek.torch.frame.exception.OwlException;
import com.huatek.torch.frame.tools.ConstantUtil;
import com.huatek.torch.frame.tools.ResultUtil;
import com.huatek.torch.sql.beans.WherePrams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * SF6环境监测
 *
 * @author vent
 * @date Jun 26, 2019 1:11:48 PM
 */
@Slf4j
@Component
@Service(interfaceClass = Sf6EnvService.class)
@Transactional(rollbackFor = Exception.class)
public class Sf6EnvServiceImpl extends AbstractCacEtlService<GisSf6Env> implements Sf6EnvService {
    @Autowired
    private Sf6EnvMapper sf6EnvMapper;
    @Autowired
	private GisSf6IncreaseRateCacheMapper gisSf6IncreaseRateCacheMapper;

    @Reference(check = false)
    private BusiSiteTreeService busiSiteTreeService;

    @Reference(check = false)
    private IecBydworkParamService iecBydworkParamService;

    @Autowired
    private Sf6EnvThresholdService sf6EnvThresholdService;

    @Autowired
    private BusiTransformerSensorDao busiTransformerSensorDao;

    @Autowired
    private BusiGisSensorDao busiGisSensorDao;
    @Autowired
    private BusiOnlineMonitorDataDao busiOnlineMonitorDataDao;

    @Autowired
    private GisSf6EnvDao gisSf6EnvDao;

    @Autowired
    private Sf6EnvThresholdDao sf6EnvThresholdDao;

    @Autowired
    private BusiGisSensorService busiGisSensorService;

    @Autowired
    private BusiGisSubTreeDao busiGisSubTreeDao;

    @Override
    protected void saveHistoryData(GisSf6Env cacEntity, EquipmentInfoDto equipmentInfo) {

        // 设置rowkey，导入hbase使用
        cacEntity.setHbaseRowkey(Tools.strReverse(TimeUtil.getTimeStr(cacEntity.getTimeStamp())) + "_"
                + cacEntity.getSensorId() + "_" + TimeUtil.getTimeStr(cacEntity.getTimeStamp()) + "_"
                + cacEntity.getCacMonitorTypeCode() + "_" + cacEntity.getMainTreeId());
        // 设备状态
        String state = iecBydworkParamService.getIecType(cacEntity.getMainTreeId(), cacEntity.getTimeStamp());
        if (StringUtils.isEmpty(state)) {
            logger.warn("IecType is empty! eqmCode: {}, timeStamp: {}", cacEntity.getEquipmentCode(),
                    cacEntity.getTimeStamp());
        }
        cacEntity.setRunState(state);
        super.saveHistoryData(cacEntity, equipmentInfo);
    }



    // √
    @Override
    protected void saveBusiWarning(GisSf6Env gisSf6Env, String cacMonitorTypeCode, String sensorId,
                                   EquipmentInfoDto equipmentInfo) {
        equipmentInfo.setSensorCode(sensorId);
        CacMonitorTypeCode type = CacMonitorTypeCode.from(cacMonitorTypeCode);

        String tmp = gisSf6Env.getTmp();
        // 阈值
        Sf6EnvThresholdVo threshold = sf6EnvThresholdService.querySf6EnvThreshold(gisSf6Env.getSensorId(), gisSf6Env.getRunState());
        if (threshold == null) {
            logger.warn("Gis SF6环境监测，sensorCode: {}, runState: {}", gisSf6Env.getSensorId(), gisSf6Env.getRunState());
            return;
        }
        String eqType = BusiConstant.EqType.EQ_TYPE2;
        // 告警 温度
        if (isThreshold(tmp, threshold.getTmp())) {
            // 保存告警
            BusiEqmWarning busiEqmWarning = newEw(eqType, BusiConstant.GzType.GZ_TYPE22, formateCwWarningMsg("{}SF6环境监测：{}℃温度超标",gisSf6Env.getPhase(),gisSf6Env.getTmp()),
                    gisSf6Env.getCacMonitorTypeCode(),"1");
            busiEqmWarning.setWarningTime(gisSf6Env.getTimeStamp());
            busiEqmWarning.setRunState(gisSf6Env.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiWcgVo vo = new BusiWcgVo();
            vo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            vo.setCollectValue(tmp);
            vo.setAlarmValue(tmp);
            vo.setThresholdValue(threshold.getTmp());
            vo.setEquipmentStatus(gisSf6Env.getRunState());
            vo.setCollectDate(gisSf6Env.getTimeStamp());
            vo.setDayIncreaseRate("");
            vo.setMonthIncreaseRate("");
            vo.setPhase(gisSf6Env.getPhase());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(vo));
        }
        // 告警 湿度
        if (isThreshold(gisSf6Env.getDew(), threshold.getDew())) {

            // 保存告警
            BusiEqmWarning busiEqmWarning = newEw(eqType, BusiConstant.GzType.GZ_TYPE22, formateCwWarningMsg("{}SF6环境监测：{}湿度超标",gisSf6Env.getPhase(),gisSf6Env.getDew()),
                    gisSf6Env.getCacMonitorTypeCode(),"1");
            busiEqmWarning.setWarningTime(gisSf6Env.getTimeStamp());
            busiEqmWarning.setRunState(gisSf6Env.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiWcgVo vo = new BusiWcgVo();
            vo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            vo.setCollectValue(gisSf6Env.getDew().toString());
            vo.setAlarmValue(gisSf6Env.getDew().toString());
            vo.setThresholdValue(threshold.getDew().toString());
            vo.setEquipmentStatus(gisSf6Env.getRunState());
            vo.setCollectDate(gisSf6Env.getTimeStamp());
            vo.setDayIncreaseRate("");
            vo.setMonthIncreaseRate("");
            vo.setPhase(gisSf6Env.getPhase());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(vo));
        }

        if (isThreshold(gisSf6Env.getConc(), threshold.getConc())) {
            // 保存告警
            BusiEqmWarning busiEqmWarning = newEw(eqType, BusiConstant.GzType.GZ_TYPE22, formateCwWarningMsg("{}SF6环境监测：{}SF6浓度超标",gisSf6Env.getPhase(),gisSf6Env.getConc()),
                    gisSf6Env.getCacMonitorTypeCode(),"1");
            busiEqmWarning.setWarningTime(gisSf6Env.getTimeStamp());
            busiEqmWarning.setRunState(gisSf6Env.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiWcgVo vo = new BusiWcgVo();
            vo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            vo.setCollectValue(gisSf6Env.getConc().toString());
            vo.setAlarmValue(gisSf6Env.getConc().toString());
            vo.setThresholdValue(threshold.getConc().toString());
            vo.setEquipmentStatus(gisSf6Env.getRunState());
            vo.setCollectDate(gisSf6Env.getTimeStamp());
            vo.setDayIncreaseRate("");
            vo.setMonthIncreaseRate("");
            vo.setPhase(gisSf6Env.getPhase());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(vo));
        }

        if (isThreshold(gisSf6Env.getOContent(), threshold.getOContent())) {
            // 保存告警
            BusiEqmWarning busiEqmWarning = newEw(eqType, BusiConstant.GzType.GZ_TYPE22, formateCwWarningMsg("{}SF6环境监测：{}O2含量超标",gisSf6Env.getPhase(),gisSf6Env.getOContent()),
                    gisSf6Env.getCacMonitorTypeCode(),"1");
            busiEqmWarning.setWarningTime(gisSf6Env.getTimeStamp());
            busiEqmWarning.setRunState(gisSf6Env.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiWcgVo vo = new BusiWcgVo();
            vo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            vo.setCollectValue(gisSf6Env.getOContent().toString());
            vo.setAlarmValue(gisSf6Env.getOContent().toString());
            vo.setThresholdValue(threshold.getOContent().toString());
            vo.setEquipmentStatus(gisSf6Env.getRunState());
            vo.setCollectDate(gisSf6Env.getTimeStamp());
            vo.setDayIncreaseRate("");
            vo.setMonthIncreaseRate("");
            vo.setPhase(gisSf6Env.getPhase());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(vo));
        }
    }
    @Override
    public Sf6EnvStatisticsVo getListEquInfo(String cacMonitorTypeCode, LocalDate day, String sensorCode) {
        CwzzTemperatureStatisticsDto param = new CwzzTemperatureStatisticsDto();
        param.setStartTime(day.atStartOfDay());
        param.setEndTime(day.plusDays(1).atStartOfDay());
        param.setCacMonitorTypeCode(cacMonitorTypeCode);
        param.setSensorCode(sensorCode);
        List<Sf6EnvStatisticsVo> list = sf6EnvMapper.getListEquInfo(param);
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    @Override
    public List<HomeActualVo> queryActuals() {
        List<HomeActualVo> homeActualVos=new ArrayList<>();
        List<String> equipmentTypeList=new ArrayList<>();
        equipmentTypeList.add(GisTreeEnum.HJJC_EQM.getValue());
        BusiSensorQueryParamDto param =new BusiSensorQueryParamDto();
        param.setEquipmentTypeList(equipmentTypeList);
        List<BusiSensorVo> sensorList = busiGisSensorService.findSensorList(param);
        if(CollectionUtils.isEmpty(sensorList)){
            return homeActualVos;
        }
        for (BusiSensorVo busiSensorVo:sensorList) {
            HomeSearchDto homeSearchDto= new HomeSearchDto();
            homeSearchDto.setSensorCode(busiSensorVo.getSensorCode());
            HomeActualVo homeActualVo = this.queryActual(homeSearchDto);
            homeActualVo.setName(busiSensorVo.getMainEquipmentName());
            homeActualVos.add(homeActualVo);
        }
        return homeActualVos;
    }

    /**
     * 判断告警
     */
    private static boolean isThreshold(String aVal, String bVal) {
        if (StringUtils.isEmpty(bVal) ) {
            return false;
        }
        return DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(bVal)) > 0;
    }

    private String formateCwWarningMsg(String msg,String phase ,String val ) {
        return format(msg, phase, val);
    }


    private String msg(TransformerInfraredTemperature cacEntity) {
        return format("温度:{}℃超标", cacEntity.getMaxTmp());
    }

    /**
     * 原始数据查询
     */
    @Override
    public Map<String, Object> findCACPageData(Map<String, Object> params) {
        if (params.get("page") != null && params.get("limit") != null) {
            PageHelper.startPage(page(params), limit(params));
        }
        Page<Map<String, Object>> page = sf6EnvMapper.findCACPageData(params);
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, page.getTotal(), "", page.getResult());
    }

    @Override
    public Map<String, Object> exportCacMonitorData(Map<String, Object> mapParams) {
        Map<String, Object> returnMap = new HashMap<>();
        if (mapParams.containsKey("mainTreeId") && StringUtils.isNotEmpty(mapParams.get("mainTreeId") + "")) {
            BusiSiteTree busiSiteTree = busiSiteTreeService.findByPK(mapParams.get("mainTreeId") + "");
            List<Sf6EnvVo> cwzzTemperatureList =
                    sf6EnvMapper.exportCacMonitorData(mapParams);
            String replaceRegex = "[\\\\n`~!@#$%^&*()+=|{}':;',\\\\\\\\[\\\\\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， 、？]";
            String treeName = busiSiteTree.getName().replaceAll(replaceRegex, "-");
            returnMap.put("fileName", String.format("%s%s", treeName, "测温数据"));
            returnMap.put("title", String.format("%s%s", treeName, "测温数据"));
            if (cwzzTemperatureList.isEmpty()) {
                cwzzTemperatureList = new ArrayList<>();
                cwzzTemperatureList.add(new Sf6EnvVo());
            }
            returnMap.put("data", cwzzTemperatureList);
        } else {
            throw new RuntimeException("主设备编码不正确");
        }
        return returnMap;
    }

    @Override
    public List<BaseCurveQueryDto> findSensorCodeList(LocalDate day) {
        return sf6EnvMapper.findSensorCodeList(day.atStartOfDay(),
                day.plusDays(1).atStartOfDay());
    }

    @Override
    public List<PointItemVo> findDaylyPointList(BaseCurveQueryDto sensorCode, LocalDate day, String subType) {
        return sf6EnvMapper.findDaylyPointList(sensorCode, subType, day.atStartOfDay(),
                day.plusDays(1).atStartOfDay());
    }

    @Override
    public PointItemDto getDaylyPointStatistics(BaseCurveQueryDto param) {
        return sf6EnvMapper.getDaylyPointStatistics(param);
    }

    @Override
    protected List<Map<String, Object>> queryMonitorDataList(LocalDateTime startTime, LocalDateTime endTime) {
        return sf6EnvMapper.queryMonitorDataList(startTime, endTime);
    }

    // 保存监测数据
    @Override
    protected void saveBusiOnlineMonitorData(BusiOnlineMonitorData busiOnlineMonitorData, Map<String, Object> item) {
        String cacMonitorTypeCode = popString(item, "cacMonitorTypeCode");
        busiOnlineMonitorData.setSubEquipmentType(SiteConstants.GisTreeEnum.HJJC_EQM.getValue());
        busiOnlineMonitorData.setExtType(ExternalTypeEnum.GIS.getValue());
        busiOnlineMonitorData.setEquipmentType(SiteTreeEnum.GIS_HL_EQM.getValue());
        // 这里将保存的任务交给父类方法完成，子类只需要修改指定几个字段就可以了
        super.saveBusiOnlineMonitorData(busiOnlineMonitorData, item);
    }

    @Override
    protected Map<String, Object> thresholdDataMap(BusiOnlineMonitorDataVo vo) {
        return null;
    }

    public  HomeActualInfoVo build(HomeActualInfoVo homeActualInfoVo,BusiGisSensor busiGisSensor,String mainTreeId){
        homeActualInfoVo.setEquipmentBrand(busiGisSensor.getSensorBrand());
        homeActualInfoVo.setEquipmentName(busiGisSensor.getSensorName());
        homeActualInfoVo.setInstallLocation(busiGisSensor.getPositionDes());
        homeActualInfoVo.setEqmId(busiGisSensor.getEquipmentId());
        homeActualInfoVo.setPhase(busiGisSensor.getPosition());
        homeActualInfoVo.setManufactor(busiGisSensor.getManufactor());
        homeActualInfoVo.setSensorBrand(busiGisSensor.getSensorBrand());
        homeActualInfoVo.setUseDate(busiGisSensor.getUseDate());
        homeActualInfoVo.setSensorId(busiGisSensor.getSensorCode());
        homeActualInfoVo.setSensorName(busiGisSensor.getSensorName());
        homeActualInfoVo.setMainTreeId(mainTreeId);
        return homeActualInfoVo;
    }
    @Override
    public HomeActualVo queryActual(HomeSearchDto param) {
        HomeActualVo homeActualVo=new HomeActualVo();
        List<BusiGisSensor> busiGisSensors = busiGisSensorDao.list(new WherePrams()
                .where("sensor_code", param.getSensorCode()));
        if(ObjectUtils.isEmpty(busiGisSensors)){
            return homeActualVo;
        }
        BusiGisSensor busiGisSensor = busiGisSensors.get(0);
        HomeActualInfoVo homeActualInfoVo =new HomeActualInfoVo();
        String mainTreeId=busiGisSubTreeDao.get(busiGisSensor.getEquipmentId()).getEquipmentId();
        homeActualInfoVo = build(homeActualInfoVo, busiGisSensor,mainTreeId);
        String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, DateUtils.addDays(new Date(), -1));
        List<BusiOnlineMonitorData> busiOnlineMonitorDatas = busiOnlineMonitorDataDao.list(new WherePrams()
                .where("sensor_code", param.getSensorCode())
                .and("day","like",date));
        //组装各种率
        if(!ObjectUtils.isEmpty(busiOnlineMonitorDatas)){
            BusiOnlineMonitorData busiOnlineMonitorData = busiOnlineMonitorDatas.get(0);
            homeActualInfoVo.setRunState(busiOnlineMonitorData.getRunState());
            homeActualInfoVo.setFalseAlarmRate(busiOnlineMonitorData.getFalseAlarmRate());
            homeActualInfoVo.setLossRate(busiOnlineMonitorData.getLossRate());
            homeActualInfoVo.setRepairCount(busiOnlineMonitorData.getRepairCount());
            homeActualInfoVo.setDTime(busiOnlineMonitorData.getCreatedTime());
        }
        homeActualVo.setHomeActualInfoVo(homeActualInfoVo);
        GisSf6Env gisSf6Env = gisSf6EnvDao.get(new WherePrams()
                .where("sensor_id", param.getSensorCode())
                .orderBy("time_stamp desc  limit 1"));

        List<HomeActualDataVo> homeActualDataVos=new ArrayList<>();
        if(ObjectUtils.isEmpty(gisSf6Env)){

            return homeActualVo;
        }
        HomeActualDataVo homeActualDataVo=new HomeActualDataVo();
        HomeActualDataVo homeActualDataVo1=new HomeActualDataVo();
        HomeActualDataVo homeActualDataVo2=new HomeActualDataVo();
        HomeActualDataVo homeActualDataVo3=new HomeActualDataVo();
        homeActualDataVo.setName("SF6浓度");
        homeActualDataVo1.setName("O2含量");
        homeActualDataVo2.setName("温度");
        homeActualDataVo3.setName("湿度");
        homeActualDataVo.setDTime(gisSf6Env.getTimeStamp());
        homeActualDataVo1.setDTime(gisSf6Env.getTimeStamp());
        homeActualDataVo2.setDTime(gisSf6Env.getTimeStamp());
        homeActualDataVo3.setDTime(gisSf6Env.getTimeStamp());
        homeActualDataVo.setValue(gisSf6Env.getConc());
        homeActualDataVo1.setValue(gisSf6Env.getOContent());
        homeActualDataVo2.setValue(gisSf6Env.getTmp());
        homeActualDataVo3.setValue(gisSf6Env.getDew());
        GisSf6EnvThreshold gisSf6EnvThreshold = sf6EnvThresholdDao.get(new WherePrams()
                .where("sensor_code", param.getSensorCode())
                .and("work_status", gisSf6Env.getRunState()));
        if(!ObjectUtils.isEmpty(gisSf6EnvThreshold)){
            homeActualDataVo.setThresholdValue(gisSf6EnvThreshold.getConc());
            homeActualDataVo1.setThresholdValue(gisSf6EnvThreshold.getOContent());
            homeActualDataVo2.setThresholdValue(gisSf6EnvThreshold.getTmp());
            homeActualDataVo3.setThresholdValue(gisSf6EnvThreshold.getDew());
        }
        homeActualDataVos.add(homeActualDataVo);
        homeActualDataVos.add(homeActualDataVo1);
        homeActualDataVos.add(homeActualDataVo2);
        homeActualDataVos.add(homeActualDataVo3);
        homeActualVo.setHomeActualDataVos(homeActualDataVos);
        return homeActualVo;
    }
}