package com.quantgroup.asset.distribution.controller;

import java.sql.Timestamp;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.quantgroup.asset.distribution.service.newrule.CoreFilter;
import com.quantgroup.asset.distribution.service.newrule.third.AuditResponce;
import com.quantgroup.asset.distribution.service.redis.IRedisService;
import com.quantgroup.asset.distribution.util.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.asset.IAssetService;
import com.quantgroup.asset.distribution.service.jpa.entity.DistributeFailLog;
import com.quantgroup.asset.distribution.service.jpa.repository.IDistributeFailLogRepository;

import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;

/**
 * 重试Controller
 * 
 * @author liwenbin
 *
 */
@RestController
@Slf4j
@RequestMapping("/retry")
public class RetryController {

	@Autowired
	private IDistributeFailLogRepository distributeFailLogRepository;
	@Autowired
	private IAssetService assetService;
	@Autowired
	private IRedisService<String> redisService;
    @Resource
    private CoreFilter coreFilter;

	@RequestMapping("/orders")
	public GlobalResponse retryOrders(String startTime, String endTime) {
		try {
			Page<DistributeFailLog> pageableFailAuditLog = distributeFailLogRepository.findByCreatedAtBetweenAndEnableAndCallType(
					Timestamp.valueOf(startTime), Timestamp.valueOf(endTime), true,0, new PageRequest(0, 1000));
			List<DistributeFailLog> distributeFailLogList = pageableFailAuditLog.getContent();
			retryDistributeFailLogListOld(distributeFailLogList);
		} catch (Exception e) {
			log.error("资产分发失败订单重新分发异常!", e);
		}
		return GlobalResponse.success();
	}

	@Async
	@RequestMapping("/repeat_db_distribute")
	public void repeatDBAudit() {
		String lockKey = "ASSET_DISTRIBUTION:REPEAT_DB_ATTRIBUTE:@88JMS";
		try {
            boolean b = redisService.setIfAbsent(lockKey, "1", 1, TimeUnit.DAYS);
            if (!b) {
                return;
            }
            old();
            now();
		} catch (Exception e) {
			log.error("数据库资产分发失败订单重新分发出现异常!", e);
		} finally {
			redisService.del(lockKey);
		}
	}
	@Async
    public void now() throws  Exception {
        log.info("数据库new资产分发失败订单重新分发开始");
        try {
            String startTime = DateUtil.getStrFormatDate("yyyy-MM-dd HH:mm:ss", -7);
            String endTime = DateUtil.timestamp2Str(System.currentTimeMillis() + "", "yyyy-MM-dd HH:mm:ss");
            int i = 1;
            while (i > 0 && !CheckController.isOffLine()) {
                Page<DistributeFailLog> pageableFailDistributeLog = distributeFailLogRepository.findByCreatedAtBetweenAndEnableAndCallType(Timestamp.valueOf(startTime),
                        Timestamp.valueOf(endTime), true, 1,new PageRequest(0, 50));
                List<DistributeFailLog> distributeFailLogList = pageableFailDistributeLog.getContent();
                retryDistributeFailLogListNew(distributeFailLogList);
                TimeUnit.SECONDS.sleep(30);
                ++i;
                if (distributeFailLogList == null || distributeFailLogList.size() < 50) {
                    i = -1;
                }
            }
            log.info("数据库new资产分发失败订单重新分发完成!");
        } catch (Exception e){
            throw e;
        }
    }
    @Async
    public void old() throws  Exception {
        log.info("数据库old资产分发失败订单重新分发开始");
     try {
         String startTime = DateUtil.getStrFormatDate("yyyy-MM-dd HH:mm:ss", -7);
         String endTime = DateUtil.timestamp2Str(System.currentTimeMillis() + "", "yyyy-MM-dd HH:mm:ss");
         int i = 1;
         while (i > 0 && !CheckController.isOffLine()) {
             Page<DistributeFailLog> pageableFailDistributeLog = distributeFailLogRepository.findByCreatedAtBetweenAndEnableAndCallType(Timestamp.valueOf(startTime),
                     Timestamp.valueOf(endTime), true, 0,new PageRequest(0, 50));
             List<DistributeFailLog> distributeFailLogList = pageableFailDistributeLog.getContent();
             retryDistributeFailLogListOld(distributeFailLogList);
             TimeUnit.SECONDS.sleep(30);
             ++i;
             if (distributeFailLogList == null || distributeFailLogList.size() < 50) {
                 i = -1;
             }
         }
         log.info("数据库old资产分发失败订单重新分发完成!");
     } catch (Exception e){
         throw e;
     }
    }
	private void retryDistributeFailLogListOld(List<DistributeFailLog> distributeFailLogList) {
        if (CollectionUtils.isNotEmpty(distributeFailLogList)) {
            log.info("old分发失败查询数量为:{}", distributeFailLogList.size());
            distributeFailLogList.forEach(distributeFailLog -> {
                AssetForm assetForm = JSON.parseObject(distributeFailLog.getContext(), AssetForm.class);
                // 重新审核
                assetService.assetsIn(assetForm);

                distributeFailLog.setEnable(false);
                distributeFailLogRepository.save(distributeFailLog);
            });
        }
    }

    private void retryDistributeFailLogListNew(List<DistributeFailLog> distributeFailLogList) {
        if (CollectionUtils.isNotEmpty(distributeFailLogList)) {
            log.info("new分发失败查询数量为:{}", distributeFailLogList.size());
            distributeFailLogList.forEach(distributeFailLog -> {
                AuditResponce assetForm = JSON.parseObject(distributeFailLog.getContext(), AuditResponce.class);
                // 重新审核
                coreFilter.coreHandle(assetForm);
                distributeFailLog.setEnable(false);
                distributeFailLogRepository.save(distributeFailLog);
            });
        }
    }
}
