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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tax.file.model.*;
import com.tax.file.service.api.FIncomeInvoiceService;
import com.tax.file.service.api.FileServerService;
import com.tax.file.service.api.TkTaxUserService;
import com.tax.file.utils.NationDic;
import com.tax.file.utils.NationUtil;
import com.tax.file.utils.income.IncomeFileExcelUtil;
import com.tax.file.utils.token.TokenFactory;
import com.yxcheng.token.common.cache.RedisService;
import com.yxcheng.token.constants.RedisContants;
import com.yxcheng.token.utils.DateUtils;
import org.apache.commons.lang.StringUtils;
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.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;

@Component
public class AsynIncomeDownService {
    @Autowired
    protected TkTaxUserService tkTaxUserService;
    @Autowired
    protected FileServerService fileServerService;
    @Autowired
    private FIncomeInvoiceService incomeInvoiceService;
    @Autowired
    private RedisService redisService;

    @Async("myExecutor")
    public Future<String> doIncomeDown(CountDownLatch latch, String taxno, List<FIncomeInvoice> list) {
        try {
            TkTaxUserExample taxUserExample = new TkTaxUserExample();
            taxUserExample.createCriteria().andTaxnoEqualTo(taxno);

            TkTaxUser taxUser = tkTaxUserService.getOne(taxUserExample);


            FileServerExample fileServerExample = new FileServerExample();
            fileServerExample.createCriteria().andServerNoEqualTo(taxUser.getServerNo());

            FileServer fileServer = fileServerService.getOne(fileServerExample);

            String tokenCode = TokenFactory.getTokenCode(taxUser, fileServer).getToken();

            if(StringUtils.isBlank(tokenCode)){
                return new AsyncResult<>("AsynIncomeApplyService taxno="+taxUser.getTaxno()+" get token failed!");
            }
            Date applyDateBegin = DateUtils.getNationDate("8");
            Date now = new Date();

            FIncomeInvoice query = new FIncomeInvoice();
            query.setTaxno(taxno);
            query.setToken(tokenCode);
            query.setZoneCode(taxUser.getZoneCode());
            query.setApplyDateBegin(applyDateBegin);
            query.setApplyDateEnd(now);
            JSONObject jsonObject = NationUtil.incomeResultQuery(query);
            String key1 = jsonObject.getString("key1");
            if("01".equals(key1)){
                JSONArray data = jsonObject.getJSONObject("key3").getJSONArray("aaData");
                if(data!=null && data.size()>0){
                    executeData(data,taxUser,tokenCode);
                }
            }


        }catch (Exception e){

        }finally {
            latch.countDown();
        }
        return new AsyncResult<>("AsynIncomeDownService taxno="+taxno+" accomplished!");
    }

    private void executeData(JSONArray jsonArray, TkTaxUser taxUser, String tokenCode) throws Exception {
        for(int i =0;i<jsonArray.size();i++){
            JSONArray array = jsonArray.getJSONArray(i);
            int applyNum = array.getInteger(2);
            int finishNum = array.getInteger(3);
            String fileStr = array.getString(6);
            String status = NationDic.transfer(NationDic.incomeDic,array.getString(4));
            if("1".equals(status)){
                String fileId = NationDic.transferFileId(fileStr);
                if(redisService.exists(RedisContants.INCOME_FILEID_LOCK + fileId))continue;
                FIncomeInvoice query = new FIncomeInvoice();
                query.setTaxno(taxUser.getTaxno());
                query.setZoneCode(taxUser.getZoneCode());
                query.setToken(tokenCode);
                query.setFileId(fileId);
                JSONObject jsonObject = NationUtil.incomeFileDown(query);
                if("01".equals(jsonObject.getString("key1"))){
                    String filePath = NationUtil.downFile(jsonObject, query);
                    if(analysisFile(filePath,taxUser)){
                        redisService.set(RedisContants.INCOME_FILEID_LOCK + fileId,"1");
                    }
                }
            }
        }
    }

    private boolean analysisFile(String filePath, TkTaxUser taxUser) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File(filePath));
            List<FIncomeInvoice> fIncomeInvoices = IncomeFileExcelUtil.readInvoice(fis);
            if(fIncomeInvoices!=null && fIncomeInvoices.size()>0){
                return updateResult(fIncomeInvoices,taxUser);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(fis!=null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    private boolean updateResult(List<FIncomeInvoice> fIncomeInvoices, TkTaxUser taxUser) {
            FIncomeInvoiceExample example = new FIncomeInvoiceExample();
            for(FIncomeInvoice invoice : fIncomeInvoices){
                example.clear();
                example.createCriteria().andInvKindEqualTo(invoice.getInvKind())
                                        .andInvNumEqualTo(invoice.getInvNum())
                                        .andUserNameEqualTo(taxUser.getUserName());

                FIncomeInvoice entity = incomeInvoiceService.getOne(example);
                if(entity==null)continue;
                if("1".equals(entity.getDownStatus())){
                    continue;
                }
                entity.setResult(invoice.getResult());
                entity.setDownStatus("1");
                entity.setProcessDate(invoice.getProcessDate());
                incomeInvoiceService.updateByPrimaryKeySelective(entity);
            }
            return true;
    }
}
