package cn.cecep.talroad.service.impl.effective;

import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.domain.SEnvGasMonHour;
import cn.cecep.talroad.domain.TCodStationDataAir;
import cn.cecep.talroad.domain.effective.ERmStationExceed;
import cn.cecep.talroad.mapper.SEnvGasMonHourMapper;
import cn.cecep.talroad.mapper.TCodStationDataAirMapper;
import cn.cecep.talroad.mapper.effective.ERmStationExceedMapper;
import cn.cecep.talroad.service.effective.ERmStationExceedService;
import cn.cecep.talroad.vo.EChartsVO;
import cn.cecep.talroad.vo.PcFactoryVo;
import cn.cecep.talroad.vo.effective.ERmStationInfo;
import cn.cecep.talroad.vo.effective.SEnvGasMonValueVo;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ERmStationExceedServiceImpl extends ServiceImpl<ERmStationExceedMapper, ERmStationExceed> implements ERmStationExceedService{

    @Autowired
    private TCodStationDataAirMapper stationDataAirMapper;
    @Autowired
    private SEnvGasMonHourMapper sEnvGasMonHourMapper;
    @Override
    public int updateBatch(List<ERmStationExceed> list) {
        return baseMapper.updateBatch(list);
    }
    @Override
    public int updateBatchSelective(List<ERmStationExceed> list) {
        return baseMapper.updateBatchSelective(list);
    }
    @Override
    public int batchInsert(List<ERmStationExceed> list) {
        return baseMapper.batchInsert(list);
    }

    @Override
    public IPage<ERmStationInfo> selectListInfo(ERmStationInfo entity) {
        if(ObjectUtil.isEmpty(entity.getPageNum())){
            entity.setPageNum(1);
            entity.setPageSize(Integer.MAX_VALUE);
        }
        Page<ERmStationInfo> page = new Page<>(entity.getPageNum(),entity.getPageSize());
       return baseMapper.selectListInfo(page,entity);
    }
    @Override
    public EChartsVO changingTrends(List<String> stationIds, String contaminant, Date start, Date end) {
        if(contaminant.endsWith("2.5")){
            contaminant = "pm25";
        }
        EChartsVO eChartsVO = new EChartsVO();
        List<String> dateList = CollUtil.map(DateUtil.rangeToList(start,
                        end, DateField.HOUR_OF_DAY),
                x -> DateUtil.format(x, "yyyy-MM-dd HH"), true);
        eChartsVO.setXData(dateList);
        eChartsVO.setName("站点变化趋势XY数据");
        QueryWrapper<TCodStationDataAir> ew = new QueryWrapper<>();
        ew.in("station_id", stationIds);
        ew.ge("monitor_time", start);
        ew.le("monitor_time", end);
        ew.eq("data_type", "H");
        ew.select(contaminant.replaceAll("([A-Z]+)", "_$1").toLowerCase()+ " AS id","monitor_time","station_id");
        ew.orderByDesc("monitor_time");
        List<TCodStationDataAir> allRmStationHours = stationDataAirMapper.selectList(ew);
        List<EChartsVO.SeriesObj> serList = generateSeriesList(allRmStationHours, stationIds, dateList, "stationId", "monitorTime");
        eChartsVO.setSeries(serList);
        return eChartsVO;
    }

    @Override
    public EChartsVO entChangingTrends(List<String> entIds, String contaminant, Date start, Date end) {
        EChartsVO eChartsVO = new EChartsVO();
        List<String> dateList = CollUtil.map(DateUtil.rangeToList(start,
                        end, DateField.HOUR_OF_DAY),
                x -> DateUtil.format(x, "yyyy-MM-dd HH"), true);
        eChartsVO.setXData(dateList);
        eChartsVO.setName("企业变化趋势XY数据");
        QueryWrapper<SEnvGasMonHour> ew = new QueryWrapper<>();
        ew.in("factory_id", entIds);
        ew.ge("monitoring_time", start);
        ew.le("monitoring_time", end);
        ew.select("SUM(CAST ("+contaminant+ " AS numeric) ) AS id","monitoring_time","factory_id");
        ew.orderByDesc("monitoring_time");
        ew.groupBy("factory_id", "monitoring_time");
        List<SEnvGasMonHour> allSEnvGasMonHours = sEnvGasMonHourMapper.selectList(ew);
        List<EChartsVO.SeriesObj> serList = generateSeriesList(allSEnvGasMonHours, entIds, dateList, "factoryId", "monitoringTime");
        eChartsVO.setSeries(serList);
        return eChartsVO;
    }

    @Override
    public List<PcFactoryVo.MapPointVo> selectGasAndHaveData(Integer pageNum, Integer pageSize) {
        Page<PcFactoryVo> page = new Page<>(pageNum,pageSize);
        return baseMapper.selectGasAndHaveData(page).getRecords().stream().map(o -> {
            PcFactoryVo.MapPointVo vo = new PcFactoryVo.MapPointVo();
            BeanUtils.copyProperties(o, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public EChartsVO selectEntPollution(String entId, Date start, Date end) {
      /*  LocalDate start=LocalDate.parse("2023-07-06", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate end=start.plusDays(1);*/
        EChartsVO eChartsVO = new EChartsVO();

        List<String> dateList = CollUtil.map(DateUtil.rangeToList(start,
               end, DateField.HOUR_OF_DAY),
                x -> DateUtil.format(x, "yyyy-MM-dd HH"), true);
        eChartsVO.setXData(dateList);
        List<SEnvGasMonValueVo> sEnvGasMonValueVos = sEnvGasMonHourMapper.selectEntPollutionMapper(entId,start,end,"factory_id,field,monitoring_time");
        String [] strings=new String[]{"so2","nox","烟尘","voc"};
        List<EChartsVO.SeriesObj> serList =  generateSeriesList(sEnvGasMonValueVos, java.util.Arrays.asList(strings), dateList, "field", "monitoringTime");
        eChartsVO.setSeries(serList);
        return eChartsVO;
    }

    @Override
    public List<SEnvGasMonValueVo> summaryOfCorporateEmissions(String entId, Date start, Date end) {
        return sEnvGasMonHourMapper.selectEntPollutionMapper(entId,start,end,"factory_id,field,name");
    }

    @Override
    public IPage<ERmStationInfo> selectStationList(ERmStationInfo entity) {
        if(ObjectUtil.isEmpty(entity.getPageNum())){
            entity.setPageNum(1);
            entity.setPageSize(Integer.MAX_VALUE);
        }
        Page<ERmStationInfo> page = new Page<>(entity.getPageNum(),entity.getPageSize());
        return baseMapper.selectStationList(page,entity);
    }

    public <T> List<EChartsVO.SeriesObj> generateSeriesList(List<T> entityList, List<String> idList, List<String> dateList, String idFieldName, String timeFieldName) {
        Map<String, List<T>> entityMap = entityList.stream().collect(Collectors.groupingBy(entity -> {
            try {
                Field idField = entity.getClass().getDeclaredField(idFieldName);
                idField.setAccessible(true);
                return idField.get(entity).toString();
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
                throw new RuntimeException("变化趋势图，获取分组时错误，分组字段获取失败!");
            }
        }));

        List<T> nullList = new ArrayList<>();

        return idList.stream().map(id -> {
            EChartsVO.SeriesObj series = new EChartsVO.SeriesObj();
            List<Object> ylist = new ArrayList<>();
            series.setName(id);
            series.setProp(id);

            Map<String, String> collect = entityMap.getOrDefault(id, nullList).stream().collect(Collectors.toMap(entity -> {
                try {
                    Field timeField = entity.getClass().getDeclaredField(timeFieldName);
                    timeField.setAccessible(true);
                    LocalDateTime time;
                    if(timeField.getType().isAssignableFrom(Date.class)){
                        time=LocalDateTime.ofInstant(((Date)timeField.get(entity)).toInstant(), ZoneId.systemDefault());
                    }else if (timeField.getType().isAssignableFrom(String.class)){
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                        time=LocalDateTime.parse((String)timeField.get(entity), formatter);
                    }else {
                        throw new RuntimeException("不好了，时间又出现新的类型了");
                    }
                    return DateUtil.format(time, "yyyy-MM-dd HH");
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                    return null;
                }
            }, entity -> {
                try {
                    Field idField = entity.getClass().getDeclaredField("id");
                    idField.setAccessible(true);
                    String idValue = (String) idField.get(entity);
                    return StringUtils.isNotBlank(idValue) ? idValue : "0";
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                    return "0";
                }
            }));

            for (String s : dateList) {
                ylist.add(collect.getOrDefault(s, "0"));
            }
            series.setValues(ylist);
            return series;
        }).collect(Collectors.toList());
    }
}
