package com.gyee.runeconomy.service.fiveloss;


import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gyee.common.model.StringUtils;
import com.gyee.common.util.DateUtils;
import com.gyee.common.vo.benchmark.FjjxbVo;
import com.gyee.runeconomy.dto.FiveLoss.AnnotationTool;
import com.gyee.runeconomy.dto.FiveLoss.FixedVo;
import com.gyee.runeconomy.dto.FiveLoss.TableTitle;
import com.gyee.runeconomy.dto.FiveLoss.exception.CustomException;
import com.gyee.runeconomy.dto.result.PowerPointData;
import com.gyee.runeconomy.dto.result.ResultCode;
import com.gyee.runeconomy.model.auto.ProBasicEquipment;
import com.gyee.runeconomy.model.auto.ProEconEquipmentInfoDay1;
import com.gyee.runeconomy.model.vo.LossPowerVo;
import com.gyee.runeconomy.service.auto.IProBasicEquipmentService;
import com.gyee.runeconomy.service.auto.IProEconEquipmentInfoDay1Service;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FiveLossService {

//    @Resource
//    private ProEconPowerFittingAnalySisService analysisService;

    @Resource
    private IProEconEquipmentInfoDay1Service equipmentInfoDay1Service;

    @Resource
    private IProBasicEquipmentService equipmentService;
//    @Resource
//    private ITurbineInfoDayService turbineInfoDayService;

    /**
     * 损失电量计算  eg: 1.5MW   一小时发电：1500kWh    一分钟发电：1500/60 == 25kW
     *
     * @param ztmxData 状态明细
     * @param zsglData 设备的理论功率
     * @param interval 原始数据的间隔
     * @param status   风机当前状态
     * @return
     */
//    private double generalLoss(List<PowerPointData> ztmxData, Map<Double, Double> zsglData, int interval, double status) {
//        double ssdl = 0.0;
//        List<PowerPointData> pointData = ztmxData.stream().filter(zt -> zt.getMxzt() == status).collect(Collectors.toList());
//        if (status == 0.0 || status == 2.0 || status == 3.0 || status == 4.0 || status == 9.0 || status == 10.0 || status == 11.0) {
//            for (PowerPointData obj : pointData) {
//                double speed = new BigDecimal(obj.getSpeed()).setScale(2, RoundingMode.FLOOR).doubleValue();
//                double zsgl = null == zsglData.get(speed) ? 0:zsglData.get(speed);
//                double power = obj.getPower();
//                double temp = (zsgl - power) > 0 ? zsgl - power : 0;
//                ssdl = ssdl + (temp / 60) * (interval / 60);
//            }
//        } else {
//            for (PowerPointData obj : pointData) {
//                if (obj.getSpeed() < 3.0) continue;
//                double speed = new BigDecimal(obj.getSpeed()).setScale(2, RoundingMode.FLOOR).doubleValue();
//                double zsgl =  null == zsglData.get(speed) ? 0:zsglData.get(speed);
//                ssdl = ssdl + (zsgl / 60) * (interval / 60);
//            }
//        }
//
//        //理论发电量 status < 0
//        if (status < 0){
//            for (PowerPointData obj : ztmxData) {
//                if (obj.getSpeed() < 3.0) continue;
//                double speed = new BigDecimal(obj.getSpeed()).setScale(2, RoundingMode.FLOOR).doubleValue();
//                double zsgl =  null == zsglData.get(speed) ? 0:zsglData.get(speed);
//                ssdl = ssdl + (zsgl / 60) * (interval / 60);
//            }
//        }
//
//        return ssdl > 0 ? ssdl : 0;
//    }


    //新的五损计算方法
    //1.思路整理 实际电量、计划检修损失电量、非计划检修损失电量、限电损失电量、受累损失电量、性能损失电量、理论发电量
    //计算思路        实际电量 当前功率 * 时间 = 电量
    //计划检修损失电量



    /**
     * 使用文件，通过自诉案功率计算五损数据
     * @param wpids  准备的数据ID
     */
//    public Map<String, Object> fiveLossCalByZSGL(String ids) {
//        Map<String, Object> promise = null;
//        try {
//            log.info("======风机绩效榜计算开始.............");
//            promise = new HashMap<>();
//            List<FjjxbVo> result = new ArrayList<>();
//            Map<String, Map<Double, Double>> zsglmap = InitialRunner.zsllglNewMap;
//
//            List<ProEconPowerFittingAnalySis> analyses = analysisService.selectListByIds(ids);
//            if (analyses.isEmpty()){
//                log.info("======风机榜效帮计算结束，数据为空.............");
//                throw new CustomException(ResultCode.ERROR);
//            }
//
//            for (ProEconPowerFittingAnalySis p : analyses) {
//                List<String> content = FileUtil.readFile(p.getPath(), true);
//                if (content.isEmpty() || zsglmap.isEmpty() || zsglmap.get(p.getWindturbineId()) == null){
//                    log.info("======风机榜效帮计算结束，" + p.getWindturbineId() + "文件内容或当前风机的自算功率为空.............");
//                    continue;
//                }
//                log.info("======风机绩效榜计算：" + p.getWindturbineId());
//                double llfdl = 0.0; //理论发电量
//                double rfdl = 0.0; //日发电量
//                double jhjxssdl = 0.0;//计划检修损失电量
//                double fjhjxssdl =0.0;//非计划检修电量
//                double xdssdl = 0.0;//限电损失电量
//                double slssdl = 0.0;//受累损失电量
//                double xnssdl = 0.0;//性能损失电量
//                double speed = 0.0;//风速
//                content.remove(0); //去掉标题栏
//                int count = 86400 / p.getInterp(); //一天86400s  一天的条数
//                List<List<String>> coll = CollectUtil.groupListByQty(content, count);
//                for (List<String> ls : coll) {
//                    List<PowerPointData> pdl = ls.stream().map(mp -> new PowerPointData(mp.split(","), false)).collect(Collectors.toList());
//                    double lldl = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), -1); //理论发电量
//                    double dj = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 0); //待机
//                    double sdtj = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 1); //手动停机
//                    double zcfd = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 2); //正常发电
//                    double xdss = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 5);  //限电损失电量
//                    double qxjcl = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 3); //缺陷降出力损失电量
//                    double xdjcl = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 4); //限电降出力损失电量
//                    double cnsltj = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 7); //场内受累停机损失电量
//                    double cnsljx = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 9); //场内受累检修损失电量
//                    double dwsl = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 10); //电网受累损失电量
//                    double hjsl = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 11); //环境受累损失电量
//                    double gzss = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 6); //故障损失电量
//                    double tjjx = generalLoss(pdl, zsglmap.get(p.getWindturbineId()), p.getInterp(), 8); //停机检修
//
//                    llfdl += lldl;
//                    jhjxssdl += (tjjx + cnsljx);
//                    fjhjxssdl += (gzss + cnsltj);
//                    xdssdl += (xdjcl + xdss);
//                    slssdl += (dwsl + hjsl);
//                    xnssdl += (dj + sdtj + zcfd + qxjcl);
//                    rfdl += pdl.get(pdl.size() - 1).getDl();
//                    speed += pdl.stream().mapToDouble(PowerPointData::getSpeed).sum();
//                }
//                FjjxbVo vo = new FjjxbVo();
//                vo.setId(p.getWindturbineId());
//                vo.setName(p.getCode());
//                vo.setLlfdl(new BigDecimal(llfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSjfdl(new BigDecimal(rfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setJhjx(new BigDecimal(jhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFjhjx(new BigDecimal(fjhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setXd(new BigDecimal(xdssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setXn(new BigDecimal(xnssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSl(new BigDecimal(slssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSpeed(new BigDecimal(speed/content.size()).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFnlly(llfdl > 0 ? new BigDecimal(rfdl / llfdl).setScale(2, RoundingMode.FLOOR).doubleValue() : 0);
//                result.add(vo);
//            }
//            log.info("======风机榜效帮计算结束.............");
//            result.stream().sorted(Comparator.comparing(FjjxbVo::getId));
//            /** 添加标题 **/
//            val fxList = AnnotationTool.getFixedVoList(FjjxbVo.class);
//            List<TableTitle> lt = fxList.stream().map(d -> new TableTitle(d.getName(), d.getDes())).collect(Collectors.toList());
//            promise.put("title", lt);
//            promise.put("data", result);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        return promise;
//    }
//    public Map<String, Object> fiveLossCalByZSGL2(String ids) {
//        Map<String, Object> promise = null;
//        try {
//            log.info("======风机绩效榜计算开始.............");
//            promise = new HashMap<>();
//            List<FjjxbVo> result = new ArrayList<>();
//            Map<String, Map<Double, Double>> zsglmap = InitialRunner.zsllglNewMap;
//
//            List<ProEconPowerFittingAnalySis> analyses = analysisService.selectListByIds(ids);
//            if (analyses.isEmpty()){
//                log.info("======风机榜效帮计算结束，数据为空.............");
//                throw new CustomException(ResultCode.ERROR);
//            }
//
//            QueryWrapper<ProEconEquipmentInfoDay1> wrapper = new QueryWrapper<>();
//            String[] split = analyses.get(0).getTime().split("-");
//            Date start = DateUtil.parse(split[0]).toJdkDate();
//            Date end = DateUtil.parse(split[1]).toJdkDate();
//            wrapper.lambda().between(ProEconEquipmentInfoDay1::getRecordDate, start, end);
//            List<ProEconEquipmentInfoDay1> list = equipmentInfoDay1Service.list(wrapper);
//            Map<String, List<ProEconEquipmentInfoDay1>> collect = list.stream().collect(Collectors.groupingBy(ProEconEquipmentInfoDay1::getWindturbineId));
//
//            List<ProEconEquipmentInfoDay1> day1s;
//            for (ProEconPowerFittingAnalySis p : analyses) {
//                day1s = collect.get(p.getWindturbineId());
//                double llfdl = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRllfdl).sum(); //理论发电量
//                double rfdl = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRfdl).sum(); //日发电量
//                double jhjxssdl = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRjxssdl).sum();//计划检修损失电量
//                double fjhjxssdl = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRgzssdl).sum();//非计划检修电量
//                double xdssdl = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRxdtjssdl).sum()+
//                        day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRxdjclssdl).sum();//限电损失电量
//                double slssdl = 0.0;//受累损失电量
//                double xnssdl = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRxnssdl).sum();//性能损失电量
//                double speed = day1s.stream().mapToDouble(ProEconEquipmentInfoDay1::getRpjfs).average().orElse(0.0);//风速
//
//                FjjxbVo vo = new FjjxbVo();
//                vo.setId(p.getWindturbineId());
//                vo.setName(p.getCode());
//                vo.setLlfdl(new BigDecimal(llfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSjfdl(new BigDecimal(rfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setJhjx(new BigDecimal(jhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFjhjx(new BigDecimal(fjhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setXd(new BigDecimal(xdssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setXn(new BigDecimal(xnssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSl(new BigDecimal(slssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSpeed(new BigDecimal(speed).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFnlly(llfdl > 0 ? new BigDecimal(rfdl / llfdl).setScale(2, RoundingMode.FLOOR).doubleValue() : 0);
//                result.add(vo);
//            }
//            log.info("======风机榜效帮计算结束.............");
//            result.stream().sorted(Comparator.comparing(FjjxbVo::getId));
//            /** 添加标题 **/
//            List<FixedVo> fxList = AnnotationTool.getFixedVoList(FjjxbVo.class);
//            List<TableTitle> lt = fxList.stream().map(d -> new TableTitle(d.getName(), d.getDes())).collect(Collectors.toList());
//            promise.put("title", lt);
//            promise.put("data", result);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        return promise;
//    }
//    public Map<String, Object> fiveLossCalByZSGL3(String ids) {
//        Map<String, Object> promise = null;
//        try {
//            log.info("======风机绩效榜计算开始.............");
//            promise = new HashMap<>();
//            List<FjjxbVo> result = new ArrayList<>();
////            Map<String, Map<Double, Double>> zsglmap = InitialRunner.zsllglNewMap;
//
//            List<ProEconPowerFittingAnalySis> analyses = analysisService.selectListByIds(ids);
//            if (analyses.isEmpty()){
//                log.info("======风机榜效帮计算结束，数据为空.............");
//                throw new CustomException(ResultCode.ERROR);
//            }
//
//            QueryWrapper<TurbineInfoDay> wrapper = new QueryWrapper<>();
//            String[] split = analyses.get(0).getTime().split("-");
//            Date start = DateUtil.parse(split[0]).toJdkDate();
//            Date end = DateUtil.parse(split[1]).toJdkDate();
//            wrapper.lambda().between(TurbineInfoDay::getRecordDate, start, end);
//            List<TurbineInfoDay> list = turbineInfoDayService.list(wrapper);
//            Map<String, List<TurbineInfoDay>> collect = list.stream().collect(Collectors.groupingBy(TurbineInfoDay::getTurbineId));
//            Map<String, List<TurbineInfoDay>> collectcz = list.stream().collect(Collectors.groupingBy(TurbineInfoDay::getStationId));
//
//            List<TurbineInfoDay> day1s;
//            for (ProEconPowerFittingAnalySis p : analyses) {
//                FjjxbVo vo = new FjjxbVo();
//                if("A".equals(p.getWindturbineId())){
//                    day1s = collectcz.get(p.getStation());
//                    vo.setId(p.getStation());
//                    vo.setName(p.getStationcn().replaceFirst("风电场",""));
//                }else {
//                    day1s = collect.get(p.getWindturbineId());
//                    vo.setId(p.getWindturbineId());
//                    vo.setName(p.getCode());
//                }
//                double llfdl = day1s.stream().mapToDouble(TurbineInfoDay::getLlfdl).sum(); //理论发电量
//                double rfdl = day1s.stream().mapToDouble(TurbineInfoDay::getRfdl).sum(); //日发电量
//                double jhjxssdl = day1s.stream().mapToDouble(TurbineInfoDay::getJhjxss).sum();//计划检修损失电量
//                double fjhjxssdl = day1s.stream().mapToDouble(TurbineInfoDay::getFjhjxss).sum();//非计划检修电量
//                double xdssdl = day1s.stream().mapToDouble(TurbineInfoDay::getXdss).sum();//限电损失电量
//                double slssdl = 0.0;//受累损失电量
//                double xnssdl = day1s.stream().mapToDouble(TurbineInfoDay::getXnss).sum();//性能损失电量
//                double speed = day1s.stream().mapToDouble(TurbineInfoDay::getPjfs).average().orElse(0.0);//风速
//
//                llfdl = llfdl/1000;
//                rfdl = rfdl/1000;
//                jhjxssdl = jhjxssdl/1000;
//                fjhjxssdl = fjhjxssdl/1000;
//                xdssdl = xdssdl/1000;
//                xnssdl = xnssdl/1000;
//
//                vo.setLlfdl(new BigDecimal(llfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSjfdl(new BigDecimal(rfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setJhjx(new BigDecimal(jhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFjhjx(new BigDecimal(fjhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setXd(new BigDecimal(xdssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setXn(new BigDecimal(xnssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSl(new BigDecimal(slssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setSpeed(new BigDecimal(speed).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFnlly(llfdl > 0 ? new BigDecimal(rfdl / llfdl).setScale(2, RoundingMode.FLOOR).doubleValue() : 0);
//                result.add(vo);
//            }
//            log.info("======风机榜效帮计算结束.............");
//            result.stream().sorted(Comparator.comparing(FjjxbVo::getId));
//            /** 添加标题 **/
//            List<FixedVo> fxList = AnnotationTool.getFixedVoList(FjjxbVo.class);
//            List<TableTitle> lt = fxList.stream().map(d -> new TableTitle(d.getName(), d.getDes())).collect(Collectors.toList());
//            promise.put("title", lt);
//            promise.put("data", result);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        return promise;
//    }

    public Map<String, Object> lossPowerAnalysis(String wpids,String beginDate,String endDate) {
        Map<String, Object> promise = null;
        try{
            promise = new HashMap<>();
            List<LossPowerVo> result = new ArrayList<>();

            QueryWrapper<ProEconEquipmentInfoDay1> qw=new QueryWrapper<>();
            QueryWrapper<ProBasicEquipment> qw2=new QueryWrapper<>();

            qw.ge("record_date", DateUtils.parseDate(beginDate)).le("record_date", DateUtils.parseDate(endDate));
            if (StringUtils.isNotEmpty(wpids)) {
                List<String> wpList = Arrays.asList(wpids.split(","));
                qw.in("windturbine_id", wpList);
                qw2.in("id", wpList);
            }

            //风机表
            List<ProBasicEquipment> equipmentList = equipmentService.list(qw2);
            //风机五损表
            List<ProEconEquipmentInfoDay1> equipmentListday1 = equipmentInfoDay1Service.list(qw);



            for(ProBasicEquipment p : equipmentList) {

                List<ProEconEquipmentInfoDay1> collect = equipmentListday1.stream().filter(e -> e.getWindturbineId().equals(p.getId())).collect(Collectors.toList());
                System.out.print("风机表>>>>>" + p);
                LossPowerVo vo = new LossPowerVo();

                vo.setId(p.getId());
                vo.setName(p.getNemCode());


                double llfdl = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRllfdl).sum(); //理论发电量
                double rfdl = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRfdl).sum(); //日发电量
                double jhjxssdl = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRjxssdl).sum();//计划检修损失电量
//                double fjhjxssdl = equipmentListday1.stream().mapToDouble(ProEconEquipmentInfoDay1::getFjhjxss).sum();//非计划检修电量
                double xdssdl = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRxdtjssdl).sum();//限电损失电量
                double slssdl = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRcwsldwssdl).sum();//受累损失电量
                double xnssdl = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRxnssdl).sum();//性能损失电量
                double speed = collect.stream().mapToDouble(ProEconEquipmentInfoDay1::getRpjfs).average().orElse(0.0);//风速

                llfdl = llfdl/1000;
                rfdl = rfdl/1000;
                jhjxssdl = jhjxssdl/1000;
//                fjhjxssdl = fjhjxssdl/1000;
                xdssdl = xdssdl/1000;
                slssdl = slssdl/1000;
                xnssdl = xnssdl/1000;


                vo.setLlfdl(new BigDecimal(llfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setSjfdl(new BigDecimal(rfdl).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setJhjx(new BigDecimal(jhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
//                vo.setFjhjx(new BigDecimal(fjhjxssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setXd(new BigDecimal(xdssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setXn(new BigDecimal(xnssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setSl(new BigDecimal(slssdl).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setSpeed(new BigDecimal(speed).setScale(2, RoundingMode.FLOOR).doubleValue());
                vo.setFnlly(llfdl > 0 ? new BigDecimal(rfdl / llfdl).setScale(2, RoundingMode.FLOOR).doubleValue() : 0);
                result.add(vo);
            }

            result.stream().sorted(Comparator.comparing(LossPowerVo::getId));

            promise.put("fjb", equipmentList);
            promise.put("fjwsb", equipmentListday1);
            promise.put("data", result);

//            for (int i = 0; i < equipmentList.length; i++) {
//                List<ProEconEquipmentInfoDay1> list = equipmentInfoDay1Service.list(qw.lambda().eq(ProEconEquipmentInfoDay1::getWindturbineId,ids[i]));
//                System.out.println("equipmentList>>>>>" + equipmentList);
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return promise;
    }
}
