package cn.cecep.talroad.service.impl;

import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.domain.AiDeepModelResult;
import cn.cecep.talroad.domain.BasDevice;
import cn.cecep.talroad.domain.BasDeviceSite;
import cn.cecep.talroad.domain.PcOutlet;
import cn.cecep.talroad.enums.EnIndustry;
import cn.cecep.talroad.mapper.AiDeepModelResultMapper;
import cn.cecep.talroad.mapper.PcOutletMapper;
import cn.cecep.talroad.service.*;
import cn.cecep.talroad.vo.*;
import cn.cecep.talroad.vo.query.MonElecRealQuery;
import cn.cecep.talroad.vo.query.SEnvGasMonRealQuery;
import cn.cecep.talroad.vo.query.SEnvGasRealQuery;
import cn.cecep.talroad.vo.query.SEnvWaterMonRealQuery;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 产排治模块base service
 */
@Service
public class ProductionManageServiceImpl implements IProductionManageService {

    @Autowired
    private PcOutletMapper outletMapper;

    @Autowired
    private ISEnvGasMonRealService envGasMonRealService;

    @Autowired
    private ISEnvWaterMonRealService waterMonRealService;

    @Autowired
    private ISEnvGasRealService envGasRealService;

    @Autowired
    private IBasDeviceService basDeviceService;

    @Autowired
    private IBasDeviceSiteService basDeviceSiteService;

    @Autowired
    private IMonElecRealService monElecRealService;

    @Autowired
    private AiDeepModelResultMapper aiDeepModelResultMapper;

    @Override
    public SearchVo getSearchVo(String outletId, List<String> deviceIds) {
        SearchVo searchVo = new SearchVo();

        // 排口在线监测点位
        if (StringUtils.isNotEmpty(outletId)) {
            List<PcOutlet> onlineOutlets = outletMapper.selectList(new QueryWrapper<PcOutlet>()
                    .eq("parent_outlet_id", outletId)
                    .in("pollutant_type", "3", "4")
                    .orderByAsc("id")
            );
            List<PcOutletVo.SimpleVo> collect = onlineOutlets.stream().map(o -> {
                PcOutletVo.SimpleVo simpleVo = new PcOutletVo.SimpleVo();
                BeanUtils.copyProperties(o, simpleVo);
                return simpleVo;
            }).collect(Collectors.toList());
            searchVo.setOutletSimpleVo(collect);
        }

        if (deviceIds != null && deviceIds.size() > 0) {
            List<BasDevice> basDevices = basDeviceService.list(new QueryWrapper<BasDevice>().in("device_id", deviceIds).orderByAsc("industry", "device_id"));

            List<BasDevice> dcsList = new ArrayList<>();
            List<BasDevice> elList = new ArrayList<>();

            // 行业为EL的是分表计电设备，其余的都是工况设备
            for (BasDevice basDevice : basDevices) {
                if (EnIndustry.EL.id().equals(basDevice.getIndustry())) {
                    elList.add(basDevice);
                } else {
                    dcsList.add(basDevice);
                }
            }

            List<BasDeviceVo.SimpleVo> dcsSimpleVoList = dcsList.stream().map(o -> {
                BasDeviceVo.SimpleVo simpleVo = new BasDeviceVo.SimpleVo();
                BeanUtils.copyProperties(o, simpleVo);
                return simpleVo;
            }).collect(Collectors.toList());
            searchVo.setDeviceSimpleVo(dcsSimpleVoList);

            if (!elList.isEmpty()) {
                List<BasDeviceSite> sites = basDeviceSiteService.list(new QueryWrapper<BasDeviceSite>()
                        .in("device_id", elList.stream().map(BasDevice::getDeviceId).collect(Collectors.toList()))
                        .orderByAsc("device_id", "id"));
                List<BasDeviceSiteVo.SimpleVo> siteSimpleVoList = sites.stream().map(o -> {
                    BasDeviceSiteVo.SimpleVo simpleVo = new BasDeviceSiteVo.SimpleVo();
                    BeanUtils.copyProperties(o, simpleVo);
                    return simpleVo;
                }).collect(Collectors.toList());
                searchVo.setDeviceSiteSimpleVo(siteSimpleVoList);
            }
        }
        return searchVo;
    }

    /**
     * 获取产排治弹框数据
     * @return
     */
    @Override
    public FrameDataVo getFrameData(SearchVo searchVo) {
        String startTime = searchVo.getStartTime();
        String endTime = searchVo.getEndTime();
        Long pageNum = searchVo.getPageNum();
        Long pageSize = searchVo.getPageSize();
        String dataType = searchVo.getDataType() == null ? "M" : searchVo.getDataType();

        // 工况设备/分表计电点位/在线监测点位
        List<Object> objects = new ArrayList<>();

        if (searchVo.getOutletSimpleVo() != null) {
            objects.addAll(searchVo.getOutletSimpleVo());
        }
        if (searchVo.getDeviceSimpleVo() != null) {
            objects.addAll(searchVo.getDeviceSimpleVo());
        }
        if (searchVo.getDeviceSiteSimpleVo() != null) {
            objects.addAll(searchVo.getDeviceSiteSimpleVo());
        }
        // 分表计电监测点位合并到一个图表中，因此将分表计电点位列表作为一个整体添加到objects集合
        if (searchVo.getMergeDeviceSiteSimpleVo() != null && searchVo.getMergeDeviceSiteSimpleVo().size() > 0) {
            objects.add(searchVo.getMergeDeviceSiteSimpleVo());
        }
        if (searchVo.getDeviceSimpleStatusVos() != null) {
            objects.addAll(searchVo.getDeviceSimpleStatusVos());
        }
        if (searchVo.getDcsOnlineVos() != null) {
            objects.addAll(searchVo.getDcsOnlineVos());
        }

        // 排口关联的工况设备/分表计电点位/在线监测点位曲线图列表
        List<EChartsVO> chartsVOS = new ArrayList<>();

        if (!objects.isEmpty()) {
            // 由于工况设备/分表计电点位/在线监测点位相关数据表数据量大，分页获取这些点位的曲线图
            List<Object> pageObjects = objects.stream().skip((pageNum - 1) * pageSize)
                    .limit(pageSize)
                    .collect(Collectors.toList());

            for (Object object : pageObjects) {
                if (object instanceof PcOutletVo.SimpleVo) {

                    EChartsVO onlineChart = getOnlineChart((PcOutletVo.SimpleVo) object, dataType, startTime, endTime);
                    chartsVOS.add(onlineChart);

                } else if (object instanceof BasDeviceVo.SimpleVo) {
                    BasDeviceVo.SimpleVo device = (BasDeviceVo.SimpleVo) object;

                    EChartsVO cepDeviceChart = basDeviceService.getDeviceChart(device.getDeviceId(), startTime, endTime, "R", device.getPollutantVos());
                    cepDeviceChart.setName("DCS监测数据-" + device.getName());
                    chartsVOS.add(cepDeviceChart);
                } else if (object instanceof List && ((List)object).get(0) instanceof BasDeviceSiteVo.SimpleVo) {
                    List<BasDeviceSiteVo.SimpleVo> sites = (List<BasDeviceSiteVo.SimpleVo>) object;
                    EChartsVO charData = monElecRealService.getCharData(sites, startTime, endTime);

                    if (StringUtils.isBlank(charData.getName())) {
                        charData.setName("计电监测数据");
                    } else {
                        charData.setName("计电监测数据-" + charData.getName());
                    }
                    chartsVOS.add(charData);
                } else if (object instanceof BasDeviceSiteVo.SimpleVo) {
                    BasDeviceSiteVo.SimpleVo site = (BasDeviceSiteVo.SimpleVo) object;

                    MonElecRealQuery query = new MonElecRealQuery();
                    query.setDeviceSiteId(site.getId());
                    query.setDataTimeStart(startTime);
                    query.setDataTimeEnd(endTime);
                    query.setPollutantVos(site.getPollutantVos());

                    EChartsVO charData = monElecRealService.getCharData(query);
                    charData.setName("计电监测数据-" + site.getName());
                    chartsVOS.add(charData);
                } else if (object instanceof BasDeviceVo.SimpleStatusVo) {
                    BasDeviceVo.SimpleStatusVo device = (BasDeviceVo.SimpleStatusVo) object;

                    EChartsVO chartsVO = basDeviceService.getDeviceStatusChart(device, startTime, endTime);
                    chartsVO.setName("生产设施状态数据-" + device.getName());
                    chartsVO.setRenderFlag("1");
                    chartsVOS.add(chartsVO);
                } else if (object instanceof BasDeviceVo.DcsOnlineVo) {
                    BasDeviceVo.DcsOnlineVo dcsOnlineVo = (BasDeviceVo.DcsOnlineVo) object;

                    List<AiDeepModelResult> aiDeepModelResults = aiDeepModelResultMapper.selectList(new QueryWrapper<AiDeepModelResult>()
                            .eq("device_id", dcsOnlineVo.getDcsSimpleVo().getDeviceId())
                            .eq("outlet_id", dcsOnlineVo.getOnlineSimpleVo().getId())
                            .ge("data_time", DateUtils.parseDate(startTime))
                            .le("data_time", DateUtils.parseDate(endTime))
                    );

                    // 设置监测物的上下限数据
                    for (AmProblemFiVo.PollutantVo pollutantVo : dcsOnlineVo.getOnlineSimpleVo().getPollutantVos()) {
                        Map<String, AmProblemFiVo.PollutantLimitVo> pollutantLimitVoMap = aiDeepModelResults.stream().collect(Collectors.toMap(
                                modelResult -> DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", modelResult.getDataTime()),
                                modelResult -> {
                                    AmProblemFiVo.PollutantLimitVo limitVo = new AmProblemFiVo.PollutantLimitVo();
                                    limitVo.setLowerLimit(BeanUtil.getProperty(modelResult, pollutantVo.getProp() + "LowLim"));
                                    limitVo.setUpperLimit(BeanUtil.getProperty(modelResult, pollutantVo.getProp() + "UpLim"));

                                    BigDecimal lowerLimit = null;
                                    BigDecimal upperLimit = null;

                                    if (StringUtils.isNotEmpty(limitVo.getLowerLimit())) {
                                        lowerLimit = new BigDecimal(limitVo.getLowerLimit()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                        limitVo.setLowerLimit(lowerLimit.stripTrailingZeros().toPlainString());
                                    }

                                    if (StringUtils.isNotEmpty(limitVo.getUpperLimit())) {
                                        upperLimit = new BigDecimal(limitVo.getUpperLimit()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                        limitVo.setUpperLimit(upperLimit.stripTrailingZeros().toPlainString());
                                    }

                                    // 由于前端上下限系列是叠加展示的，上限的系列值=上限-下限
                                    if (lowerLimit != null && upperLimit != null) {
                                        String upper = upperLimit.subtract(lowerLimit).stripTrailingZeros().toPlainString();
                                        limitVo.setUpperLimit(upper);
                                    }
                                    return limitVo;
                                },
                                (o1, o2) -> o1));

                        pollutantVo.setPollutantLimitMap(pollutantLimitVoMap);
                    }

                    EChartsVO onlineChart = getOnlineChart(dcsOnlineVo.getOnlineSimpleVo(), dataType, startTime, endTime);

                    EChartsVO cepDeviceChart = basDeviceService.getDeviceChart(
                            dcsOnlineVo.getDcsSimpleVo().getDeviceId(), startTime, endTime, "R",
                            dcsOnlineVo.getDcsSimpleVo().getPollutantVos()
                    );
                    cepDeviceChart.setName("DCS监测数据-" + dcsOnlineVo.getDcsSimpleVo().getName());
                    cepDeviceChart.getSeries().addAll(0, onlineChart.getSeries());

                    chartsVOS.add(cepDeviceChart);
                } else {
                    throw new RuntimeException("未知的类型（不属于工况设备/分表计电点位/在线监测点位）");
                }
            }
        }

        FrameDataVo vo = new FrameDataVo();
        vo.setChartsVOS(chartsVOS);
        vo.setTotal(objects.size());
        return vo;
    }

    private EChartsVO getOnlineChart(PcOutletVo.SimpleVo onlinePoint, String dataType, String startTime, String endTime) {
        EChartsVO charData;

        // 废气监测点
        if ("4".equals(onlinePoint.getPollutantType()) && ("1".equals(onlinePoint.getPollutantOutletType()) || "3".equals(onlinePoint.getPollutantOutletType()))) {
            SEnvGasMonRealQuery query = new SEnvGasMonRealQuery();
            query.setDataType(dataType);
            query.setOutletId(onlinePoint.getId());
            query.setMonitoringStartTime(startTime);
            query.setMonitoringEndTime(endTime);
            query.setPollutantVos(onlinePoint.getPollutantVos());

            String s = StringUtils.isEmpty(onlinePoint.getMonitoringPointName()) ? "" : ("-" + onlinePoint.getMonitoringPointName());

            charData = envGasMonRealService.getCharData(query);
            charData.setName("废气在线监测数据" + s);
        } else if ("4".equals(onlinePoint.getPollutantType()) && "2".equals(onlinePoint.getPollutantOutletType())) { // 废水监测点
            SEnvWaterMonRealQuery query = new SEnvWaterMonRealQuery();
            query.setDataType(dataType);
            query.setOutletId(onlinePoint.getId());
            query.setMonitoringStartTime(startTime);
            query.setMonitoringEndTime(endTime);
            query.setPollutantVos(onlinePoint.getPollutantVos());

            String s = StringUtils.isEmpty(onlinePoint.getMonitoringPointName()) ? "" : ("-" + onlinePoint.getMonitoringPointName());

            charData = waterMonRealService.getCharData(query);
            charData.setName("废水在线监测数据" + s);
        } else if ("3".equals(onlinePoint.getPollutantType())) { // 无组织
            SEnvGasRealQuery query = new SEnvGasRealQuery();
            query.setDataType(dataType);
            query.setOutletId(onlinePoint.getId());
            query.setMonitoringStartTime(startTime);
            query.setMonitoringEndTime(endTime);
            query.setPollutantVos(onlinePoint.getPollutantVos());

            String s = StringUtils.isEmpty(onlinePoint.getMonitoringPointName()) ? "" : ("-" + onlinePoint.getMonitoringPointName());

            charData = envGasRealService.getCharData(query);
            charData.setName("无组织在线监测数据" + s);
        } else {
            throw new RuntimeException(String.format("未知的排口类型（pollutantType=%s, pollutantOutletType=%s）",
                    onlinePoint.getPollutantType(), onlinePoint.getPollutantOutletType()));
        }
        return charData;
    }

}
