package com.ho.business.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.*;
import com.ho.business.feignclient.TdFeignClient;
import com.ho.business.mapper.EarningsCalculateMapper;
import com.ho.business.mapper.EarningsCalculateMpptMapper;
import com.ho.business.service.*;
import com.ho.business.util.QueuesUtil;
import com.ho.business.vo.req.bigScreen.CommonBigScreenReq;
import com.ho.business.vo.req.device.DeviceTypeQuery;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.InverterResp.PowerGenerateRespVO;
import com.ho.business.vo.resp.profit.DayProfitType;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.vo.req.StationHomeRespVo;
import com.ho.td.api.entity.query.TdBaseTimeQuery;
import jodd.util.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EarningsCalculateMpptServiceImpl implements EarningsCalculateMpptService {


    @Autowired
    EarningsCalculateMpptMapper earningsCalculateMpptMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private ModelDeviceService modelDeviceService;

    @Autowired
    private DeviceTypeConfigService deviceTypeConfigService;

    public static final String TOTAL_RELEASE = "totalRelease";

    @Autowired
    RedisService redisService;

    @Autowired
    EarningsCalculateMapper earningsCalculateMapper;

    @Autowired
    private TdFeignClient tdFeignClient;
    @Override
    public int deleteByDay(String day, List<Integer> typeList) {
        int i = earningsCalculateMpptMapper.deleteByDay(day, typeList);
        return i;
    }

    /**
     * 计算光伏收益
     * @return
     */
    private List<EarningsCalculateMppt> countMpptIncome(Station station,String beginTime){
        List<EarningsCalculateMppt> list =new ArrayList<>();
        Integer stationId = station.getId();
        // 总发
        List<DeviceRespVO> deviceRespVOS = deviceService.getListByDeviceType(stationId, DeviceTypeConstant.MPPT);
        if (deviceRespVOS.isEmpty()) {
            deviceRespVOS = deviceService.getListByFuzzyDeviceType(stationId, DeviceTypeConstant.MPPT);
        }
        for (DeviceRespVO vo : deviceRespVOS) {
            // 查询光伏Mppt 放电量关联字段 如果没关联，则不计算
            List<ModelDeviceColComp> deviceCp = modelDeviceService.getCompListByType("device", vo.getDeviceType(), TOTAL_RELEASE);
            if(deviceCp == null ){
                break;
            }
            // 查询设备模型，没查询到则返回，不计算
            DeviceTypeQuery deviceTypeQuery = new DeviceTypeQuery();
            deviceTypeQuery.setGroupId(station.getGroupId());
            deviceTypeQuery.setDeviceType(deviceCp.get(0).getDeviceType());
            List<DeviceTypeConfig> deviceTypeConfigs = deviceTypeConfigService.queryListByCondition(deviceTypeQuery);
            if (deviceTypeConfigs == null){
                break;
            }
            //开始计算
            //1:组装时序数据库查询参数
            DateTime beginDate = DateUtil.beginOfDay(DateUtil.parse(beginTime));
            DateTime endDate = DateUtil.endOfDay(beginDate);
            TdBaseTimeQuery tdBaseQuery = new TdBaseTimeQuery();
            tdBaseQuery.setBeginTime(beginDate.toMsStr());
            tdBaseQuery.setEndTime(endDate.toMsStr());
            tdBaseQuery.setTime("1m");
            tdBaseQuery.setStationId(station.getId());
            tdBaseQuery.setGroupId(station.getGroupId());
            tdBaseQuery.setModelName((deviceTypeConfigs.get(0)).getModelName());
            tdBaseQuery.setCol(deviceCp.get(0).getDeviceCol());
            tdBaseQuery.setSrcId(vo.getSrcId());
            // 查询设备时序数据，如果为空则不计算
            DataResult<List<StationHomeRespVo>> listDataResult = tdFeignClient.queryPointTableList(tdBaseQuery);
            List<StationHomeRespVo> datas = listDataResult.getData();
            if(datas ==null){
                break;
            }
            // 获取电价分时段计算收益
            List<EarningsCalculateSub> elecTemplateSubs = earningsCalculateMapper.queryElecTemplateSubByStationId(station.getId(), 0, beginTime,2);
            BigDecimal lastelec = BigDecimal.ZERO;
            BigDecimal elec = BigDecimal.ZERO;
            int num = 0 ;
            for (EarningsCalculateSub sub : elecTemplateSubs ){
                String earnBegin = sub.getBeginTime();
                String earnEnd = sub.getEndTime();
                DateTime earnBeginDate = DateUtil.parse(beginTime + " " + earnBegin + ":00");
                DateTime earnEndate = DateUtil.parse(beginTime + " " + earnEnd + ":59");
                List<StationHomeRespVo> subData = datas.stream().filter(i->DateUtil.isIn(DateUtil.parse(i.getDate()),earnBeginDate,earnEndate)).collect(Collectors.toList());
                if(subData.size()>0){
                    if(num==0){
                        elec = subData.get(subData.size()-1).getDigital().subtract(subData.get(0).getDigital());
                    }else {
                        elec = subData.get(subData.size() - 1).getDigital().subtract(lastelec);
                    }
                    lastelec = subData.get(subData.size()-1).getDigital();
                    num++;
                    EarningsCalculateMppt earn =new EarningsCalculateMppt();
                    earn.setDay(beginTime);
                    earn.setGroupId(station.getGroupId());
                    earn.setStationId(station.getId());
                    earn.setSrcId(tdBaseQuery.getSrcId());
                    earn.setPrice(sub.getPrice());
                    earn.setRateType(sub.getType());
                    earn.setType(1);
                    earn.setCreateTime(new Date());
                    BigDecimal discount = sub.getDiscount() == null ? BigDecimal.ONE : sub.getDiscount();
                    earn.setTotal(BigDecimal.ZERO);
                    earn.setElec(elec);
                    earn.setDiscount(discount);
                    earn.setDigital(new BigDecimal(String.format("%.4f",elec.multiply(sub.getPrice()))));
                    list.add(earn);
                }
            }
        }
        return list;
    }

    @Override
    public void todayMpptIncome(List<Station> stations,String beginTime){
        if(stations != null && stations.size() > 0){
            for (Station station:stations){
                List<EarningsCalculateMppt> list = countMpptIncome(station,beginTime);
                // 缓存今日收益
                if(list.size()>0){
                    String key = RedisKeyConstant.PV.STATION_PV_TODAY_PROFIT + station.getId();
                    BigDecimal todayIncone = list.stream().map(EarningsCalculateMppt::getDigital).reduce(BigDecimal.ZERO,BigDecimal::add);
                    redisService.set(key, todayIncone);
                }
            }
        }
    }

    @Override
    public List<PowerGenerateRespVO> countPvIncome(Integer stationId, String beginTime, String endTime) {
        return earningsCalculateMpptMapper.countPvIncome(stationId,beginTime,endTime);
    }

    @Override
    public BigDecimal countAllPvIncome(Integer stationId,String beginTime, String endTime) {
        BigDecimal data = earningsCalculateMpptMapper.countAllPvIncome(stationId,beginTime,endTime);
        return data==null?BigDecimal.ZERO:data;
    }

    @Override
    public List<DayProfitType> getProfit(String begin, String end, Integer groupId) {
        return earningsCalculateMpptMapper.getProfit(begin, end, groupId);
    }

    @Override
    public Date getFirstTime() {
        String day = earningsCalculateMpptMapper.getFirstTime();
        DateTime date = null;
        if(day!=null){
            date = DateUtil.parse(day, CommonConstant.DATE_YMD);
        }
        return date;
    }

    @Override
    public List<DayProfitType> getEarningsByParam(CommonBigScreenReq req) {
        return earningsCalculateMpptMapper.getEarningsByParam(req);
    }

    @Override
    public void allMpptIncome(List<Station> stations,String beginTime) {
        if(stations != null && stations.size() > 0){
            for (Station station:stations){
                List<EarningsCalculateMppt> list = countMpptIncome(station,beginTime);
                // 数据插入
                if(list.size()>0){
                    int a = this.earningsCalculateMpptMapper.insertBatch(list);
                    System.err.println("修改的行数:" + a);
                }
            }
        }
    }
}
