package org.springblade.modules.api.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.cache.ParamCache;
import org.springblade.common.constant.CommonConstant;
import org.springblade.common.utils.CommonUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.shopping.entity.Consign;
import org.springblade.modules.shopping.entity.ConsignConfig;
import org.springblade.modules.shopping.service.IConsignConfigService;
import org.springblade.modules.shopping.service.IConsignService;
import org.springblade.modules.shopping.wrapper.ConsignWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class ConsignSchedulingTask implements SchedulingConfigurer {

	private static final Logger log = LoggerFactory.getLogger(ConsignSchedulingTask.class);

	private static final String PATTERN_DATE = org.springblade.core.tool.utils.DateUtil.PATTERN_DATE;
	private static final String PATTERN_TIME = org.springblade.core.tool.utils.DateUtil.PATTERN_TIME;
	private static final String PATTERN_DATETIME = org.springblade.core.tool.utils.DateUtil.PATTERN_DATETIME;

	private static final String TASK_NAME = "【定时修改进货订单数据】";
	public static boolean isStartTask = true;
	@Autowired
	private IConsignService consignService;

	@Autowired
	private IConsignConfigService consignConfigService;

	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
		if(!isStartTask){
			return;
		}
		Runnable task = new Runnable() {
			@Override
			public void run() {
				//任务逻辑代码部分.
				log.info(TASK_NAME + "定时任务开始: " + LocalDateTime.now());
				//获取配置的增益时间
				int gainTime = Integer.parseInt(ParamCache.getValue(CommonConstant.GAIN_CONSIGN_TIME));
				log.info(TASK_NAME + "增益时间: " + gainTime);
				updateConsignConfig(gainTime);
				log.info(TASK_NAME + "定时任务结束: " + LocalDateTime.now());
			}
		};

		Trigger trigger = new Trigger() {
			@Override
			public Date nextExecutionTime(TriggerContext triggerContext) {
				//任务触发，可修改任务的执行周期.
				//每一次任务触发，都会执行这里的方法一次，重新获取下一次的执行时间
				//cron = timerQueryMapper.getCronTime();
				//0/5 * * * * ?
				//0 0 1 * * ?
				//定时时间间隔 分钟
				String cron = "0 0/1 * * * ?";
				if(StringUtil.isEmpty(cron)){
					cron = "0 10 00 * * ?";
				}
				log.info(TASK_NAME + "定时时间间隔: " + cron);
				//String cron = "0 0/" + taskTime + " * * * ?";
				//23:20:00执行
				//String cron = "0 20 23 * * ?";
				//00:10:00执行
				CronTrigger trigger = new CronTrigger(cron);
				return trigger.nextExecutionTime(triggerContext);
			}
		};
		taskRegistrar.addTriggerTask(task, trigger);
	}

	/**
	 * 1、逻辑删除场次
	 * 2、通过增益时间新建场次
	 * 3、更新关联场次的用户单（关联场次ID）
	 * 4、
	 */
	private void updateConsignConfig(Integer gainTime){
		//当前时间大于结束时间的第一条数据
		ConsignConfig consignConfig = consignConfigService.getOne(Wrappers.<ConsignConfig>lambdaQuery()
			.lt(ConsignConfig::getEndTime, DateUtil.now())
				.eq(ConsignConfig::getIsEnabled, 2)
			.orderByDesc(ConsignConfig::getEndTime).last(" limit 1"));
		if (consignConfig != null){
			ConsignConfig config = new ConsignConfig();
			//场次开始时间和结束时间都加上增益时间
			String startDate = DateUtil.format(consignConfig.getStartTime(), PATTERN_TIME);
			String endDate = DateUtil.format(consignConfig.getEndTime(), PATTERN_TIME);
			//是否取下一天
			String ymd = DateUtil.format(DateUtil.date(), PATTERN_DATE);
			String startTime = ymd + StringPool.SPACE + startDate;
			String endTime = ymd + StringPool.SPACE + endDate;
			//设置增益时间偏移量
			Date start = DateUtil.offsetMinute(DateUtil.parse(startTime,PATTERN_DATETIME),gainTime);
			Date end = DateUtil.offsetMinute(DateUtil.parse(endTime,PATTERN_DATETIME),gainTime);
			//更新数据
			config.setStartTime(start);
			config.setEndTime(end);
			config.setTitle(consignConfig.getTitle());
			config.setIsEnabled(consignConfig.getIsEnabled());
			//更新当前场次变为停用
			consignConfig.setIsEnabled(1);//停用
			consignConfig.setIsNow(1);//旧
			consignConfigService.updateById(consignConfig);
			//新增场次
			String configNo = CommonUtil.genTimeID();
			config.setConfigNo(configNo);
			config.setIsNow(2);//新
			consignConfigService.save(config);
			//更新进货表数据
			consign(start, end, consignConfig.getId(), configNo);
		}
	}
	/**
	 * 1.更新发布的进货商品需要
	 * 	 把原数据逻辑删除， 新增一条数据 处理的开始时间和结束时间
	 * 	 时间变为下一天时间
	 * 2.修改商品的价格
	 * 	 抢购价 溢价
	 */
	private void consign(Date startDate, Date endTime, Long configId, String configNo){
		ConsignConfig consignConfig = consignConfigService.getOne(Wrappers.<ConsignConfig>lambdaQuery()
			.eq(ConsignConfig::getConfigNo, configNo));
		Long configNowId = 0L;
		if(consignConfig != null){
			configNowId = consignConfig.getId();
		}else{
			log.info("获取数据失败....");
		}
		List<Consign> list = consignService.list(Wrappers.<Consign>lambdaQuery()
			.eq(Consign::getConsignFor,1) //后台
			.eq(Consign::getIsSale, 2) //上线
			.eq(Consign::getIsDelivery,1) //是否交割
			.eq(Consign::getConsignConfigId, configId)); //没有交割
		Double ratio = Double.valueOf(ParamCache.getValue(CommonConstant.DEFAULT_CONDIGN_RATIO_T1));
		if (list.size() > 0){
			//通过场次Id更新用户单时间等数据
			Consign consign = list.get(0);
			Double consignPrice = ConsignWrapper.build().getPrice(consign.getConsignPrice());
			Consign sign = new Consign();
			sign.setStartTime(startDate);
			sign.setEndTime(endTime);
			sign.setConsignPrice(consignPrice);
			//sign.setObtainPrice(consign.getConsignPrice()); //不能更新用户取得价
			sign.setPremiumPrice(consignPrice);
			sign.setConsignConfigId(configNowId);
			//状态为寄售中，价格不相等的数据更新时间和场次
			consignService.update(sign, Wrappers.<Consign>lambdaQuery()
				.eq(Consign::getConsignConfigId, configId)
				.eq(Consign::getConsignState, 1) //寄售中才变动
				.ne(Consign::getConsignPrice, consign.getConsignPrice()));
			/**
			 * 查询寄售数据中平台需要兜底的数据，
			 * 	1、目的把寄售状态改为待付款
			 * 	2、状态为1：寄售中
			 * 	3、剩余数量为 1
			 * 	4、寄售价台的寄售价相等的数据
			 */
			Consign platform = new Consign();
			platform.setConsignState(2);//待付款
			platform.setNowStock(0);//被平台抢
			consignService.update(platform, Wrappers.<Consign>lambdaQuery()
				.eq(Consign::getConsignConfigId, configId)
				.eq(Consign::getConsignState, 1) //寄售中才变动
				.eq(Consign::getConsignPrice, consign.getConsignPrice()));
		}
		List<Consign> batchList = new ArrayList<>();
		for (Consign item: list ) {
			//使用第一条数据更新场次的所有寄售价
			Consign consign = list.get(0);
			Consign sign = new Consign();
			BeanUtil.copyProperties(consign,sign);
			sign.setId(null);
			sign.setStartTime(startDate);
			sign.setEndTime(endTime);
			sign.setTitle(item.getTitle());
			Double consignPrice = ConsignWrapper.build().getPrice(consign.getConsignPrice());
			//Double price = NumberUtil.add(consign.getConsignPrice(),ratioPrice);// 0.105
			//Double consignPrice = NumberUtil.roundDown(price,2);
			sign.setConsignPrice(consignPrice);
			sign.setNowStock(sign.getTotalNum()); //初始金额等于总金额
			sign.setObtainPrice(consign.getObtainPrice());//进货价 == 取得价
			sign.setPremiumPrice(consignPrice);
			sign.setCreateTime(DateUtil.date());
			sign.setConsignConfigId(configNowId);
			sign.setConsignState(1); //变为1
			item.setConsignState(3); //把来源为后台的原数据更新为已完成
			batchList.add(sign);
		}
		boolean updateFlg = consignService.updateBatchById(list);
		if (!updateFlg){
			log.info("定时任务更新失败: " + LocalDateTime.now());
		}
		boolean saveBatchFlg = consignService.saveBatch(batchList);
		if (!saveBatchFlg){
			log.info("定时任务新增失败: " + LocalDateTime.now());
		}
	}

}
