package com.jianshui.invoice.task;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jianshui.common.core.domain.entity.Companyservice;
import com.jianshui.common.core.redis.RedisCache;
import com.jianshui.common.utils.StringUtils;
import com.jianshui.common.utils.spring.SpringUtils;
import com.jianshui.framework.manager.AsyncManager;
import com.jianshui.invoice.domain.BillInfo;
import com.jianshui.invoice.domain.Invoice;
import com.jianshui.invoice.domain.InvoiceBack;
import com.jianshui.invoice.domain.dto.HXResponse;
import com.jianshui.invoice.domain.dto.QueryBillInfoDTO;
import com.jianshui.invoice.factory.IInvoiceRequestFactory;
import com.jianshui.invoice.factory.IInvoiceResponseFactory;
import com.jianshui.invoice.factory.IInvoiceServiceFactory;
import com.jianshui.invoice.mapper.InvoiceBackMapper;
import com.jianshui.invoice.mapper.InvoiceMapper;
import com.jianshui.invoice.service.IInvoiceApiService;
import com.jianshui.invoice.service.IInvoiceRequestService;
import com.jianshui.queue.utils.RedisQueueUtil;
import com.jianshui.system.service.ICompanyserviceService;
import com.jianshui.system.service.IServiceManageService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.TimerTask;

/**
 * @Description 批量开票任务
 **/
@Slf4j
public class AddInvoiceBatchTask extends TimerTask {

//    private BillInfo finalBillInfo;
//    private Companyservice companyservice;
//    private IInvoiceApiService invoiceApiService;
//
    private ICompanyserviceService iCompanyserviceService;
//
    private IServiceManageService serviceManageService;
//
    private IInvoiceRequestFactory invoiceRequestFactory;
//
    private IInvoiceServiceFactory invoiceServiceFactory;
//
    private InvoiceBackMapper invoiceBackMapper;
    
    private String identity;
    private String order;


    public AddInvoiceBatchTask(ICompanyserviceService iCompanyserviceService, IServiceManageService serviceManageService
            , IInvoiceRequestFactory invoiceRequestFactory,IInvoiceServiceFactory invoiceServiceFactory,InvoiceBackMapper invoiceBackMapper,String identity,String order) {
        this.iCompanyserviceService = iCompanyserviceService;
        this.serviceManageService = serviceManageService;
        this.invoiceRequestFactory = invoiceRequestFactory;
        this.invoiceServiceFactory = invoiceServiceFactory;
        this.invoiceBackMapper = invoiceBackMapper;
        this.identity = identity;
        this.order = order;
        
    }

    @SneakyThrows
    @Override
    public void run() {

        // 异步处理
        // 1-1 identity校验
        if (StringUtils.isEmpty(identity)) {
            log.info("[重汽批量开票接口]身份认证参数为空!");
            return;
        }

        // 1-2 企业信息校验
        Companyservice companyservice = null;
        try {
            companyservice = iCompanyserviceService.selectCompanyserviceByIdentity(identity);
        } catch (Exception e) {
            log.info("[重汽批量开票接口]获取企业信息异常!identity={},e={}", identity, e);
            return;
        }
        if (companyservice == null) {
            log.info("[重汽批量开票接口]企业信息不存在!identity={}", identity);
            return;
        }

        // 1-3 获得入口报文适配器
        JSONObject decryptResult = null;
        try {
            String requestAdapterKey = serviceManageService.getRequestAdapterKey("invoice", companyservice.getCompanyid());
            IInvoiceRequestService invoiceRequestService = invoiceRequestFactory.getService(requestAdapterKey);
            decryptResult = invoiceRequestService.decryptZq(identity,order, companyservice, "addBatch");
        } catch (Exception e) {
            log.info("[重汽批量开票接口]请求解密失败!identity={},e={}", identity, e);
            return;
        }

        // 2-报文处理
        cn.hutool.json.JSONObject billJson = null;
        try {
            billJson = JSONUtil.parseObj(decryptResult);
        } catch (Exception e) {
            log.info("[重汽批量开票接口]报文格式化异常!identity={}，e={}", identity, e);
            return;
        }
        if (billJson.get("billInfo") == null) {
            log.info("[重汽批量开票接口]未匹配到发票报文!identity={}", identity);
            return;
        }

        JSONArray billJsonArray = null;
        try {
            billJsonArray = JSONUtil.parseArray(billJson.get("billInfo"));
        } catch (Exception e) {
            log.info("[重汽批量开票接口]发票报文获取异常!identity={},e={}", identity, e);
            return;
        }
        if (billJsonArray.size() == 0) {
            log.info("[重汽批量开票接口]发票报文为空!identity={}", identity);
            return;
        }

        // 3-报文递交开票
        for (Object billInfoObj : billJsonArray) {

            // 1-前置条件判断
            InvoiceBack invoiceBack = new InvoiceBack();
            invoiceBack.setUpdateTime(new Date());
            invoiceBack.setCreateTime(new Date());
            invoiceBack.setId(IdUtil.randomUUID());
            invoiceBack.setSystemOrderno(IdUtil.randomUUID());
            invoiceBack.setStatus("1");
            invoiceBack.setIdentity(identity);
            invoiceBack.setBackMsg("");
            invoiceBack.setBackUrl("");

            BillInfo billInfo = BeanUtil.copyProperties(billInfoObj, BillInfo.class);
            if (billInfo == null) {
                log.info("[重汽批量开票接口]报文格式错误!identity={}", identity);
                continue;
            }
            billInfo.setSource("2");

            // 4-获得请求实例，并且进行扣费
            IInvoiceApiService invoiceService = null;
            try {
                String serviceKey = serviceManageService.getCompanyServiceSupplier("invoice", companyservice.getCompanyid());
                serviceManageService.companyConsume("invoice", companyservice.getCompanyid());
                billInfo.setServiceSupplierKey(serviceKey);
                invoiceService = invoiceServiceFactory.getService(serviceKey);
            } catch (Exception e) {
                //invoiceBack.setResultCode("9999");
                //invoiceBack.setResultMsg("扣费失败！");
                log.info("[重汽批量开票接口]扣费失败!identity={},e={}", identity, e);
                continue;
            }

            // 5-开票
            try {

                try {
                    // 控制台问题，开票太快了会报9000错误，询问说添加一秒延时解决。
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // 处理中断异常
                    log.error("延时异常：{}",e.toString());
                }

                HXResponse resultHx = invoiceService.addInvoice(billInfo, companyservice);
                log.info("[重汽批量开票接口]开票identity={},返回结果result={}", identity, resultHx);

                if (!resultHx.isSuccess()) {

                    QueryWrapper<InvoiceBack> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("system_orderno", billInfo.getOutTradeOrderno());
                    InvoiceBack invoiceBackTemp = invoiceBackMapper.selectOne(queryWrapper);

                    if (invoiceBackTemp != null) {
                        invoiceBackTemp.setResultCode("9999");
                        invoiceBackTemp.setResultMsg(resultHx.getMessage());
                        invoiceBackTemp.setStatus("0");
                        invoiceBackTemp.setUpdateTime(new Date());
                        invoiceBackMapper.updateInvoiceBack(invoiceBackTemp);

                        invoiceService.callBackAisino(invoiceBackTemp, "", identity,0L);
                    } else {
                        invoiceBack.setResultCode("9999");
                        invoiceBack.setResultMsg(resultHx.getMessage());
                        invoiceBack.setSystemOrderno(billInfo.getOutTradeOrderno());
                        invoiceBack.setStatus("0");
                        invoiceBack.setCreateTime(new Date());
                        invoiceBackMapper.insertInvoiceBack(invoiceBack);

                        invoiceService.callBackAisino(invoiceBack, "", identity,0L);
                    }
                    log.info("[重汽批量开票接口]提交开票异常，开票失败!identity={},msg={}", identity, resultHx.getMessage());
                }

            } catch (Exception e) {

                QueryWrapper<InvoiceBack> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("system_orderno", billInfo.getOutTradeOrderno());
                InvoiceBack invoiceBackTemp = invoiceBackMapper.selectOne(queryWrapper);

                if (invoiceBackTemp != null) {
                    invoiceBackTemp.setResultCode("9999");
                    invoiceBackTemp.setResultMsg("开票失败!");
                    invoiceBackTemp.setStatus("0");
                    invoiceBackTemp.setUpdateTime(new Date());
                    invoiceBackMapper.updateInvoiceBack(invoiceBackTemp);

                    invoiceService.callBackAisino(invoiceBackTemp, "", identity, 0L);
                } else {
                    invoiceBack.setResultCode("9999");
                    invoiceBack.setResultMsg("开票失败!");
                    invoiceBack.setSystemOrderno(billInfo.getOutTradeOrderno());
                    invoiceBack.setStatus("0");
                    invoiceBack.setCreateTime(new Date());
                    invoiceBackMapper.insertInvoiceBack(invoiceBack);

                    invoiceService.callBackAisino(invoiceBack, "",  identity,0L);
                }

                log.info("[重汽批量开票接口]提交开票异常，开票失败!identity={},e={}", identity, e);
            }
        }
        
        
        /*RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        InvoiceMapper invoiceMapper = SpringUtils.getBean(InvoiceMapper.class);
        Thread.sleep(10 * 1000); // 睡眠10秒再去查询
        log.info("【定时任务】【发票查询】开始查询发票：{}", JSONObject.toJSONString(this.finalBillInfo));
        QueryBillInfoDTO queryBillInfoDTO = new QueryBillInfoDTO();
        queryBillInfoDTO.setFpqqlsh(this.finalBillInfo.getSystemOrderno());
        invoiceApiService.queryInvoice(queryBillInfoDTO, this.companyservice);

        // 获取发票
        Invoice invoice = invoiceMapper.selectBySystemOrderNo(this.companyservice.getCompanyid(), this.finalBillInfo.getSystemOrderno());
        if (invoice == null || StringUtils.equalsAny(Integer.toString(invoice.getState()), "0", "20")) {
            // 查询下失败队列，是否有次数
            String keys = "invoice_query_times_" + this.companyservice.getCompanyid() + "_" + this.finalBillInfo.getSystemOrderno();
            Integer queryTimes = redisCache.getCacheObject(keys);
            // 查询重试次数超过20次，就不查了
            if (queryTimes != null && queryTimes > 20) {
                log.error("【定时任务】【发票查询】发票信息始终不存在，不再进行查询：{}", JSONObject.toJSONString(this.finalBillInfo));
                redisCache.deleteObject(keys);
                return;
            }
            if (queryTimes == null) {
                queryTimes = 0;
            }
            queryTimes += 1;
            redisCache.setCacheObject(keys, queryTimes);
//            log.error("【定时任务】【发票查询】发票信息不存在或还在开票中，再次进入查询：{}", JSONObject.toJSONString(this.finalBillInfo));
//            AsyncManager.me().execute(new AddInvoiceBatchTask(this.finalBillInfo, companyservice, this.invoiceApiService));
        }

//        RedisQueueUtil.build().setData(invoice).onQueue("invoice_add_callback_consumer").retry(0).dispatch();*/




    }
}
