package com.yuchen.saas.park.service.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yuchen.saas.park.api.dto.energy.PowerAddDTO;
import com.yuchen.saas.park.api.entity.device.PmgBatSmartEquipment;
import com.yuchen.saas.park.api.entity.park.PmgBatPowerData;
import com.yuchen.saas.park.api.vo.park.energy.EnergyStatisticVO;
import com.yuchen.saas.park.api.vo.park.energy.SevenTrendVO;
import com.yuchen.saas.park.api.vo.park.energy.TotalRankingVO;
import com.yuchen.saas.park.service.mapper.PmgBatPowerDataMapper;
import com.yuchen.saas.park.service.service.PmgBatPowerDataService;
import com.yuchen.saas.park.service.service.PmgBatSmartEquipmentService;
import com.yuchen.saas.park.service.util.DateTimeUtils;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * @author 颜艺波
 * @date 2022/6/28 16:59
 * @Description
 */
@Service
public class PmgBatPowerDataServiceImpl extends BaseServiceImpl<PmgBatPowerDataMapper, PmgBatPowerData>
        implements PmgBatPowerDataService {

    @Autowired
    PmgBatSmartEquipmentService equipmentService;

    @Override
    public Boolean add(PowerAddDTO powerAddDTO) {
        PmgBatPowerData pmgBatPowerData = new PmgBatPowerData();
        BeanUtils.copyProperties(powerAddDTO, pmgBatPowerData);
        // 园区id通过设备查询数据库获取
        PmgBatSmartEquipment equipment = equipmentService.getOne(Wrappers.<PmgBatSmartEquipment>lambdaQuery()
                .select(PmgBatSmartEquipment::getParkId)
                .eq(PmgBatSmartEquipment::getProductKey, powerAddDTO.getProductKey())
                .eq(PmgBatSmartEquipment::getDeviceName, powerAddDTO.getDeviceName()));
        if (equipment != null) {
            pmgBatPowerData.setParkId(equipment.getParkId());
            pmgBatPowerData.setTenantId(equipment.getTenantId());
        } else {
            pmgBatPowerData.setParkId(34325345354L);
        }
        this.save(pmgBatPowerData);
        return true;
    }

    @Override
    public EnergyStatisticVO energyStatistic(Long parkId) {
        EnergyStatisticVO waterStatisticVO = new EnergyStatisticVO();
        waterStatisticVO.setToday(useToday(parkId));
        waterStatisticVO.setMonth(useMonth(parkId));
        waterStatisticVO.setLastMonth(useLastMonth(parkId));
        waterStatisticVO.setTotal(useTotal(parkId));
        return waterStatisticVO;
    }

    @Override
    public List<SevenTrendVO> sevenTrend(Long parkId) {
        List<SevenTrendVO> sevenTrendVOList = new LinkedList<>();
        List<PmgBatPowerData> deviceList = getPowerDevice(parkId);
        for (int i = 0; i < 7; i++) {
            SevenTrendVO sevenTrendVO = new SevenTrendVO();
            Long beginTimestamp = DateTimeUtils.beginTimestampBefore(i);
            Long endTimestamp = DateTimeUtils.endTimestampBefore(i);
            sevenTrendVO.setDate(new Date(beginTimestamp));
            sevenTrendVO.setValue(useBetween(parkId, beginTimestamp, endTimestamp, deviceList));
            sevenTrendVOList.add(sevenTrendVO);
        }
        return sevenTrendVOList;
    }

    @Override
    public List<TotalRankingVO> totalRanking(Long parkId) {
        return this.baseMapper.totalRanking(parkId);
    }

    @Override
    public String useToday(Long parkId) {
        List<PmgBatPowerData> deviceList = getPowerDevice(parkId);
        return useBetween(parkId, DateTimeUtils.beginTimestampToday(), System.currentTimeMillis(), deviceList);
    }

    @Override
    public String useMonth(Long parkId) {
        List<PmgBatPowerData> deviceList = getPowerDevice(parkId);
        return useBetween(parkId, DateTimeUtils.beginTimestampMonth(), System.currentTimeMillis(), deviceList);
    }

    @Override
    public String useLastMonth(Long parkId) {
        List<PmgBatPowerData> deviceList = getPowerDevice(parkId);
        return useBetween(parkId, DateTimeUtils.beginTimestampLastMonth(), DateTimeUtils.endTimestampLastMonth(), deviceList);
    }

    @Override
    public String useTotal(Long parkId) {
        List<PmgBatPowerData> deviceList = getPowerDevice(parkId);
        BigDecimal total = BigDecimal.ZERO;
        for (PmgBatPowerData e : deviceList) {
            String eachTotal = useLast(parkId, e.getProductKey(), e.getDeviceName(), System.currentTimeMillis());
            total = total.add(new BigDecimal(eachTotal));
        }
        return total.setScale(2, RoundingMode.HALF_UP).toString();
    }


    private String useBetween(Long parkId, Long beginTimestamp, Long endTimestamp, List<PmgBatPowerData> deviceList) {
        BigDecimal total = BigDecimal.ZERO;
        for (PmgBatPowerData e : deviceList) {
            String beginData = useLast(parkId, e.getProductKey(), e.getDeviceName(), beginTimestamp);
            String endData = useLast(parkId, e.getProductKey(), e.getDeviceName(), endTimestamp);
            BigDecimal beginDecimal = new BigDecimal(beginData);
            BigDecimal endDecimal = new BigDecimal(endData);
            total = total.add(endDecimal).subtract(beginDecimal);
        }
        return total.setScale(2, RoundingMode.HALF_UP).toString();
    }

    private String useLast(Long parkId, String productKey, String deviceName, Long timestamp) {
        PmgBatPowerData data = this.getOne(Wrappers.<PmgBatPowerData>lambdaQuery()
                .eq(PmgBatPowerData::getParkId, parkId)
                .eq(PmgBatPowerData::getProductKey, productKey)
                .eq(PmgBatPowerData::getDeviceName, deviceName)
                .le(PmgBatPowerData::getReportTime, timestamp)
                .orderByDesc(PmgBatPowerData::getReportTime)
                .last("limit 1"));
        if (data == null || data.getValue() == null) {
            return "0.00";
        }
        return data.getValue();
    }

    /**
     * 获取水表
     * @param parkId
     * @return
     */
    private List<PmgBatPowerData> getPowerDevice(Long parkId) {
        List<PmgBatPowerData> deviceList = this.list(Wrappers.<PmgBatPowerData>lambdaQuery()
                .select(PmgBatPowerData::getProductKey, PmgBatPowerData::getDeviceName)
                .eq(PmgBatPowerData::getParkId, parkId)
                .groupBy(PmgBatPowerData::getProductKey, PmgBatPowerData::getDeviceName));

        return deviceList;
    }
}
