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

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.hw.common.core.utils.DateUtils;
import com.hw.ems.base.domain.BaseCollectDeviceInfo;
import com.hw.ems.base.domain.BaseLineMonitor;
import com.hw.ems.base.domain.BaseTypeRelation;
import com.hw.ems.base.domain.SysDatasource;
import com.hw.ems.base.mapper.BaseCollectDeviceInfoMapper;
import com.hw.ems.base.mapper.BaseLineMonitorMapper;
import com.hw.ems.base.mapper.BaseTypeRelationMapper;
import com.hw.ems.base.service.IBaseLineMonitorService;
import com.hw.ems.base.service.ISysDatasourceService;
import com.hw.ems.record.domain.RecordDnbInstant;
import com.hw.ems.record.domain.RecordWaterInstant;
import com.hw.ems.record.mapper.RecordDnbInstantMapper;
import com.hw.ems.record.mapper.RecordWaterInstantMapper;
import com.hw.ems.report.service.IBoardService;
import com.hw.ems.report.service.IDataAnalysisService;
import com.hw.common.core.utils.sortReportUitls;
import com.hw.ems.report.service.IEnergyPreviewService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import static com.hw.ems.base.service.impl.BaseLineMonitorServiceImpl.getNextLevelLineMonitorList;


/**
 * 看板Service业务层处理
 *
 * @author YinQ
 * @date 2023-04-09
 */
@Service
public class BoardServiceImpl implements IBoardService {

    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private BaseTypeRelationMapper baseTypeRelationMapper;

    @Autowired
    private RecordDnbInstantMapper recordDnbInstantMapper;

    @Autowired
    private RecordWaterInstantMapper recordWaterInstantMapper;

    @Autowired
    private BaseLineMonitorMapper baseLineMonitorMapper;

    @Autowired
    private IDataAnalysisService dataAnalysisService;

    @Autowired
    private IBaseLineMonitorService baseLineMonitorService;

    @Autowired
    private ISysDatasourceService datasourceService;

    @Autowired
    private BaseCollectDeviceInfoMapper collectDeviceInfoMapper;

    @Autowired
    private IEnergyPreviewService energyPreviewService;

    /**
     * 表具信息
     *
     * @param paramMap
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public Map<String, Object> tablewareInfo(Map paramMap) {
        HashMap<String, Object> result = new HashMap<>();
        if (String.valueOf(paramMap.get("energyType")).equals("")) {
            return result;
        }
        Long energyType = Long.valueOf(String.valueOf(paramMap.get("energyType")));
        Long relationId;
        if (String.valueOf(paramMap.get("relationId")).equals("")){
            relationId = null;
        }else {
            relationId = Long.valueOf(String.valueOf(paramMap.get("relationId")));
        }
        BaseTypeRelation typeRelation = new BaseTypeRelation();
        typeRelation.setType(0L);
        typeRelation.setRelationId(relationId);
        typeRelation.setMonitorType(energyType);
        List<BaseTypeRelation> typeRelations = baseTypeRelationMapper.selectBaseTypeRelationList(typeRelation);
        if (typeRelations.size() == 0){
            return result;
        }
        List<String> monitorIdList = typeRelations.stream().map(BaseTypeRelation::getMonitorId).collect(Collectors.toList());
        HashMap<String, Object> params = new HashMap<>();

//        params.put("beginCollectTime",String.valueOf(paramMap.get("beginCollectTime")));
//        params.put("endCollectTime",String.valueOf(paramMap.get("endCollectTime")));
        ArrayList<HashMap<String,Object>> energyList = new ArrayList<>();
        //查询有子集的父级设备List
        BaseLineMonitor baseLineMonitor = new BaseLineMonitor();
        baseLineMonitor.setMonitorType(energyType);
        List<BaseLineMonitor> baseLineMonitorList = baseLineMonitorService.selectBaseLineMonitorList(baseLineMonitor);
        List<BaseLineMonitor> baseLineMonitors = baseLineMonitorService.selectMonitorSubsetList(baseLineMonitor);
        List<String> monitorIdParentList = baseLineMonitors.stream().map(BaseLineMonitor::getMonitorId).collect(Collectors.toList());

        if (energyType == 2) {
            RecordDnbInstant recordDnbInstant = new RecordDnbInstant();
            params.put("monitorIdList",monitorIdList);
            recordDnbInstant.setParams(params);
            List<RecordDnbInstant> recordDnbInstants = recordDnbInstantMapper.instantList(recordDnbInstant);
            for (RecordDnbInstant dnbInstant : recordDnbInstants) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("monitorId",dnbInstant.getMonitorId());
                map.put("monitorName",dnbInstant.getMonitorName());
                map.put("consumption",dnbInstant.getConsumption());
                map.put("onlineState",dnbInstant.getOnlineState());
                ArrayList<HashMap<String,Object>> childEnergyList = new ArrayList<>();
                if (monitorIdParentList.contains(dnbInstant.getMonitorId())){
                    List<BaseLineMonitor> nextLevelLineMonitorList = getNextLevelLineMonitorList(baseLineMonitorList, dnbInstant.getMonitorId());
                    List<String> monitorIdChildList = nextLevelLineMonitorList.stream().map(BaseLineMonitor::getMonitorId).collect(Collectors.toList());
                    params.put("monitorIdList",monitorIdChildList);
                    recordDnbInstant.setParams(params);
                    List<RecordDnbInstant> recordDnbInstantList = recordDnbInstantMapper.instantList(recordDnbInstant);
                    for (RecordDnbInstant instant : recordDnbInstantList) {
                        HashMap<String, Object> instantMap = new HashMap<>();
                        instantMap.put("monitorId",instant.getMonitorId());
                        instantMap.put("monitorName",instant.getMonitorName());
                        instantMap.put("consumption",instant.getConsumption());
                        instantMap.put("onlineState",instant.getOnlineState());
                        childEnergyList.add(instantMap);
                    }
                    map.put("childMap",childEnergyList);
                }else {
                    map.put("childMap",childEnergyList);
                }
                energyList.add(map);
            }
        } else if (energyType == 3) {
            RecordWaterInstant recordWaterInstant = new RecordWaterInstant();
            params.put("monitorIdList",monitorIdList);
            recordWaterInstant.setParams(params);
            List<RecordWaterInstant> recordWaterInstants = recordWaterInstantMapper.instantList(recordWaterInstant);
            for (RecordWaterInstant waterInstant : recordWaterInstants) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("monitorId",waterInstant.getMonitorId());
                map.put("monitorName",waterInstant.getMonitorName());
                map.put("consumption",waterInstant.getConsumption());
                map.put("onlineState",waterInstant.getOnlineState());
                ArrayList<HashMap<String,Object>> childEnergyList = new ArrayList<>();
                if (monitorIdParentList.contains(waterInstant.getMonitorId())){
                    List<BaseLineMonitor> nextLevelLineMonitorList = getNextLevelLineMonitorList(baseLineMonitorList, waterInstant.getMonitorId());
                    List<String> monitorIdChildList = nextLevelLineMonitorList.stream().map(BaseLineMonitor::getMonitorId).collect(Collectors.toList());
                    params.put("monitorIdList",monitorIdChildList);
                    recordWaterInstant.setParams(params);
                    List<RecordWaterInstant> recordWaterInstantList = recordWaterInstantMapper.instantList(recordWaterInstant);
                    for (RecordWaterInstant waterInstant1 : recordWaterInstantList) {
                        HashMap<String, Object> instantMap = new HashMap<>();
                        instantMap.put("monitorId",waterInstant1.getMonitorId());
                        instantMap.put("monitorName",waterInstant1.getMonitorName());
                        instantMap.put("consumption",waterInstant1.getConsumption());
                        instantMap.put("onlineState",waterInstant1.getOnlineState());
                        childEnergyList.add(instantMap);
                    }
                    map.put("childMap",childEnergyList);
                }else {
                    map.put("childMap",childEnergyList);
                }
                energyList.add(map);
            }
        }
        result.put("energyList",energyList);
        return result;
    }

    /**
     * 园区首页概览
     *
     * @param paramMap
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public Map<String, Object> parkHomepageOverview(Map paramMap) {
        HashMap<String, Object> result = new HashMap<>();
        ArrayList<String> monitorIdList = new ArrayList<>();
        List<BaseLineMonitor> baseLineMonitors = baseLineMonitorMapper.selectBaseLineMonitorList(new BaseLineMonitor());
        Map<String, String> startAndEndTime = DateUtils.getStartAndEndTime();
        paramMap.put("timeSub", 0);
        //电计算
        List<BaseLineMonitor> lineDnbMonitorList = getNextLevelLineMonitorList(baseLineMonitors, "S01_00001");
        List<String> dnbMonitorList = lineDnbMonitorList.stream().map(BaseLineMonitor::getMonitorId).collect(Collectors.toList());
        monitorIdList.addAll(dnbMonitorList);
        paramMap.put("energyType", 2);
        BigDecimal monthDnbConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("monthStart"), startAndEndTime.get("monthEnd"));
        BigDecimal yearDnbConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("yearStart"), startAndEndTime.get("yearEnd"));
        result.put("monthDnbConsumption", monthDnbConsumption);
        result.put("yearDnbConsumption", yearDnbConsumption);
        //月环比
        BigDecimal lastMonthDnbConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("lastMonthStart"), startAndEndTime.get("lastMonthEnd"));
        BigDecimal dnbMoM = sortReportUitls.calculateMoMYoY(monthDnbConsumption, lastMonthDnbConsumption, 2);
        result.put("dnbMonthMoM", dnbMoM);
        //月同比
        BigDecimal lastYearMonthDnbConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("lastYearMonthStart"), startAndEndTime.get("lastYearMonthEnd"));
        BigDecimal dnbYoY = sortReportUitls.calculateMoMYoY(monthDnbConsumption, lastYearMonthDnbConsumption, 2);
        result.put("dnbMonthYoY", dnbYoY);
        //年同比
        BigDecimal lastYearDnbConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("lastYearStart"), startAndEndTime.get("lastYearEnd"));
        BigDecimal dnbYearYoY = sortReportUitls.calculateMoMYoY(monthDnbConsumption, lastYearDnbConsumption, 2);
        result.put("dnbYearYoY", dnbYearYoY);
        result.put("dnbYearMoM", dnbYearYoY);

        //水计算
        List<BaseLineMonitor> lineWaterMonitorList = getNextLevelLineMonitorList(baseLineMonitors, "S02_00001");
        List<String> waterMonitorList = lineWaterMonitorList.stream().map(BaseLineMonitor::getMonitorId).collect(Collectors.toList());
        monitorIdList.addAll(waterMonitorList);
        paramMap.put("energyType", 3);
        BigDecimal monthWaterConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("monthStart"), startAndEndTime.get("monthEnd"));
        BigDecimal yearWaterConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("yearStart"), startAndEndTime.get("yearEnd"));
        result.put("monthWaterConsumption", monthWaterConsumption);
        result.put("yearWaterConsumption", yearWaterConsumption);
        //月环比
        BigDecimal lastMonthWaterConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("lastMonthStart"), startAndEndTime.get("lastMonthEnd"));
        BigDecimal waterMonthMoM = sortReportUitls.calculateMoMYoY(monthWaterConsumption, lastMonthWaterConsumption, 2);
        result.put("waterMonthMoM", waterMonthMoM);
        //月同比
        BigDecimal lastYearMonthWaterConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("lastYearMonthStart"), startAndEndTime.get("lastYearMonthEnd"));
        BigDecimal waterMonthYoY = sortReportUitls.calculateMoMYoY(monthWaterConsumption, lastYearMonthWaterConsumption, 2);
        result.put("waterMonthYoY", waterMonthYoY);
        //年同比
        BigDecimal lastYearWaterConsumption = parkConsumption(paramMap, monitorIdList, startAndEndTime.get("lastYearStart"), startAndEndTime.get("lastYearEnd"));
        BigDecimal waterYearYoY = sortReportUitls.calculateMoMYoY(yearWaterConsumption, lastYearWaterConsumption, 2);
        result.put("waterYearYoY", waterYearYoY);
        result.put("waterYearMoM", waterYearYoY);
        return result;
    }

    /**
     * 30天分项业态占比图
     *
     * @param paramMap
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public Map<String, Object> categoryBusinessChart(Map paramMap) {
        return null;
    }


    private BigDecimal parkConsumption(Map paramMap, ArrayList<String> monitorIdList, String startDate, String endDate) {
        List<Map<String, String>> energyList;
        paramMap.put("monitorIdList", monitorIdList);
        paramMap.put("startTime", startDate);
        paramMap.put("endTime", endDate);
        energyList = dataAnalysisService.energyConsumptionByTime(paramMap);
        if (energyList.size() > 0) {
            String expend = String.valueOf(energyList.get(0).get("expend"));
            return new BigDecimal(expend);
        } else {
            return new BigDecimal("0.00");
        }
    }

    /**
     * 接入园区、设备数量
     * @param paramMap
     * @return
     */
    @Override
    @DS("master")
    public Map<String, Object> parkEquipmentNumber(Map paramMap) {
        HashMap<String, Object> result = new HashMap<>();
        // 加载sf-cloud库的sys_datasource
        List<SysDatasource> dateSources = datasourceService.selectSysDatasource();
        try{
            int parkNumber = dateSources.size();
            int equipmentNumber = 0;
            for (SysDatasource dateSource : dateSources) {
                DynamicDataSourceContextHolder.push(dateSource.getPoolName());// 这是数据源的key
                List<BaseCollectDeviceInfo> baseCollectDeviceInfos = collectDeviceInfoMapper.selectBaseCollectDeviceInfoList(new BaseCollectDeviceInfo());
                equipmentNumber += baseCollectDeviceInfos.size();
            }
            result.put("parkNumber", parkNumber);
            result.put("equipmentNumber", equipmentNumber);
        }catch (Exception e){
            logger.error("service == parkEquipmentNumber == exception:" + e.getMessage());
        }
        return result;
    }

    /**
     * 各园区能耗排名
     * @param paramMap
     * @return
     */
    @Override
    @DS("master")
    public ArrayList<HashMap<String, Object>>parkEnergyRanking(Map paramMap) {
        ArrayList<HashMap<String, Object>> result = new ArrayList<>();
        if (String.valueOf(paramMap.get("energyType")).equals("")) {
            return result;
        }
        // 加载sf-cloud库的sys_datasource
        List<SysDatasource> dateSources = datasourceService.selectSysDatasource();
        ArrayList<String> monitorIdList = new ArrayList<>();
        BaseTypeRelation relation = new BaseTypeRelation();
        relation.setMonitorType(Long.parseLong(String.valueOf(paramMap.get("energyType"))));
        relation.setType(0L);
        relation.setRelationId(1L);
        try{
            List<Map<String, String>> energyList = new ArrayList<>();
            for (SysDatasource dateSource : dateSources) {
                    DynamicDataSourceContextHolder.push(dateSource.getPoolName());// 这是数据源的key
                    HashMap<String, Object> resultMap = new HashMap<>();
                    resultMap.put("poolName",dateSource.getPoolName());
                    resultMap.put("parkName",dateSource.getParkName());
                    List<BaseTypeRelation> baseTypeRelations = baseTypeRelationMapper.selectBaseTypeRelationList(relation);
                    for (BaseTypeRelation baseTypeRelation : baseTypeRelations) {
                        monitorIdList.add(baseTypeRelation.getMonitorId());
                    }
                    paramMap.put("monitorIdList", monitorIdList);
                    paramMap.put("timeSub", 0);
                    Map<String, String> startAndEndTime = DateUtils.getStartAndEndTime();
                    paramMap.put("startTime", startAndEndTime.get("yearStart"));
                    paramMap.put("endTime", startAndEndTime.get("yearEnd"));
                    //查询能源耗量
                    energyList = energyPreviewService.energyConsumptionByTime(paramMap);
                    if (energyList.size() > 0) {
                        resultMap.put("yearEnergy", energyList.get(0).get("expend"));
                    } else {
                        resultMap.put("yearEnergy", 0.00);
                    }
                    result.add(resultMap);
                }
        }catch (Exception e){
            logger.error("service == parkEnergyRanking == exception:" + e.getMessage());
        }
        return result;
    }
}
