package com.tax.file.service.async.down;

import com.tax.file.constants.FileConstants;
import com.tax.file.context.FileDownContext;
import com.tax.file.model.DownFileModel;
import com.tax.file.model.TkFile;
import com.tax.file.model.TkFileExample;
import com.tax.file.model.TkTaxUser;
import com.tax.file.mq.rabbit.producer.RabbitMQMessageProducer;
import com.tax.file.service.api.TkTaxUserService;
import com.tax.file.service.async.ExecuteMqService;
import com.tax.file.service.async.strategy.LastMonthFixStrategy;
import com.yxcheng.token.common.cache.RedisService;
import com.yxcheng.token.common.model.MqMessage;
import com.yxcheng.token.constants.RedisContants;
import com.yxcheng.token.utils.DateUtils;
import com.yxcheng.token.utils.UUIDGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.concurrent.Future;

@Component
public class FixFileDownService extends AbstractFileDownService {
    private static final Logger logger = LoggerFactory.getLogger(AsyncFileDownService.class);
    @Autowired
    private TkTaxUserService tkTaxUserService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RabbitMQMessageProducer producer;

    @Autowired
    private FileDownQueryPageService fileDownQueryPageService;



    public void fixLastMonthRemain(TkTaxUser e, FileDownContext context) {
        if(!LastMonthFixStrategy.isNeedFix(e.getFixDownDate())) {
            return;
        }
        logger.info(e.getTaxno() + " fixLastMonthRemain...");
        Date now = new Date();

        Date preDateEnd = DateUtils.toDayEnd(DateUtils.getPreLastDay(now, 1));
        Date preDateStart = DateUtils.toDayStart(DateUtils.getApplyStartDate(preDateEnd,FileConstants.applyCycle));

        TkFileExample example = new TkFileExample();
        example.createCriteria().andTaxnoEqualTo(e.getTaxno())
                .andApplyDateBetween(preDateStart,preDateEnd)
                .andDownStatusEqualTo("0");

        //如果上个月末数据没有一条成功的，需要重新下载
        List<TkFile> tkFiles = tkFileService.selectByExample(example);
        if(tkFiles!=null && tkFiles.size()>0){
            DownFileModel model = new DownFileModel();
            model.setTaxUser(e);
            model.setPreDateStart(preDateStart);
            model.setPreDateEnd(preDateEnd);
            model.setContext(context);
            producer.sendFixDownFileTopic(model, e.getPublishNo());
        }
    }

    public void finish(String userName, String taxNo) {
        redisService.set(RedisContants.FIX_DOWN_FILE_LOCK + taxNo,"0",5);
    }

    public boolean isExecuting(String uuidFlag, String userName, String taxNo) {
        logger.info(Thread.currentThread().getName() + " " + taxNo + " value: " + redisService.get(RedisContants.FIX_DOWN_FILE_LOCK + taxNo));
        if("1".equals(redisService.get(RedisContants.FIX_DOWN_FILE_LOCK + taxNo)))return true;

        redisService.set(RedisContants.FIX_DOWN_FILE_LOCK+taxNo,"1",60*60);
        return false;
    }

    @Async("myExecutor")
    public Future<String> execute(MqMessage mqMessage) {
        DownFileModel model = (DownFileModel)mqMessage;
        String userName = model.getTaxUser().getUserName();
        String taxNo = model.getTaxUser().getTaxno();
        String uuidFlag = UUIDGenerator.generate();

        if(isExecuting(uuidFlag, userName, taxNo)) return new AsyncResult<>("taxNo="+taxNo+" is executing");
        logger.info(Thread.currentThread().getName() + " " + taxNo + " FixFileDownService");
        try{
            if(fileDownQueryPageService.doPage(uuidFlag, model,model.getContext(),model.getPreDateStart(),model.getPreDateEnd())){
                model.getTaxUser().setFixDownDate(new Date());
                tkTaxUserService.updateByPrimaryKeySelective(model.getTaxUser());
            }
        }finally {
            finish(userName, taxNo);
        }
        return new AsyncResult<>("taxNo="+taxNo+" accomplished!");
    }
}
