package com.hw.ems.record.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


import com.alibaba.fastjson2.JSONObject;
import com.hw.common.core.constant.SecurityConstants;
import com.hw.common.core.constant.TdEngineConstants;
import com.hw.common.core.domain.R;
import com.hw.common.core.text.Convert;
import com.hw.common.core.utils.DateUtils;
import com.hw.common.core.utils.StringUtils;
import com.hw.ems.base.domain.BaseEnergyType;
import com.hw.ems.base.domain.BaseMonitorInfo;
import com.hw.ems.base.service.IBaseEnergyTypeService;
import com.hw.ems.base.service.IBaseMonitorInfoService;
import com.hw.ems.record.domain.RecordDnbInstant;
import com.hw.ems.record.domain.vo.RecordDnbInstantDataVo;
import com.hw.ems.record.mapper.RecordDnbInstantMapper;
import com.hw.ems.record.service.IRecordDnbInstantService;
import com.hw.ems.report.domain.ReportPointDnb;
import com.hw.ems.report.service.IReportPointDnbService;
import com.hw.tdengine.api.RemoteTdEngineService;
import com.hw.tdengine.api.domain.*;
import com.hw.tdengine.api.domain.ems.TdSuperTableEmsSelectVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 电实时数据Service业务层处理
 *
 * @author YinQ
 * @date 2023-04-07
 */
@Service
public class RecordDnbInstantServiceImpl implements IRecordDnbInstantService {
    @Autowired
    private RecordDnbInstantMapper recordDnbInstantMapper;

    @Autowired
    private IBaseMonitorInfoService baseMonitorInfoService;

    @Autowired
    private RemoteTdEngineService remoteTdEngineService;

    @Autowired
    private IBaseEnergyTypeService baseEnergyTypeService;
    @Autowired
    private IReportPointDnbService reportPointDnbService;


    /**
     * 查询电实时数据
     *
     * @param objid 电实时数据主键
     * @return 电实时数据
     */
    @Override
    //@DS("#header.poolName")
    public RecordDnbInstant selectRecordDnbInstantByObjid(Long objid) {
//        return recordDnbInstantMapper.selectRecordDnbInstantByObjid(objid);
        return new RecordDnbInstant();
    }

    /**
     * 查询电实时数据列表
     *
     * @param recordDnbInstant 电实时数据
     * @return 电实时数据
     */
//    @Override
//    @DS("#header.poolName")
////    @DataScope(deptAlias = "null")
//    public List<RecordDnbInstant> selectRecordDnbInstantList(RecordDnbInstant recordDnbInstant) {
//        return recordDnbInstantMapper.selectRecordDnbInstantList(recordDnbInstant);
//    }
    @Override
    //@DS("#header.poolName")
//    @DataScope(deptAlias = "null")
    public RecordDnbInstantDataVo selectRecordDnbInstantList(RecordDnbInstant recordDnbInstant) {
        RecordDnbInstantDataVo recordDnbInstantDataVo = new RecordDnbInstantDataVo();
        try {

            Integer pageNum = Integer.valueOf((String) recordDnbInstant.getParams().get("pageNum"));
            Integer pageSize = Integer.valueOf((String) recordDnbInstant.getParams().get("pageSize"));
            Integer offset = (pageNum - 1) * pageSize;
            List<RecordDnbInstant> records = new ArrayList<RecordDnbInstant>();
            BaseMonitorInfo queryMonitorInfo = new BaseMonitorInfo();
            queryMonitorInfo.setMonitorId(recordDnbInstant.getMonitorId());
//            List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoService.selectBaseMonitorInfoList(queryMonitorInfo);
            String stratTime = (String) recordDnbInstant.getParams().get("beginTime");
            String endTime = (String) recordDnbInstant.getParams().get("endTime");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //todo 因为手动补录采集时间默认为空，且手动补录页面初始化需要展示出所有的历史数据
            if (stratTime==null){
                //开始事件设置的足够远，确保可以查询到所有数据
                stratTime ="2023-01-01 00:00:00";
            }
            if (endTime==null){
                //结束事件设置为当前时间
                endTime = sdf.format(new Date(System.currentTimeMillis()));
            }
            Date dateStrat = sdf.parse(stratTime);
            Date dateEnd = sdf.parse(endTime);

            TdSuperTableEmsSelectVo tdSuperTableCommonSelectVo = new TdSuperTableEmsSelectVo();
            tdSuperTableCommonSelectVo.setDatabaseName("db_hwmes");
            tdSuperTableCommonSelectVo.setSuperTableName("st_electricity");
            tdSuperTableCommonSelectVo.setStartTime(dateStrat.getTime());
            tdSuperTableCommonSelectVo.setEndTime(dateEnd.getTime());
            tdSuperTableCommonSelectVo.setFirstFieldName("ts");
            tdSuperTableCommonSelectVo.setOrderByFieldName("ts");
            tdSuperTableCommonSelectVo.setSort("desc");
            tdSuperTableCommonSelectVo.setOffset(offset);
            tdSuperTableCommonSelectVo.setLimit(pageSize);

            Object monitorObjidValue = recordDnbInstant.getParams().get("monitorObjid");
            if (monitorObjidValue != null) {
                tdSuperTableCommonSelectVo.setMonitorObjid(Long.valueOf(String.valueOf(monitorObjidValue)));
            }

            TdReturnDataVo tdReturnDataVo = remoteTdEngineService.getSuperTableHistoryData(tdSuperTableCommonSelectVo, SecurityConstants.INNER).getData();
            if (tdReturnDataVo == null) {
                return recordDnbInstantDataVo;
            }
            List<Map<String, Object>> dataList = tdReturnDataVo.getDataList();

            for (Map<String, Object> data : dataList) {
                RecordDnbInstant recordDnbInstant1 = new RecordDnbInstant();
                recordDnbInstant1.setObjid(Long.valueOf(String.valueOf(data.get(TdEngineConstants.ST_TAG_EMS_MONITOROBJID))));
                recordDnbInstant1.setMonitorId(String.valueOf(data.get(TdEngineConstants.ST_TAG_EMS_MONITORID)));
                recordDnbInstant1.setMonitorName(String.valueOf(data.get(TdEngineConstants.ST_TAG_EMS_MONITORNAME)));
                if (data.get("volatagea")!=null ){
                    recordDnbInstant1.setVA(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("volatagea")))));
                }
                if (data.get("volatageb")!=null ){
                    recordDnbInstant1.setVB(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("volatageb")))));
                }
                if (data.get("volatagec")!=null ){
                    recordDnbInstant1.setVC(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("volatagec")))));
                }
                if (data.get("currenta")!=null ){
                    recordDnbInstant1.setIA(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("currenta")))));
                }
                if (data.get("currentb")!=null ){
                    recordDnbInstant1.setIB(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("currentb")))));
                }
                if (data.get("currentc")!=null ){
                    recordDnbInstant1.setIC(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("currentc")))));
                }
                if (data.get("glys")!=null ){
                    recordDnbInstant1.setGlys(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("glys")))));
                }
                if (data.get("zxyg")!=null ){
                    recordDnbInstant1.setZxyg(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("zxyg")))));
                }
                if (data.get("activepower")!=null ){
                    recordDnbInstant1.setActivePower(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("activepower")))));
                }
                if (data.get("reactivepower")!=null ){
                    recordDnbInstant1.setReactivePower(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("reactivepower")))));
                }

                //调整时间格式
                String substring = String.valueOf(data.get("ts")).replaceAll("T", " ").substring(0, 19);
                recordDnbInstant1.setCollectTime(sdf.parse(substring));
//                recordDnbInstant.setConsumption(BigDecimal.valueOf(Double.valueOf(String.valueOf(data.get("consumption")))));
                if (data.get("reactivepower")!=null ){
                    recordDnbInstant1.setCollectType(Long.valueOf(String.valueOf(data.get("collecttype"))));
                }
                records.add(recordDnbInstant1);
            }
            recordDnbInstantDataVo.setCount(tdReturnDataVo.getCount());
            recordDnbInstantDataVo.setRecordDnbInstants(records);
            return recordDnbInstantDataVo;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return recordDnbInstantDataVo;
    }

    /**
     * 新增电实时数据
     *
     * @param recordDnbInstant 电实时数据
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int insertRecordDnbInstant(RecordDnbInstant recordDnbInstant) {
        /*if (StringUtils.isNotEmpty(recordDnbInstant.getMonitorId())){
            RecordDnbInstant dnbInstant = new RecordDnbInstant();
            dnbInstant.setMonitorId(recordDnbInstant.getMonitorId());
            List<RecordDnbInstant> recordDnbInstants = recordDnbInstantMapper.instantList(dnbInstant);
            if (recordDnbInstants.size() > 0){
                for (RecordDnbInstant instant : recordDnbInstants) {
                    if (instant.getZxyg().compareTo(recordDnbInstant.getZxyg()) > 0){
                        return 0;
                    }
                }
            }
        }*/
        BaseMonitorInfo baseMonitorInfo = new BaseMonitorInfo();
        baseMonitorInfo.setMonitorId(recordDnbInstant.getMonitorId());
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoService.selectBaseMonitorInfoList(baseMonitorInfo);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date collectTime = recordDnbInstant.getCollectTime();
        TdTableVo tdTableVo = new TdTableVo();
        tdTableVo.setDatabaseName("db_hwmes");
        tdTableVo.setSuperTableName("st_electricity");
        tdTableVo.setTableName("t_e_"+baseMonitorInfos.get(0).getObjid());
        List<TdField> fields = new ArrayList<TdField>();
        List<TdField> field2s = new ArrayList<TdField>();
        TdField field = new TdField();
        TdField field2 = new TdField();
        TdField field3 = new TdField();
        TdField field4 = new TdField();
        field.setFieldName(TdEngineConstants.ST_TAG_EMS_BUILDID);
        field.setFieldValue(baseMonitorInfos.get(0).getBuildId());
        field2.setFieldName(TdEngineConstants.ST_TAG_EMS_MONITORNAME);
        field2.setFieldValue(baseMonitorInfos.get(0).getMonitorName());
        field3.setFieldName(TdEngineConstants.ST_TAG_EMS_MONITOROBJID);
        field3.setFieldValue(baseMonitorInfos.get(0).getObjid());
        field4.setFieldName(TdEngineConstants.ST_TAG_EMS_MONITORID);
        field4.setFieldValue(baseMonitorInfos.get(0).getMonitorId());
        fields.add(field);
        fields.add(field2);
        fields.add(field3);
        fields.add(field4);
        tdTableVo.setTagsFieldValues(fields);
        TdField field5 = new TdField();
        TdField field6 = new TdField();
        field5.setFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME);

        field5.setFieldValue(sdf.format(collectTime));
        field6.setFieldName("zxyg");
        field6.setFieldValue(recordDnbInstant.getZxyg());
        field2s.add(field5);
        field2s.add(field6);
        tdTableVo.setSchemaFields(field2s);
        R<?> r = remoteTdEngineService.insertTable(tdTableVo, SecurityConstants.INNER);
//        recordDnbInstant.setRecordTime(new Date());
//        recordDnbInstant.setCollectType(0L);
//        return recordDnbInstantMapper.insertRecordDnbInstant(recordDnbInstant);
        return 1;
    }

    /**
     * 修改电实时数据
     *
     * @param recordDnbInstant 电实时数据
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int updateRecordDnbInstant(RecordDnbInstant recordDnbInstant) {
        recordDnbInstant.setRecordTime(new Date());
        return recordDnbInstantMapper.updateRecordDnbInstant(recordDnbInstant);
    }

    /**
     * 批量删除电实时数据
     *
     * @param objids 需要删除的电实时数据主键
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int deleteRecordDnbInstantByObjids(String objids) {
        return recordDnbInstantMapper.deleteRecordDnbInstantByObjids(Convert.toStrArray(objids));
    }

    /**
     * 删除电实时数据信息
     *
     * @param objid 电实时数据主键
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int deleteRecordDnbInstantByObjid(Long objid) {
        return recordDnbInstantMapper.deleteRecordDnbInstantByObjid(objid);
    }

    /**
     * 实时数据
     *
     * @param recordDnbInstant
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public List<RecordDnbInstant> instantList(RecordDnbInstant recordDnbInstant) {
        //是空 直接添加
        if (StringUtils.isEmpty(recordDnbInstant.getMonitorSubset())) {
            return recordDnbInstantMapper.instantList(new RecordDnbInstant());
        }
        List<RecordDnbInstant> dnbInstantList = new ArrayList<>();
        BaseMonitorInfo monitorInfo = new BaseMonitorInfo();
        //查询子集加入到父id中
        monitorInfo.setParentId(Long.valueOf(recordDnbInstant.getMonitorSubset()));
        monitorInfo.setParams(null);
        recordDnbInstant.setParams(null);
        //查询id为getMonitorSubset的子集
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoService.selectBaseMonitorInfoList(monitorInfo);
        for (BaseMonitorInfo baseMonitorInfo : baseMonitorInfos) {
            RecordDnbInstant dnbInstant = new RecordDnbInstant();
            dnbInstant.setMonitorId(baseMonitorInfo.getMonitorId());
            dnbInstant.setMonitorName(baseMonitorInfo.getMonitorName());
            RecordDnbInstant baseDnbInstant = new RecordDnbInstant();
            baseDnbInstant.setMonitorSubset(baseMonitorInfo.getMonitorId());
            List<RecordDnbInstant> dnbInstantListOld = recordDnbInstantMapper.instantList(baseDnbInstant);
            if (dnbInstantListOld.size() > 0) {
                BigDecimal zxyg = dnbInstantListOld.stream().map(RecordDnbInstant::getZxyg).reduce(BigDecimal.ZERO, BigDecimal::add);
                Date collectTime = dnbInstantListOld.stream().map(RecordDnbInstant::getCollectTime).max(Date::compareTo).orElse(null);
                dnbInstant.setZxyg(zxyg);
                dnbInstant.setCollectTime(collectTime);
            }
            dnbInstantList.add(dnbInstant);
        }
        return dnbInstantList;
    }

    /**
     * 获取最新实时电数据
     * 需要先排序在查询出每个设备的最新数据
     *
     * @param baseDnbInstant
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public List<RecordDnbInstant> selectRealTimeParentList(RecordDnbInstant baseDnbInstant) {
        List<RecordDnbInstant> dnbInstantList = new ArrayList<>();
        if (StringUtils.isEmpty(baseDnbInstant.getMonitorSubset())) {
            return recordDnbInstantMapper.instantList(new RecordDnbInstant());
        }
        RecordDnbInstant dnbInstant = new RecordDnbInstant();
        BaseMonitorInfo monitorInfo = new BaseMonitorInfo();
        monitorInfo.setMonitorId(baseDnbInstant.getMonitorSubset());
        baseDnbInstant.setParams(null);
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoService.selectBaseMonitorInfoList(monitorInfo);
        if (baseMonitorInfos.size() > 0) {

            List<RecordDnbInstant> dnbInstantListOld = recordDnbInstantMapper.instantList(baseDnbInstant);
            dnbInstant.setMonitorId(baseMonitorInfos.get(0).getMonitorId());
            dnbInstant.setMonitorName(baseMonitorInfos.get(0).getMonitorName());
            if (dnbInstantListOld.size() > 0) {
                BigDecimal zxyg = dnbInstantListOld.stream().map(RecordDnbInstant::getZxyg).reduce(BigDecimal.ZERO, BigDecimal::add);
                Date collectTime = dnbInstantListOld.stream().map(RecordDnbInstant::getCollectTime).max(Date::compareTo).orElse(null);
                dnbInstant.setZxyg(zxyg);
                dnbInstant.setCollectTime(collectTime);
            }
        }
//        HashMap<String, List<BaseMonitorInfo>> childrenMonitorInfoMap = baseMonitorInfoService.buildMonitorMap(baseMonitorInfos);
//        List<BaseMonitorInfo> baseMonitorList = childrenMonitorInfoMap.get(baseDnbInstant.getMonitorSubset());
//        List<String> monitorList  = baseMonitorList.stream().map(BaseMonitorInfo::getMonitorId).collect(Collectors.toList());
//        HashMap<String, Object> paramMap = new HashMap<>();
//        paramMap.put("monitorList", monitorList);
//        baseDnbInstant.setParams(paramMap);
//
//        List<BaseMonitorInfo> collect = baseMonitorInfos.stream().filter(e -> e.getMonitorId().equals(baseDnbInstant.getMonitorSubset())).collect(Collectors.toList());
//
        dnbInstantList.add(dnbInstant);
        return dnbInstantList;
    }


    /**
     * 表具实时状态
     *
     * @param dnbInstant
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public RecordDnbInstant tablewareDetailsInfo(RecordDnbInstant dnbInstant) {
        if (StringUtils.isEmpty(dnbInstant.getMonitorId())) {
            return null;
        }
        List<RecordDnbInstant> recordDnbInstants = recordDnbInstantMapper.instantList(dnbInstant);
        if (recordDnbInstants.size() == 0) {
            return null;
        }
        return recordDnbInstants.get(0);
    }

    @Override
    //@DS("#header.poolName")
    public List<RecordDnbInstant> voltageCurrentCurve(RecordDnbInstant dnbInstant) {
        if (StringUtils.isEmpty(dnbInstant.getMonitorId())) {
            return null;
        }
        if (StringUtils.isEmpty(dnbInstant.getStartTime()) || StringUtils.isEmpty(dnbInstant.getEndTime())) {
            String nowTime = DateUtils.getTime();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime modifiedDateTime = LocalDateTime.parse(nowTime, formatter).minusMinutes(30);
            String thirtyTime = modifiedDateTime.format(formatter);
            dnbInstant.setStartTime(thirtyTime);
            dnbInstant.setEndTime(nowTime);
        }
        return recordDnbInstantMapper.selectRecordDnbInstantList(dnbInstant);
    }

    /**
     * 定时任务用：通过定时任务获取电实时数据
     */
    //todo 通过tde 将电实时数据存入到电整点数据中
    @Override
    public void getDnbInstantByJob() {
        TdHistorySelectDto tdHistorySelectDto = new TdHistorySelectDto();
        tdHistorySelectDto.setFirstFieldName("ts");
        tdHistorySelectDto.setDatabaseName(TdEngineConstants.EMS_DATABASE_NAME);
        List<BaseEnergyType> baseEnergyTypes = baseEnergyTypeService.selectBaseEnergyTypeList(new BaseEnergyType());

        //获取当前时间与一小时前时间
        long endTime = System.currentTimeMillis();
        //从一小时前开始，十点的话就是从九点开始，不是九点零一，开始就
        long startTime = System.currentTimeMillis() - 60 * 60 * 1000 - 10;
        tdHistorySelectDto.setStartTime(startTime);
        tdHistorySelectDto.setEndTime(endTime);
        Date date = new Date();
        int hours = date.getHours();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //获取所有的计量设备
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoService.selectBaseMonitorInfoList(new BaseMonitorInfo());
        List<ReportPointDnb> reportPoints = new ArrayList<ReportPointDnb>();
        //根据计量设备id获取能源表名称
        if (!baseMonitorInfos.isEmpty()) {
            for (BaseMonitorInfo baseMonitorInfo : baseMonitorInfos) {
                try {
                    String emsTableName = TdEngineConstants.getEmsTableName(baseMonitorInfo.getObjid());
                    //获取当前数据以及一小时前的数据
                    tdHistorySelectDto.setTableName(emsTableName);
//            tdHistorySelectDto.setTableName("t_e_ceshi7");
                    List<Map<String, Object>> dnbInstant = remoteTdEngineService.getHistoryData(tdHistorySelectDto, SecurityConstants.INNER).getData().getDataList();
                    R<TdReturnDataVo> historyData = remoteTdEngineService.getHistoryData(tdHistorySelectDto, SecurityConstants.INNER);
                    ReportPointDnb report = new ReportPointDnb();
                    report.setMonitorId(baseMonitorInfo.getMonitorId());
                    report.setMonitorName(baseMonitorInfo.getMonitorName());
                    report.setpMonitorId(String.valueOf(baseMonitorInfo.getParentId()));
                    report.setAddress(baseMonitorInfo.getMonitorAddr());
                    BigDecimal MaxZXYG = BigDecimal.valueOf(Double.valueOf(String.valueOf(dnbInstant.get(dnbInstant.size() - 1).get("zxyg"))));
                    BigDecimal MinZXYG = BigDecimal.valueOf(Double.valueOf(String.valueOf(dnbInstant.get(0).get("zxyg"))));
                    //pt ct值暂时无用，默认为1 需要时从计量设备信息中根据id获取
                    int pt = 1;
                    int ct = 1;
                    //乘ct值和pt值
                    /**
                     * (MAX(ifnull(t1.zxyg,0)) - MIN(ifnull(t1.zxyg,0)))  * ifnull(t2.pt,1) * ifnull(t2.ct,1)as expend,
                     * 				0 as price,
                     * 				hour(date_sub(@nowDate, interval 1 hour)) as point_time,
                     * 				DATE_FORMAT(date_sub(@nowDate, interval 1 hour),'%Y-%m-%d %H:00:00') as begin_time,
                     * 				DATE_FORMAT(@nowDate,'%Y-%m-%d %H:00:00') as end_time,
                     * 				DATE_FORMAT(date_sub(@nowDate,interval 1 hour),'%Y-%m-%d %H:00:00') as record_time*/
                    report.setExpend(MaxZXYG.subtract(MinZXYG).multiply(new BigDecimal(pt)).multiply(new BigDecimal(ct)));
                    report.setPrice(new BigDecimal(0));
                    report.setPointTime(String.valueOf(hours - 1));
                    report.setMeterValue(MaxZXYG.subtract(MinZXYG));
                    report.setRecordTime(sdf.parse(sdf.format(startTime)));
                    report.setBeginTime(sdf.parse(sdf.format(startTime)));
                    report.setEndTime(sdf.parse(sdf.format(endTime)));
                    reportPoints.add(report);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }
        //将获取到的数据存入到实时数据中
        for (ReportPointDnb p : reportPoints) {
            reportPointDnbService.insertReportPointDnb(p);
        }

    }


}
