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

import cn.hutool.core.collection.CollectionUtil;
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.google.common.collect.Maps;
import com.huatek.busi.common.BusiConstant;
import com.huatek.busi.common.CurveType;
import com.huatek.busi.common.DateUtils;
import com.huatek.busi.common.SiteConstants;
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.BusiSensorQueryParamDto;
import com.huatek.busi.dto.EquipmentInfoDto;
import com.huatek.busi.dto.HomeSearchDto;
import com.huatek.busi.dto.cable.BusiCableCirculationDto;
import com.huatek.busi.dto.cable.BusiCableCirculationFailureStatisticsDto;
import com.huatek.busi.dto.cable.BusiCableCirculationStatisticsDto;
import com.huatek.busi.dto.curve.BaseCurveQueryDto;
import com.huatek.busi.dto.curve.PointItemDto;
import com.huatek.busi.entity.*;
import com.huatek.busi.mapper.cable.BusiCableCirculationMapper;
import com.huatek.busi.mapper.cable.CableCirculationStatisticsMapper;
import com.huatek.busi.service.IBusiCableSensorService;
import com.huatek.busi.service.IBusiCableSubTreeService;
import com.huatek.busi.service.IecBydworkParamService;
import com.huatek.busi.service.cable.BusiCableCirculationCacheService;
import com.huatek.busi.service.cable.BusiCableCirculationService;
import com.huatek.busi.service.cable.BusiOtherThresholdService;
import com.huatek.busi.service.impl.cac.AbstractCacEtlService;
import com.huatek.busi.vo.*;
import com.huatek.busi.vo.cable.*;
import com.huatek.busi.vo.curve.PointItemVo;
import com.huatek.busi.vo.echarts.EchartLineDataVo;
import com.huatek.busi.vo.echarts.SeriesItemVo;
import com.huatek.busi.vo.warning.BusiIcgeVo;
import com.huatek.frame.base.util.BeanUtils;
import com.huatek.torch.frame.tools.ConstantUtil;
import com.huatek.torch.frame.tools.ResultUtil;
import com.huatek.torch.sql.beans.WherePrams;
import com.huatek.torch.util.uuid.Uuid;
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.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 电缆环流接口实现
 *
 * @author Bobi_huo
 * @date 2020-09-10 14:50
 */
@Slf4j
@Component
@Service(interfaceClass = BusiCableCirculationService.class)
@Transactional(rollbackFor = Exception.class)
public class BusiCableCirculationServiceImpl<psvm> extends AbstractCacEtlService<BusiCableCirculation>
        implements BusiCableCirculationService {

    @Autowired
    private BusiCableCirculationMapper circulationMapper;

    @Autowired
    private BusiCableCirculationDao circulationDao;

    @Autowired
    private BusiSiteTreeDao busiSiteTreeDao;

    @Autowired
    private IecBydworkParamService iecBydworkParamService;

    @Autowired
    private BusiOtherThresholdService busiOtherThresholdService;

    @Autowired
    CableCirculationStatisticsMapper cableCirculationStatisticsMapper;

    @Autowired
    private BusiCableCirculationCacheService busiCableCirculationCacheService;

    private static final String UNDEFINED = "undefined";

    @Override
    public void saveHistoryData(BusiCableCirculation cacEntity, EquipmentInfoDto equipmentInfo) {
        // 电缆环流
        // 设备状态
        String state = iecBydworkParamService.geCabletIecType(cacEntity.getSubTreeId(), cacEntity.getTimeStamp());
        if (StringUtils.isEmpty(state)) {
            logger.warn("IecType is empty! eqmCode: {}, timeStamp: {}", cacEntity.getEquipmentCode(),
                    cacEntity.getTimeStamp());
        }
        cacEntity.setRunState(state);
        // 设置rowkey，导入hbase使用
        cacEntity.setHbaseRowkey(Tools.strReverse(TimeUtil.getTimeStr(cacEntity.getTimeStamp())) + "_"
                + cacEntity.getSensorId() + "_" + TimeUtil.getTimeStr(cacEntity.getTimeStamp()) + "_"
                + cacEntity.getCacMonitorTypeCode() + "_" + cacEntity.getMainTreeId());

        super.saveHistoryData(cacEntity, equipmentInfo);
    }



    @Override
    public void saveBusiWarning(BusiCableCirculation cacEntity, String cacMonitorTypeCode, String sensorId,
                                EquipmentInfoDto equipmentInfo) {
        // 阈值
        BusiOtherThreshold otherThreshold = busiOtherThresholdService.getOtherThreshold(cacEntity.getMainTreeId(), cacEntity.getRunState(), cacEntity.getSensorId());
        if (otherThreshold == null) {
            logger.warn("otherThreshold not exists! mainTreeId: {}, runState: {}, sensorCode: {}",
                    cacEntity.getMainTreeId(), cacEntity.getRunState(), cacEntity.getSensorId());
            return;
        }
        Map<String, Object> stabilityMap =
                busiStabilityService.getStabilityBySensorCodeAndStatus(sensorId, cacEntity.getRunState());
        // 电缆环流告警
        String txWarning = isDLHLWarning(cacEntity, otherThreshold);
        if ("1".equals(txWarning)) {
            // 保存告警
            BusiEqmWarning busiEqmWarning =
                    newEw(BusiConstant.EqType.EQ_TYPE5, BusiConstant.GzType.GZ_TYPE17, formateDlhlWarningMsg(cacEntity), cacMonitorTypeCode, "1");
            busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning.setRunState(cacEntity.getRunState());
            busiEqmWarning = this.buildCableWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiIcgeVo busiIcgeVo = new BusiIcgeVo();
            busiIcgeVo.setCollectValue(cacEntity.getTotalCoreCurrent());
            busiIcgeVo.setAlarmValue(cacEntity.getTotalCoreCurrent());
            busiIcgeVo.setPhase(cacEntity.getPhase());
            busiIcgeVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            // 稳定性指标
            busiIcgeVo.setStabilityIndex(getString(stabilityMap, "totalCurrent", "--"));
            busiIcgeVo.setThresholdValue(otherThreshold.getElectThresholdVal());
            busiIcgeVo.setWarningValue(otherThreshold.getElectPrewarningVal());
            busiIcgeVo.setEquipmentStatus(cacEntity.getRunState());
            busiIcgeVo.setCollectDate(cacEntity.getTimeStamp());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiIcgeVo));
        } else if ("2".equals(txWarning)) {
            // 保存告警
            BusiEqmWarning busiEqmWarning =
                    newEw(BusiConstant.EqType.EQ_TYPE5, BusiConstant.GzType.GZ_TYPE17, formateDlhlWarningMsg(cacEntity), cacMonitorTypeCode, "2");
            busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
            busiEqmWarning.setWarningFlag("2");
            busiEqmWarning.setRunState(cacEntity.getRunState());
            busiEqmWarning = this.buildCableWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiIcgeVo busiIcgeVo = new BusiIcgeVo();
            busiIcgeVo.setCollectValue(cacEntity.getTotalCoreCurrent());
            busiIcgeVo.setAlarmValue(cacEntity.getTotalCoreCurrent());
            busiIcgeVo.setPhase(cacEntity.getPhase());
            busiIcgeVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            // 稳定性指标
            busiIcgeVo.setStabilityIndex(getString(stabilityMap, "totalCurrent", "--"));
            busiIcgeVo.setThresholdValue(otherThreshold.getElectThresholdVal());
            busiIcgeVo.setWarningValue(otherThreshold.getElectPrewarningVal());
            busiIcgeVo.setEquipmentStatus(cacEntity.getRunState());
            busiIcgeVo.setCollectDate(cacEntity.getTimeStamp());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiIcgeVo));
        }
    }

    private String isDLHLWarning(BusiCableCirculation cacEntity, BusiOtherThreshold otherThreshold) {
        String flag = "0";
        if(otherThreshold.getElectThresholdVal() != null && !"".equals(otherThreshold.getElectThresholdVal()))
        {
            if (DecimalUtil.getVal(cacEntity.getTotalCoreCurrent()).compareTo(DecimalUtil.getVal(otherThreshold.getElectThresholdVal())) > 0) {
                if (DecimalUtil.getVal(cacEntity.getTotalCoreCurrent()).compareTo(DecimalUtil.getVal(otherThreshold.getElectPrewarningVal())) < 0) {
                    flag = "2";
                }
                if (DecimalUtil.getVal(cacEntity.getTotalCoreCurrent()).compareTo(DecimalUtil.getVal(otherThreshold.getElectPrewarningVal())) > 0) {
                    flag = "1";
                }
            }
        }
        return flag;
    }

    private String formateDlhlWarningMsg(BusiCableCirculation cacEntity) {
        return format("电缆环流电流:{}(A)超标", cacEntity.getTotalCoreCurrent());
    }

    private EchartLineDataVo getTrendData(BusiCableCirculationStatisticsDto dto) {

        if (dto.getStartTime() == null || dto.getEndTime() == null) {
            dto.check();
        }
        CurveType curveType = CurveType.newInstance("电缆环流(A)", 1);
        String subTitle = "电缆环流(A)";

        EchartLineDataVo result = new EchartLineDataVo(subTitle + "趋势曲线");



        int availableCount = 0;
        // 设置X轴坐标值：升序且不重复；保存每条曲线每个X坐标对应的值在allPointMap里，X轴坐标值相同的点会覆盖
        Map<String, Map<String, Object>> allPointMap = Maps.newLinkedHashMap();



//        List<BusiCableCirculationVo> historyDatas = circulationMapper.getHistoryData(dto);

        List<BusiCableCirculationIncreaseRateCacheVo> historyDatas = cableCirculationStatisticsMapper.getHistoryData(dto);

        availableCount += historyDatas.size();
        String lineName = subTitle;
        Map<String, Object> valMap = Maps.newHashMapWithExpectedSize(historyDatas.size());
        for (BusiCableCirculationIncreaseRateCacheVo historyData : historyDatas) {
//            valMap.put(DateUtil.formatLcoalDateTime(historyData.getDTime()), historyData.getTotalCoreCurrent());
            valMap.put(historyData.getDTime().toString(), historyData.getTotalCoreCurrent());
        }
        allPointMap.put(lineName, valMap);
        //设置开始日期和结束日期之间的X轴值
        long days = ChronoUnit.DAYS.between(dto.getStartTime(), dto.getEndTime());
        if (days >= 0) {
            Stream.iterate(dto.getStartTime(), d -> d.plusDays(1)).limit(days + 1)
                    .forEach(day -> result.getXAxisData().add(day.toString()));
        }
        // 根据X轴进行构造曲线
        setYAxisData(result, curveType, allPointMap, subTitle);
        result.setAvailableCount(availableCount);
        return result;
    }

    static void setYAxisData(EchartLineDataVo result, CurveType curveType,
                             Map<String, Map<String, Object>> allPointMap, String subTitle) {
            String line = subTitle;
            Map<String, Object> linePointMap = allPointMap.get(line);
            List<Object> dataList =
                    result.getXAxisData().stream().map(xAxis -> getVal(linePointMap, xAxis)).collect(Collectors.toList());
            result.getSeries().add(new SeriesItemVo(line, dataList));
    }

    static Object getVal(Map<String, Object> map, String key) {
        if (map == null || map.isEmpty()) {
            return UNDEFINED;
        }
        Object val = map.get(key);
        return val == null ? UNDEFINED : val;
    }

    @Override
    public void updateCurrentData(BusiCableCirculation cacEntity, EquipmentInfoDto equipmentInfo) {
        busiCableCirculationCacheService.saveCableCirculationCache(cacEntity, equipmentInfo);
    }

    @Override
    public Map<String, Object> page(BusiCableCirculationDto dto) {
        PageInfo<BusiCableCirculationVo> pageInfo = PageHelper.startPage(dto.getPage(), dto.getLimit())
                .doSelectPageInfo(() -> circulationMapper.selectBusiCableCircuPage(dto));
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, pageInfo.getTotal(), "查询成功", pageInfo.getList());
    }

    @Override
    public Map<String, Object> addCable(BusiCableCirculationDto dto) {
        BusiCableCirculation cableCirculation = new BusiCableCirculation();
        BeanUtils.copyPropertiesWithIgnoreNull(dto, cableCirculation);
        cableCirculation.setId(Uuid.getUUID());
        cableCirculation.setStatus(SiteConstants.Status.NORMAL.getValue());
        cableCirculation.setTimeStamp(LocalDateTime.now());
        int count = circulationDao.add(cableCirculation);
        if (count > 0) {
            log.debug("addCable: {}", count);
            return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "新增成功", "");
        }
        return ResultUtil.put(ConstantUtil.REQUEST_FAIL, "新增失败", "");
    }

    @Override
    public Map<String, Object> findCableById(String id) {
        BusiCableCirculation circulation = circulationDao.get(id);
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "操作成功", circulation);
    }

    @Override
    public Map<String, Object> updateCable(BusiCableCirculationDto dto) {
        BusiCableCirculation cableCirculation = new BusiCableCirculation();
        BeanUtils.copyPropertiesWithIgnoreNull(dto, cableCirculation);
        // circulationDao.updateLocal(cableCirculation) 221214修改为下面一行，待验证
        int count = circulationDao.update(cableCirculation);
        if (count > 0) {
            log.debug("updateCable: {}", count);
            return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "修改成功", "");
        }
        return ResultUtil.put(ConstantUtil.REQUEST_FAIL, "修改失败", "");
    }

    @Override
    public Map<String, Object> deleteCable(List<String> ids) {
        //删除
        if (circulationMapper.deleteBusiCable(ids) > 0) {
            return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "删除成功", "");
        }
        return ResultUtil.put(ConstantUtil.REQUEST_FAIL, "删除失败", "");
    }

    @Override
    public Map<String, Object> getRealData(String equipmentId) {
        Map<String, Object> data = new HashMap<>();
        CableCirculationDataVo cableCirculationDataVos = new CableCirculationDataVo();
        // 查询实时数据
        List<BusiCableCirculationVo> realData = circulationMapper.getRealData(equipmentId);
        if (CollectionUtil.isNotEmpty(realData)) {
            // 获取基本信息
            cableCirculationDataVos = busiOtherThresholdService.getCableData(realData.get(0).getSensorId(),equipmentId);
        }
        data.put("realData", realData);
        data.put("cableData", cableCirculationDataVos);
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "查询成功", data);
    }

    @Override
    public Map<String, Object> getRealDataForCable(String equipmentId) {
        Map<String, Object> data = new HashMap<>();
        CableCirculationDataVo cableCirculationDataVos = new CableCirculationDataVo();
        // 查询实时数据
        List<BusiCableCirculationVo> realData = circulationMapper.getRealDataForCable(equipmentId);
        if (CollectionUtil.isNotEmpty(realData)) {
            // 获取基本信息
            cableCirculationDataVos = busiOtherThresholdService.getCableDataForCable(realData.get(0).getSensorId(),equipmentId);
        }
        data.put("realData", realData);
        data.put("cableData", cableCirculationDataVos);
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "查询成功", data);
    }

    @Override
    public Map<String, Object> getHistoryTrendChart(BusiCableCirculationStatisticsDto dto) {
        EchartLineDataVo echartLineDataVo = getTrendData(dto);
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, "查询成功", echartLineDataVo);
    }

    @Override
    public BusiCableCirculationStatisticsVo getListEquInfo(String cacMonitorTypeCode, LocalDate day, String sensorCode) {
        BusiCableCirculationFailureStatisticsDto param = new BusiCableCirculationFailureStatisticsDto();
        param.setStartTime(day.atStartOfDay());
        param.setEndTime(day.plusDays(1).atStartOfDay());
        param.setCacMonitorTypeCode(cacMonitorTypeCode);
        param.setSensorCode(sensorCode);
        List<BusiCableCirculationStatisticsVo> list = circulationMapper.getListEquInfo(param);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

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

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

    @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>> pageInfo = circulationMapper.findCACPageData(params);
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, pageInfo.getTotal(), "请求成功", pageInfo.getResult());
    }

    @Override
    public Map<String, Object> exportCacMonitorData(Map<String, Object> mapParams) {
        Map<String, Object> returnMap = new HashMap<>();
        if (mapParams.containsKey("mainTreeId") && StringUtils.isNotEmpty(String.valueOf(mapParams.get("mainTreeId")))) {
            BusiSiteTree busiSiteTree = busiSiteTreeDao.get(String.valueOf(mapParams.get("mainTreeId")));
            List<BusiCableCirculationReportVo> circulationVos = circulationMapper.exportCacMonitorData(mapParams);
            for(int i = 0;i < circulationVos.size(); i++ ){
                if(circulationVos.get(i).getRunState().equals("1")){
                    circulationVos.get(i).setRunState("发电");
                }else if(circulationVos.get(i).getRunState().equals("2")){
                    circulationVos.get(i).setRunState("抽水");
                }else if(circulationVos.get(i).getRunState().equals("3")){
                    circulationVos.get(i).setRunState("空闲");
                }else{
                    circulationVos.get(i).setRunState("空载");
                }
            }
            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 (circulationVos.isEmpty()) {
                circulationVos = new ArrayList<>();
                circulationVos.add(new BusiCableCirculationReportVo());
            } else {
//                circulationVos.stream().forEach(transformerIcge -> {
//                    transformerIcge.setType(SiteConstants.IcgeType.getName(transformerIcge.getType()));
//                });
            }
            returnMap.put("data", circulationVos);
        } else {
            throw new RuntimeException("主设备编码不正确");
        }
        return returnMap;
    }


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

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

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


//    public static void main(String[] args)
//    {
//        String a=null;
//        System.out.println(a.trim());
//    }

}
