package com.zcxk.rmcp.web.service.impl;

import com.zcxk.core.common.exception.BusinessException;
import com.zcxk.core.common.pojo.PageResult;
import com.zcxk.core.oauth2.util.UserUtil;
import com.zcxk.core.utils.BigDecimalUtils;
import com.zcxk.core.utils.CacheClient;
import com.zcxk.core.utils.DateUtil;
import com.zcxk.core.utils.util.RedisUtil;
import com.zcxk.rmcp.api.dto.meterreadrecord.MeterReadRecordDeviceDto;
import com.zcxk.rmcp.api.dto.meterreadrecord.MeterReadRecordDto;
import com.zcxk.rmcp.api.dto.meterreadrecord.MeterReadRecordUpdateDto;
import com.zcxk.rmcp.api.dto.readmeter.MeterData;
import com.zcxk.rmcp.api.enums.ReadStatusEnum;
import com.zcxk.rmcp.api.enums.RmcpErrorEnum;
import com.zcxk.rmcp.api.vo.MeterReadRecordVo;
import com.zcxk.rmcp.core.dao.mongo.MeterReadRecordDao;
import com.zcxk.rmcp.core.mongo.MeterReadRecord;
import com.zcxk.rmcp.web.service.MeterReadRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;

/**
 * @author Andy
 * @version V1.0
 * @description: 抄表记录
 * @date 2021/7/22
 **/
@Service
public class MeterReadRecordServiceImpl implements MeterReadRecordService {


    @Autowired
    private CacheClient cacheClient;

    /**
     * 水表最后数据缓存前缀
     */
    public static final String PREFIX_CACHE_FLAG = "last-meter-data:";

    @Resource
    private MeterReadRecordDao meterReadRecordDao;

    @Override
    public void saveMeterReadRecord(MeterReadRecord readRecord) {
        for (MeterReadRecord.MeterReadInfo datum : readRecord.getData()) {
            datum.setReadTime(System.currentTimeMillis());
        }
        meterReadRecordDao.saveMeterReadRecord(readRecord);
    }

    @Override
    public long updateReadData(MeterReadRecordUpdateDto dto) {
        MeterReadRecordVo readRecordVo = meterReadRecordDao.findMeterReadRecord(dto.getId(), dto.getReadDate());
        if (readRecordVo == null) {
            throw BusinessException.builder(RmcpErrorEnum.RMCP_NOT_FOUND);
        }
        if (readRecordVo.getData().getReadStatus().equals(ReadStatusEnum.READ.getMessage())) {
            throw BusinessException.builder(RmcpErrorEnum.RMCP_UPDATE_FAIL.getStatus(), "该设备已抄表，不能再更新读数。");
        }
        // 上一次读数
        Double prevReadData = 0D;
        int queryDate    = Integer.parseInt(dto.getReadDate().replaceAll("-",""));
        int currentDate  = DateUtil.parseInt(new Date(), 0);
        BigDecimal lastCost = new BigDecimal("0");
        if (queryDate == currentDate) {
            // 获取上一个记录
            MeterReadRecordVo prevVo = findPrevRecord(dto.getId(), queryDate);
            if (prevVo != null &&prevVo.getData().getReadData() != null) {
                prevReadData = prevVo.getData().getReadData();
            }
            // 当前读数 - 上一次读数 = 当前用水量
            lastCost  = BigDecimalUtils.subtract(dto.getReadData(), prevReadData);
        }
        long total = meterReadRecordDao.updateReadData(dto.getId(), readRecordVo.getDeviceId(), queryDate, dto.getReadData(), lastCost);
        if (total == 0) {
            throw BusinessException.builder(RmcpErrorEnum.RMCP_UPDATE_FAIL);
        }
        return total;
    }

    @Override
    public PageResult<MeterReadRecordVo> pageMeterReadRecord(MeterReadRecordDto dto) {
        return meterReadRecordDao.pageMeterReadRecord(dto, UserUtil.getCurrentUser().getUserCondition(),
                PageRequest.of(dto.getPageNum() - 1, dto.getPageSize()));
    }

    @Override
    public List<MeterReadRecordVo> listMeterReadRecord(MeterReadRecordDto dto) {
        return meterReadRecordDao.listMeterReadRecord(dto, UserUtil.getCurrentUser().getUserCondition());
    }

    @Override
    public List<MeterReadRecordVo> listSingleDeviceTimeWaterConsumption(MeterReadRecordDeviceDto dto) {
        return meterReadRecordDao.queryDeviceMeterReadRecordWithCondtion(dto.getDeviceId(), dto.getStartDate(),dto.getEndDate());
    }

    /**
    * 获取上一个记录
    * @author Andy
    * @date 10:21 2021/8/30
    * @param id:
    * @param currentDate: 当前时间
    * @return com.zcxk.rmcp.api.vo.MeterReadRecordVo
    **/
    private MeterReadRecordVo findPrevRecord(Long id, Integer currentDate){
        return meterReadRecordDao.findMeterReadRecord(id, Criteria.where("data.readDate").lt(currentDate) ,"data.readDate", Sort.Direction.DESC);
    }

    /**
    * 获取下一个记录
    * @author Andy
    * @date 10:21 2021/8/30
    * @param id:
    * @param currentDate: 当前时间
    * @return com.zcxk.rmcp.api.vo.MeterReadRecordVo
    **/
    private MeterReadRecordVo findNextRecord(Long id, Integer currentDate){
        return meterReadRecordDao.findMeterReadRecord(id, Criteria.where("data.readDate").gt(currentDate) ,"data.readDate", Sort.Direction.ASC);
    }

}
