/**
 * Copyright 2019 DH
 * All right reserved.
 * 项目名称: 山洪灾害运维系统
 * 创建日期:2023/8/21
 */
package org.springblade.jobtask;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.baseinfo.rtu.entity.RtuInfoEntity;
import org.springblade.modules.baseinfo.rtu.service.IRtuBaseInfoService;
import org.springblade.modules.business.data.dto.*;
import org.springblade.modules.business.data.service.*;
import org.springblade.modules.business.upcount.dto.RtuUpCountInfoDTO;
import org.springblade.modules.business.upcount.entity.RtuUpCountInfoEntity;
import org.springblade.modules.business.upcount.service.IRtuUpCountService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/***
 * Date:2023/8/21
 * Title: 测站上报率统计
 * Description：按小时统计上报率，按天统计上报率
 * @author dylan
 * @version 1.0
 * Remark：认为有必要的其他信息
 */
@Slf4j
@Component
@EnableScheduling
public class RtuUpCountProcessor {
	private static ThreadFactory upCountThreadFactory = new ThreadFactoryBuilder().setNameFormat("up-count-thread-pool-%d").build();
	private static ExecutorService upCountThreadPool = new ThreadPoolExecutor(1, 1,
		0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), upCountThreadFactory, new ThreadPoolExecutor.AbortPolicy());

	@Resource
	private IRtuUpCountService upCountService;

	@Resource
	private IRtuBaseInfoService rtuBaseInfoService;

	@Resource
	private IRtuDataRainStoreService rainStoreService;

	@Resource
	private IRtuDataWaterLevelStoreService waterLevelStoreService;

	@Resource
	private IRtuDataGroundStoreService groundStoreService;

	@Value("${spring.task-config.rtu-datagram-up-task}")
	private boolean rtuDatagramUpRun;


//	@Scheduled(cron = "10 0 0/1 * * *")
	public void upHourCountTask() {
		if(rtuDatagramUpRun) {
			log.info("按小时上报率统计任务创建 {}", Func.formatDateTime(new Date()));
			UpHourCountTask task = new UpHourCountTask(LocalDateTime.now());
			FutureTask<Integer> futureTask = new FutureTask<>(task);
			upCountThreadPool.execute(futureTask);
		}
	}

//	@Scheduled(cron = "20 0 0 0/1 * *")
	public void upDayCountTask() {
		if(rtuDatagramUpRun) {
			log.info("按天上报率统计任务创建 {}", Func.formatDateTime(new Date()));
			UpDayCountTask task = new UpDayCountTask(LocalDateTime.now());
			FutureTask<Integer> futureTask = new FutureTask<>(task);
			upCountThreadPool.execute(futureTask);
		}
	}

	private class UpHourCountTask implements Callable<Integer> {
		private LocalDateTime checkTime;

		public UpHourCountTask(LocalDateTime checkTime) {
			this.checkTime = checkTime;
		}

		@Override
		public Integer call() throws Exception {
			LambdaQueryWrapper<RtuInfoEntity> rtuWrapper = Wrappers.<RtuInfoEntity>query().lambda();
			rtuWrapper.eq(RtuInfoEntity::getIsDeleted, 0);
			List<RtuInfoEntity> list = rtuBaseInfoService.list(rtuWrapper);
			for (RtuInfoEntity entity : list) {
				//统计雨量站
				if (entity.getIsRain() != null && entity.getIsRain() == 1) {
					LambdaQueryWrapper<RtuUpCountInfoEntity> wrapper = Wrappers.<RtuUpCountInfoEntity>query().lambda();
					wrapper.eq(RtuUpCountInfoEntity::getRtuCode, entity.getRtuCode());
					wrapper.eq(RtuUpCountInfoEntity::getTimeKind, 1);
					wrapper.eq(RtuUpCountInfoEntity::getUpKind, 1);
					LocalDateTime et = checkTime.withMinute(0).withSecond(0).withNano(0);
					LocalDateTime st = et.minusHours(1);
					wrapper.eq(RtuUpCountInfoEntity::getCountTime, Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
					long count = upCountService.count(wrapper);
					if (count == 0) {
						RtuDataRainDTO dataRainDTO = new RtuDataRainDTO();
						dataRainDTO.setRtuCode(entity.getRtuCode());
						dataRainDTO.setBeginTime(Date.from(st.atZone(ZoneId.systemDefault()).toInstant()));
						dataRainDTO.setEndTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						long upCount = rainStoreService.rtuUpDataCount(dataRainDTO);
						RtuUpCountInfoEntity rtuUpCountInfoEntity = new RtuUpCountInfoEntity();
						rtuUpCountInfoEntity.setRtuCode(entity.getRtuCode());
						rtuUpCountInfoEntity.setTimeKind(1);
						rtuUpCountInfoEntity.setUpKind(1);
						rtuUpCountInfoEntity.setCountTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						rtuUpCountInfoEntity.setUpCount((int) upCount);
						upCountService.save(rtuUpCountInfoEntity);
					}
				}
				//统计水位
				if ((entity.getIsRes() != null && entity.getIsRes() == 1) || (entity.getIsRiver() != null && entity.getIsRiver() == 1)) {
					LambdaQueryWrapper<RtuUpCountInfoEntity> wrapper = Wrappers.<RtuUpCountInfoEntity>query().lambda();
					wrapper.eq(RtuUpCountInfoEntity::getRtuCode, entity.getRtuCode());
					wrapper.eq(RtuUpCountInfoEntity::getTimeKind, 1);
					wrapper.eq(RtuUpCountInfoEntity::getUpKind, 3);
					LocalDateTime et = checkTime.withMinute(0).withSecond(0).withNano(0);
					LocalDateTime st = et.minusHours(1);
					wrapper.eq(RtuUpCountInfoEntity::getCountTime, Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
					long count = upCountService.count(wrapper);
					if (count == 0) {
						RtuDataWaterLevelDTO dto = new RtuDataWaterLevelDTO();
						dto.setRtuCode(entity.getRtuCode());
						dto.setBeginTime(Date.from(st.atZone(ZoneId.systemDefault()).toInstant()));
						dto.setEndTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						long upCount = waterLevelStoreService.rtuUpDataCount(dto);
						RtuUpCountInfoEntity rtuUpCountInfoEntity = new RtuUpCountInfoEntity();
						rtuUpCountInfoEntity.setRtuCode(entity.getRtuCode());
						rtuUpCountInfoEntity.setTimeKind(1);
						rtuUpCountInfoEntity.setUpKind(3);
						rtuUpCountInfoEntity.setCountTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						rtuUpCountInfoEntity.setUpCount((int) upCount);
						upCountService.save(rtuUpCountInfoEntity);
					}
				}
				//墒情
				if (entity.getIsGround() != null && entity.getIsGround() == 1) {
					LambdaQueryWrapper<RtuUpCountInfoEntity> wrapper = Wrappers.<RtuUpCountInfoEntity>query().lambda();
					wrapper.eq(RtuUpCountInfoEntity::getRtuCode, entity.getRtuCode());
					wrapper.eq(RtuUpCountInfoEntity::getTimeKind, 1);
					wrapper.eq(RtuUpCountInfoEntity::getUpKind, 4);
					LocalDateTime et = checkTime.withMinute(0).withSecond(0).withNano(0);
					LocalDateTime st = et.minusHours(1);
					wrapper.eq(RtuUpCountInfoEntity::getCountTime, Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
					long count = upCountService.count(wrapper);
					if (count == 0) {
						RtuDataGroundDTO dataGroundDTO = new RtuDataGroundDTO();
						dataGroundDTO.setRtuCode(entity.getRtuCode());
						dataGroundDTO.setBeginTime(Date.from(st.atZone(ZoneId.systemDefault()).toInstant()));
						dataGroundDTO.setEndTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						long upCount = groundStoreService.rtuUpDataCount(dataGroundDTO);
						RtuUpCountInfoEntity rtuUpCountInfoEntity = new RtuUpCountInfoEntity();
						rtuUpCountInfoEntity.setRtuCode(entity.getRtuCode());
						rtuUpCountInfoEntity.setTimeKind(1);
						rtuUpCountInfoEntity.setUpKind(4);
						rtuUpCountInfoEntity.setCountTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						rtuUpCountInfoEntity.setUpCount((int) upCount);
						upCountService.save(rtuUpCountInfoEntity);
					}
				}
			}
			return 0;
		}
	}

	private class UpDayCountTask implements Callable<Integer> {
		private LocalDateTime checkTime;

		public UpDayCountTask(LocalDateTime checkTime) {
			this.checkTime = checkTime;
		}

		@Override
		public Integer call() throws Exception {
			LambdaQueryWrapper<RtuInfoEntity> rtuWrapper = Wrappers.<RtuInfoEntity>query().lambda();
			rtuWrapper.eq(RtuInfoEntity::getIsDeleted, 0);
			List<RtuInfoEntity> list = rtuBaseInfoService.list(rtuWrapper);
			for (RtuInfoEntity entity : list) {
				//统计雨量站
				if (entity.getIsRain() != null && entity.getIsRain() == 1) {
					LambdaQueryWrapper<RtuUpCountInfoEntity> wrapper = Wrappers.<RtuUpCountInfoEntity>query().lambda();
					wrapper.eq(RtuUpCountInfoEntity::getRtuCode, entity.getRtuCode());
					wrapper.eq(RtuUpCountInfoEntity::getTimeKind, 2);
					wrapper.eq(RtuUpCountInfoEntity::getUpKind, 1);
					LocalDateTime et = checkTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
					LocalDateTime st = et.minusDays(1);
					wrapper.eq(RtuUpCountInfoEntity::getCountTime, Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
					long count = upCountService.count(wrapper);
					if (count == 0) {
						RtuUpCountInfoDTO dto = new RtuUpCountInfoDTO();
						dto.setRtuCode(entity.getRtuCode());
						dto.setUpKind(1);
						dto.setTimeKind(1);
						dto.setBeginTime(Date.from(st.atZone(ZoneId.systemDefault()).toInstant()));
						dto.setEndTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						long upCount = upCountService.upCount(dto);
						RtuUpCountInfoEntity rtuUpCountInfoEntity = new RtuUpCountInfoEntity();
						rtuUpCountInfoEntity.setRtuCode(entity.getRtuCode());
						rtuUpCountInfoEntity.setTimeKind(2);
						rtuUpCountInfoEntity.setUpKind(1);
						rtuUpCountInfoEntity.setCountTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						rtuUpCountInfoEntity.setUpCount((int) upCount);
						upCountService.save(rtuUpCountInfoEntity);
					}
				}
				//统计水位
				if ((entity.getIsRes() != null && entity.getIsRes() == 1) || (entity.getIsRiver() != null && entity.getIsRiver() == 1)) {
					LambdaQueryWrapper<RtuUpCountInfoEntity> wrapper = Wrappers.<RtuUpCountInfoEntity>query().lambda();
					wrapper.eq(RtuUpCountInfoEntity::getRtuCode, entity.getRtuCode());
					wrapper.eq(RtuUpCountInfoEntity::getTimeKind, 2);
					wrapper.eq(RtuUpCountInfoEntity::getUpKind, 3);
					LocalDateTime et = checkTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
					LocalDateTime st = et.minusDays(1);
					wrapper.eq(RtuUpCountInfoEntity::getCountTime, Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
					long count = upCountService.count(wrapper);
					if (count == 0) {
						RtuUpCountInfoDTO dto = new RtuUpCountInfoDTO();
						dto.setRtuCode(entity.getRtuCode());
						dto.setUpKind(3);
						dto.setTimeKind(1);
						dto.setBeginTime(Date.from(st.atZone(ZoneId.systemDefault()).toInstant()));
						dto.setEndTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						long upCount = upCountService.upCount(dto);
						RtuUpCountInfoEntity rtuUpCountInfoEntity = new RtuUpCountInfoEntity();
						rtuUpCountInfoEntity.setRtuCode(entity.getRtuCode());
						rtuUpCountInfoEntity.setTimeKind(2);
						rtuUpCountInfoEntity.setUpKind(3);
						rtuUpCountInfoEntity.setCountTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						rtuUpCountInfoEntity.setUpCount((int) upCount);
						upCountService.save(rtuUpCountInfoEntity);
					}
				}
				//墒情
				if (entity.getIsGround() != null && entity.getIsGround() == 1) {
					LambdaQueryWrapper<RtuUpCountInfoEntity> wrapper = Wrappers.<RtuUpCountInfoEntity>query().lambda();
					wrapper.eq(RtuUpCountInfoEntity::getRtuCode, entity.getRtuCode());
					wrapper.eq(RtuUpCountInfoEntity::getTimeKind, 2);
					wrapper.eq(RtuUpCountInfoEntity::getUpKind, 4);
					LocalDateTime et = checkTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
					LocalDateTime st = et.minusDays(1);
					wrapper.eq(RtuUpCountInfoEntity::getCountTime, Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
					long count = upCountService.count(wrapper);
					if (count == 0) {
						RtuUpCountInfoDTO dto = new RtuUpCountInfoDTO();
						dto.setRtuCode(entity.getRtuCode());
						dto.setUpKind(4);
						dto.setTimeKind(1);
						dto.setBeginTime(Date.from(st.atZone(ZoneId.systemDefault()).toInstant()));
						dto.setEndTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						long upCount = upCountService.upCount(dto);
						RtuUpCountInfoEntity rtuUpCountInfoEntity = new RtuUpCountInfoEntity();
						rtuUpCountInfoEntity.setRtuCode(entity.getRtuCode());
						rtuUpCountInfoEntity.setTimeKind(2);
						rtuUpCountInfoEntity.setUpKind(4);
						rtuUpCountInfoEntity.setCountTime(Date.from(et.atZone(ZoneId.systemDefault()).toInstant()));
						rtuUpCountInfoEntity.setUpCount((int) upCount);
						upCountService.save(rtuUpCountInfoEntity);
					}
				}
			}
			return 0;
		}
	}
}
