package com.jiayue.ipfcst.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.jiayue.ipfcst.common.data.entity.InverterStatusData;
import com.jiayue.ipfcst.common.data.repository.InverterStatusDataRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 逆变器数据信息业务层
 *
 * @author yh
 * @version 1.0
 * @since 2019/8/5 16:02
 */
@Service
public class InverterStatusDataService {

    private final InverterStatusDataRepository inverterStatusDataRepository;
    @Autowired
    public InverterStatusDataService(InverterStatusDataRepository inverterStatusDataRepository){
        this.inverterStatusDataRepository = inverterStatusDataRepository;
    }


    /**
     * 根据时间和编号 分页查询 逆变器数据 yh
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param no        设备编号
     * @param page      页码
     * @param size      条数
     * @param timeSortOrder 排序
     * @param noSortOrder 排序
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Map<String, Object> findByTimeBetweenAndNoForPaging(Date startTime, Date endTime,
                                                          Integer page, Integer size,
                                                          Integer[] no, String timeSortOrder,String noSortOrder)  {
        Map<String, Object> map = new HashMap<>();
        List<Sort.Order> orders = new ArrayList<Sort.Order>();

        if (timeSortOrder.indexOf("asc") >= 0) {
          orders.add(new Sort.Order(Sort.Direction.ASC, "time"));
        } else {
          orders.add(new Sort.Order(Sort.Direction.DESC, "time"));
        }

        if (noSortOrder.indexOf("asc") >= 0) {
          orders.add(new Sort.Order(Sort.Direction.ASC, "equipmentNo"));
        } else {
          orders.add(new Sort.Order(Sort.Direction.DESC, "equipmentNo"));
        }

        Sort sort = Sort.by(orders);
        Date newTime = DateUtil.parse("2023-04-01","yyyy-MM-dd");

        Specification<InverterStatusData> specification = this.specificationFindByTimeAndNo(DateUtil.beginOfDay(newTime), DateUtil.endOfDay(newTime),no);
        Pageable pageable = PageRequest.of(page - 1, size, sort);
        Page inverterStatusDatas = inverterStatusDataRepository.findAll(specification,pageable);
        List<InverterStatusData> datas = new ArrayList<>();
        datas = inverterStatusDatas.getContent();
        Calendar calendar = Calendar.getInstance();
        // 修改日期
        datas.forEach(data -> {
          calendar.setTime(data.getTime());
          // 设置新的年月日
          calendar.set(Calendar.YEAR, DateUtil.year(startTime));
          calendar.set(Calendar.MONTH, DateUtil.month(startTime)); // 注意月份从0开始，即0对应1月
          calendar.set(Calendar.DAY_OF_MONTH, DateUtil.dayOfMonth(startTime));
          data.setTime(calendar.getTime());
        });

        this.defaultReplace(datas);
        map.put("content", datas);
        map.put("count", inverterStatusDatas.getTotalElements());
        return map;
    }

    /**
     * 根据时间和编号 分页查询条件 yh
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param no       设备编号
     * @return 过滤条件
     */
    Specification<InverterStatusData> specificationFindByTimeAndNo(final Date startTime, final Date endTime,final Integer[] no) {
        return (Specification<InverterStatusData>) (root, criteriaQuery, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (startTime!=null) {
                //大于或等于传入时间
                predicates.add(cb.greaterThanOrEqualTo(root.get("time").as(Date.class), startTime));
            }
            if (endTime!=null) {
                //小于传入时间
                predicates.add(cb.lessThan(root.get("time").as(Date.class), endTime));
            }

//            if(no!=null){
//              predicates.add(cb.equal(root.get("equipmentNo").as(Integer.class), no));
//            }
            if (no!=null) {
              List<Predicate> list = new ArrayList<Predicate>();
              CriteriaBuilder.In<Integer> in = cb.in(root.get("equipmentNo"));
              for (int i = 0; i<no.length;i++) {
                in.value(no[i]);
              }
              predicates.add(in);
            }

            //添加排序的功能
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));

        };
    }




    /**
     * 根据时间和编号 分页查询 逆变器数据 yh
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param page      页码
     * @param size      条数
     * @param timeSortOrder  时间排序
     * @param noSortOrder  设备排序
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Map<String, Object> findByTimeBetweenForPaging(Date startTime, Date endTime,
                                                               Integer page, Integer size,
                                                                String timeSortOrder,String noSortOrder) {
        Map<String, Object> map = new HashMap<>();

        List<Sort.Order> orders = new ArrayList<Sort.Order>();

        if (timeSortOrder.indexOf("asc") >= 0) {
            orders.add(new Sort.Order(Sort.Direction.ASC, "time"));
        } else {
            orders.add(new Sort.Order(Sort.Direction.DESC, "time"));
        }

        if (noSortOrder.indexOf("asc") >= 0) {
            orders.add(new Sort.Order(Sort.Direction.ASC, "equipmentNo"));
        } else {
            orders.add(new Sort.Order(Sort.Direction.DESC, "equipmentNo"));
        }

        Sort sort = Sort.by(orders);
        Date newTime = DateUtil.parse("2023-04-01","yyyy-MM-dd");
        Specification<InverterStatusData> specification = this.specificationFindByTime(DateUtil.beginOfDay(newTime), DateUtil.endOfDay(newTime));
        Pageable pageable = PageRequest.of(page - 1, size, sort); //页码：前端从1开始，jpa从0开始，做个转换
        Page inverterStatusDatas = inverterStatusDataRepository.findAll(specification,pageable);
        List<InverterStatusData> datas = new ArrayList<>();
        datas = inverterStatusDatas.getContent();
        Calendar calendar = Calendar.getInstance();
        // 修改日期
        datas.forEach(data -> {
          calendar.setTime(data.getTime());
          // 设置新的年月日
          calendar.set(Calendar.YEAR, DateUtil.year(startTime));
          calendar.set(Calendar.MONTH, DateUtil.month(startTime)); // 注意月份从0开始，即0对应1月
          calendar.set(Calendar.DAY_OF_MONTH, DateUtil.dayOfMonth(startTime));
          data.setTime(calendar.getTime());
        });
        this.defaultReplace(datas);
        map.put("content", datas);// 结果集
        map.put("count", inverterStatusDatas.getTotalElements());// 总记录数
        return map;
    }

    /**
     * 根据时间 分页查询条件 yh
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 过滤条件
     */
    Specification<InverterStatusData> specificationFindByTime(final Date startTime, final Date endTime) {
        return (Specification<InverterStatusData>) (root, criteriaQuery, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (startTime!=null) {
                //大于或等于传入时间
                predicates.add(cb.greaterThanOrEqualTo(root.get("time").as(Date.class), startTime));
            }
            if (endTime!=null) {
                //小于传入时间
                predicates.add(cb.lessThan(root.get("time").as(Date.class), endTime));
            }
            //添加排序的功能
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));

        };
    }

    /**
     *  对集合进行 -99替换null操作，主要用于图标展示空值
     *
     * @param datas  需要替换集合
     */
    public void defaultReplace(List<InverterStatusData> datas){
      BigDecimal nullBig =  new BigDecimal(-99);
      for(InverterStatusData i :datas){
        if(i.getActivePower().compareTo(nullBig)==0){
          i.setActivePower(null);
        }
        if(i.getReactivePower().compareTo(nullBig)==0){
          i.setReactivePower(null);
        }
        if(i.getPowerFactor().compareTo(nullBig)==0){
          i.setPowerFactor(null);
        }
        if(i.getVoltage().compareTo(nullBig)==0){
          i.setVoltage(null);
        }
        if(i.getElectricalCurrent().compareTo(nullBig)==0){
          i.setElectricalCurrent(null);
        }
        if(i.getDayElectricQuantity().compareTo(nullBig)==0){
          i.setDayElectricQuantity(null);
        }
        if(i.getDayGridConnectedHours().compareTo(nullBig)==0){
          i.setDayGridConnectedHours(null);
        }
      }

    }


  public List<InverterStatusData> findByTimeBetweenAndNo(Long startTime, Long endTime, Integer[] no){
    List<InverterStatusData> inverterStatusData = inverterStatusDataRepository.findByTimeBetweenAndEquipmentNoIn(new Date(startTime), new Date(endTime), no);

    return inverterStatusData;
  }

}
