package com.cpp.web.service.overhaulplan.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cpp.web.domain.BaseForecastCloudEntity;
import com.cpp.web.domain.BaseForecastEntity;
import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
import com.cpp.web.domain.overhaulplan.OverhaulPlan;
import com.cpp.web.domain.overhaulplan.OverhaulPlanRecords;
import com.cpp.web.domain.station.ElectricField;
import com.cpp.web.mapper.overhaulplan.OverhaulPlanMapper;
import com.cpp.web.service.overhaulplan.OverhaulPlanRecordsService;

import com.cpp.web.service.overhaulplan.OverhaulPlanService;
import com.cpp.web.service.station.ElectricFieldService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

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

/**
 * cpp_overhaul_plan
 *
 * @author fxy
 * @date 2024-10-08 9:47:33
 */
@Service
@RequiredArgsConstructor
public class OverhaulPlanServiceImpl extends ServiceImpl<OverhaulPlanMapper, OverhaulPlan> implements OverhaulPlanService {

    private final OverhaulPlanMapper overhaulPlanMapper;

    private final ElectricFieldService electricFieldService;

    private final OverhaulPlanRecordsService overhaulPlanRecordsService;

    /**
     * 查询所有检修计划
     *
     * @return
     */
    @Override
    public QueryWrapper<OverhaulPlan> getList() {
        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();
        return wrapper;
    }

    /**
     * 根据场站编号查询检修计划信息
     *
     * @param stationCode
     * @return
     */
    @Override
    public QueryWrapper<OverhaulPlan> getByStationCode(String stationCode, Integer status) {
        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();
        if (null != status) {
            if (!"".equals(stationCode)) {
                wrapper.eq("station_code", stationCode);
                wrapper.eq("status", status);
            }
        } else {
            if (!"".equals(stationCode)) {
                wrapper.eq("station_code", stationCode);
            }
        }
        return wrapper;
    }

    @Override
    public List<OverhaulPlan> findByStationCode(String stationCode) {
        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();
        if (null != stationCode && !"".equals(stationCode)) {
            wrapper.eq("station_code", stationCode);
        }
        wrapper.eq("status", 1);
        return list(wrapper);
    }

    @Override
    public List<OverhaulPlan> findByStationCodeAndTimeBetween(Date startTime, Date endTime, String stationCode) {
        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();
        if (startTime != null && !endTime.equals("") && endTime != null && !endTime.equals("")) {
            wrapper.and(a -> a.or(w -> w.isNull("end_time").le("start_time", endTime))
                    .or(w -> w.isNotNull("end_time").le("start_time", endTime).gt("end_time", startTime))
                    .or(w -> w.isNotNull("end_time").le("start_time", endTime).gt("start_time", startTime))
                    .or(w -> w.isNotNull("end_time").le("end_time", endTime).gt("start_time", endTime))
                    .or(w -> w.isNotNull("end_time").le("start_time", startTime).gt("end_time", endTime)));
        }
        if (null != stationCode && !"".equals(stationCode)) {
            wrapper.eq("station_code", stationCode);
        }
        wrapper.eq("status", 1);
        return overhaulPlanMapper.selectList(wrapper);
    }

    /**
     * 返回修正后数据
     *
     * @param list
     * @return
     */
    @Override
    public List getCorrectionData(List<BaseForecastCloudEntity> list, String fileType, String fileName, String stationCode) {

        BigDecimal capacity;
        List<BaseForecastEntity> resultList = new ArrayList<>();
        List<OverhaulPlanRecords> overhaulPlanRecordsList = new ArrayList<>();
        Date startTime;
        Date endTime;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取场站装机容量
        ElectricField electricField = electricFieldService.findByStationCode(stationCode);
        if (null != electricField) {
            capacity = electricField.getCapacity();
        } else {
            capacity = BigDecimal.ZERO;
        }
        if (null != list && list.size() > 0) {
            list.stream().sorted(Comparator.comparing(BaseForecastCloudEntity::getTime));
            startTime = list.get(0).getTime();
            endTime = list.get(list.size() - 1).getTime();

            // 查询检修计划
            List<OverhaulPlan> overhaulPlanList = findByStationCodeAndTimeBetween(startTime, endTime, stationCode);

            List<PlanDto> planDtos = new ArrayList<>();

            for (OverhaulPlan overhaulPlan : overhaulPlanList) {
                PlanDto planDto;
                if (overhaulPlan.getStartTime().before(startTime) && overhaulPlan.getEndTime().after(endTime)) {
                    planDto = new PlanDto(startTime, endTime, overhaulPlan, capacity);
                } else if (overhaulPlan.getStartTime().before(startTime)) {
                    planDto = new PlanDto(startTime, overhaulPlan.getEndTime(), overhaulPlan, capacity);
                } else if (overhaulPlan.getEndTime().after(endTime)) {
                    planDto = new PlanDto(overhaulPlan.getStartTime(), endTime, overhaulPlan, capacity);
                } else {
                    planDto = new PlanDto(overhaulPlan.getStartTime(), overhaulPlan.getEndTime(), overhaulPlan, capacity);
                }
                planDtos.add(planDto);
                overhaulPlanRecordsList.add(new OverhaulPlanRecords(overhaulPlan.getId(), list.get(0).getForecastModel(), FileTypeEnum.valueOf(fileType), fileName + "【数据使用时间段：" + simpleDateFormat.format(planDto.getStartTime()) + "~" + simpleDateFormat.format(planDto.getEndTime()) + "】", stationCode));
            }

            for (BaseForecastEntity baseForecastEntity : list) {
                List<PlanDto> planDtoList = planDtos.stream().filter(l -> l.isIn(baseForecastEntity)).collect(Collectors.toList());
                if (planDtoList.size() > 0) {
                    PlanDto planDto = planDtoList.get(0);
                    baseForecastEntity.setCapacity(capacity);
                    baseForecastEntity.setOpenCapacity(capacity.subtract(planDto.getOverhaulPlan().getOverhaulCapacity()));
                    baseForecastEntity.setFpValue(baseForecastEntity.getFpValue().subtract(baseForecastEntity.getFpValue().multiply(planDto.getRadio())));
                } else {
                    baseForecastEntity.setOpenCapacity(capacity);
                    baseForecastEntity.setCapacity(capacity);

                }
            }
        }
        overhaulPlanRecordsService.saveBatch(overhaulPlanRecordsList);
        return list;
    }


    /**
     *  保存
     * @param stationCode
     * @param overhaulPlanList
     */
    @Override
    public void save(String stationCode, List<OverhaulPlan> overhaulPlanList) {

        List<OverhaulPlan> useOverPlanList = getUsePlan(stationCode);
        // 将执行中的检修计划置为废弃
        useOverPlanList.forEach(plan -> plan.setStatus(2));
        saveOrUpdateBatch(useOverPlanList);
        saveBatch(overhaulPlanList);
    }

    @Override
    public List<OverhaulPlan> findById(Long id) {
        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();
        if (null != id && !"".equals(id)){
            wrapper.eq("id",id);
        }
        return list(wrapper);
    }


    @Override
    public List<OverhaulPlan> findByAllId(List<Long> idList) {
        List<OverhaulPlan> overhaulPlanList = new ArrayList<>();

        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();
        for (Long l : idList) {
            if (null != l && !"".equals(l)){
                wrapper.eq("id",l);
            }
            overhaulPlanList.add(overhaulPlanMapper.selectOne(wrapper));
        }

        return overhaulPlanList;
    }


    /**
     *  获取使用中的检修计划
     * @param stationCode
     * @return
     */
    public List<OverhaulPlan> getUsePlan(String stationCode) {

        QueryWrapper<OverhaulPlan> wrapper = new QueryWrapper<>();

        if (!"".equals(stationCode) && null != stationCode) {
            wrapper.eq("station_code", stationCode);
            wrapper.eq("status", 1);
            wrapper.le("end_time", new Date());
        }
        return list(wrapper);
    }


    @Data
    public class PlanDto {
        private Date startTime;
        private Date endTime;
        private BigDecimal radio;
        private OverhaulPlan overhaulPlan;

        public Boolean isIn(BaseForecastEntity baseForecastEntity) {
            if (baseForecastEntity.getTime().getTime() >= startTime.getTime() && baseForecastEntity.getTime().getTime() < endTime.getTime()) {
                return true;
            }
            return false;
        }

        public PlanDto(Date startTime, Date endTime, OverhaulPlan overhaulPlan, BigDecimal capacity) {
            this.startTime = startTime;
            this.endTime = endTime;
            this.overhaulPlan = overhaulPlan;
            this.radio = BigDecimal.ONE.subtract(overhaulPlan.getOverhaulCapacity().divide(capacity, 2, RoundingMode.HALF_UP));
        }
    }

}
