package com.chinacreator.process.job;

import com.alibaba.fastjson.JSON;
import com.chinacreator.process.dao.HuaweiWalletOrderDao;
import com.chinacreator.process.util.HttpInvoke;
import com.chinacreator.process.util.RsaUtil;
import com.chinacreator.process.util.URLUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

import java.net.URLEncoder;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class HuaweiWalletNotifyJob {

    private static Logger logger = Logger.getLogger("HuaweiWalletNotify");

    @Autowired
    private HuaweiWalletOrderDao huaweiWalletOrderDao;

    @Scheduled(cron = "0/10 * * * * *")
    public void doProcess() throws Exception{
        logger.info("开始处理华为钱包订单回调job");
        //获取表中需要订购的数据
        List<HashMap> dataList = huaweiWalletOrderDao.queryNotifyList();
        logger.info("获取数据条数" + dataList.size());
        if (dataList!=null&&dataList.size()>0){
            CountDownLatch threadSignal = new CountDownLatch(dataList.size());
            ExecutorService executorService = new ThreadPoolExecutor(10, 20, 10L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());

            for (HashMap<String,String> data : dataList){
                huaweiWalletOrderDao.updataQueryNotifyList(data.get("ID"),"2");
            }
            for (HashMap<String, String> data : dataList) {
                HuaweiWalletNotifyService continueService = new HuaweiWalletNotifyService(dataList.size(), threadSignal, data, huaweiWalletOrderDao);
                executorService.execute(continueService);
            }
            executorService.shutdown();
            try {
                executorService.awaitTermination(5L, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //每取一轮数据，休眠100毫秒
        Thread.sleep(100);
        try{
            //更新执行状态为2且执行时间超过10分钟的数据为待处理
            int res = huaweiWalletOrderDao.updExecTimeout();
            if(res > 0){
                logger.info("更新状态为2处理中且执行时间超过2分钟的数据为待处理的异常数据条数【"+res+"】");
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.info("更新状态为2处理中且执行时间超过2分钟的数据失败");
        }


        logger.info("结束华为钱包订单回调job");
    }

}

/**
 * 处理类
 * @author xinlong.liu
 * @date 20220721
 */
class HuaweiWalletNotifyService implements Runnable {

    private static Logger logger = Logger.getLogger("HuaweiWalletNotify");
    private int totalSize;
    private CountDownLatch threadSignal;
    private HuaweiWalletOrderDao huaweiWalletOrderDao;
    private HashMap<String,String> data; //订购数据

    public HuaweiWalletNotifyService(int totalSize,CountDownLatch threadSignal,HashMap<String,String> data,HuaweiWalletOrderDao huaweiWalletOrderDao){
        this.totalSize = totalSize;
        this.threadSignal = threadSignal;
        this.data = data;
        this.huaweiWalletOrderDao = huaweiWalletOrderDao;
    }

    @Override
    public void run() {
        String isnotify = "8000";
        String returnCode = "8000";
        String returnDesc = "回调出错";
        //组件回调参数
        HashMap<String,Object> logmap = new HashMap<String, Object>();
        HashMap<String,String> map = new HashMap<String, String>();
        logmap.put("data",data);
        int notifycount = 0;
        try{
            notifycount = Integer.parseInt(data.get("NOTIFYCOUNT"));
            String spOrderNo = data.get("ID");
            String orderNo = data.get("ORDERNO");
            String spid = data.get("HWSPID");
            String orderTime = data.get("ORDERTIME");
            String rechargeTime = data.get("RECHARGETIME");
            String status = data.get("STATUS");
            String phoneNumber = data.get("USERID");
            String productCode = data.get("SPID");
            String productType = data.get("PRODUCTYPE");
            String faceValue = data.get("FACEVALUE");
            String callbackParam1 = data.get("NOTIFYPARAM1");
            String callbackParam2 = data.get("NOTIFYPARAM2");
            String callbackParam3 = data.get("NOTIFYPARAM3");
            String signType = data.get("SIGNTYPE");
            String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            String notifyUrl = data.get("NOTIFYURL");
            logmap.put("url",notifyUrl);
            String signStr = signByRSA(data);
            logmap.put("签名原文signStr",signStr);

            map.put("spOrderNo",spOrderNo);
            map.put("orderNo",orderNo);
            map.put("spid",spid);
            map.put("orderTime",orderTime);
            map.put("rechargeTime",rechargeTime);
            map.put("status",status);
            map.put("phoneNumber",phoneNumber);
            map.put("productCode",productCode);
            map.put("productType",productType);
            map.put("faceValue",faceValue);
            map.put("callbackParam1",callbackParam1);
            map.put("callbackParam2",callbackParam2);
            map.put("callbackParam3",callbackParam3);
            map.put("signType",signType);
            map.put("timestamp",timestamp);
//                    http://testapi.mige.tv/univideo/huaweinotify
            String url = huaweiWalletOrderDao.getValue("huaweinotify");
            String sign = URLUtil.get(url+"?signStr="+ URLEncoder.encode(signStr));
            map.put("sign",sign);
            logmap.put("reqDate",map);
            Map headMap = new HashMap();
            headMap.put("certVersion","0");
            headMap.put("requestId",timestamp+ UUID.randomUUID().toString().replaceAll("-", "").substring(0, 7));
            logmap.put("headle",headMap);
            String res = "";
            if (notifyUrl.indexOf("https") != -1) {
                res = HttpInvoke.sendhttpsReq("POST", notifyUrl, JSON.toJSONString(map), headMap);
            } else {
                res = URLUtil.postJson(notifyUrl, JSON.toJSONString(map), 5000);
            }
//                    String res = URLUtil.postJson(notifyUrl, JSON.toJSONString(map),5000);
            logmap.put("res",res);
            com.alibaba.fastjson.JSONObject obj = JSON.parseObject(res);
            if("0".equals(obj.getString("returnCode"))){
                isnotify = "0";
                returnCode = "0";
                returnDesc = "success";
            }else {
                returnCode = obj.getString("returnCode");
                returnDesc = res;
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.info("回调出错："+e);
        }finally {
            logger.info(JSON.toJSONString(logmap));
            try {
                huaweiWalletOrderDao.updataQueryNotifyList(data.get("ID"),isnotify,notifycount+1,returnCode,returnDesc);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                logger.info("修改回调状态失败"+data.get("ID"));
            }
        }
    }

    /**
     * 生成签名原文
     * @param data
     * @return
     */
    public String signByRSA(HashMap<String,String> data) {
        String str = "";
        String spOrderNo = data.get("ID");
        String orderNo = data.get("ORDERNO");
        String spid = data.get("HWSPID");
        String orderTime = data.get("ORDERTIME");
        String rechargeTime = data.get("RECHARGETIME");
        String status = data.get("STATUS");
        String phoneNumber = data.get("USERID");
        String productCode = data.get("SPID");
        String productType = data.get("PRODUCTYPE");
        String faceValue = data.get("FACEVALUE");
        String callbackParam1 = data.get("CALLBACKPARAM1");
        String callbackParam2 = data.get("CALLBACKPARAM2");
        String callbackParam3 = data.get("CALLBACKPARAM3");
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        boolean flag = false;

        if (!StringUtils.isEmpty(callbackParam1)){
            str += "callbackParam1="+callbackParam1;
            flag =true;
        }
        if (!StringUtils.isEmpty(callbackParam2)){
            if (flag){
                str += "&callbackParam2="+callbackParam2;
            }else {
                str += "callbackParam2="+callbackParam2;
            }
            flag =true;
        }
        if (!StringUtils.isEmpty(callbackParam3)){
            if (flag){
                str += "&callbackParam3="+callbackParam3;
            }else {
                str += "callbackParam3="+callbackParam3;
            }
            flag = true;
        }
        if (!StringUtils.isEmpty(faceValue)){
            if (flag){
                str += "&faceValue="+faceValue;
            }else {
                str += "faceValue="+faceValue;
            }
        }
        if (!StringUtils.isEmpty(orderNo)){
            str += "&orderNo="+orderNo;
        }
        if (!StringUtils.isEmpty(orderTime)){
            str += "&orderTime="+orderTime;
        }
        if (!StringUtils.isEmpty(phoneNumber)){
            str += "&phoneNumber="+phoneNumber;
        }
        if (!StringUtils.isEmpty(productCode)){
            str += "&productCode="+productCode;
        }
        if (!StringUtils.isEmpty(productType)){
            str += "&productType="+productType;
        }
        if (!StringUtils.isEmpty(rechargeTime)){
            str += "&rechargeTime="+rechargeTime;
        }
        if (!StringUtils.isEmpty(spOrderNo)){
            str += "&spOrderNo="+spOrderNo;
        }
        if (!StringUtils.isEmpty(spid)){
            str += "&spid="+spid;
        }
        if (!StringUtils.isEmpty(status)){
            str += "&status="+status;
        }
        if (!StringUtils.isEmpty(timestamp)){
            str += "&timestamp="+timestamp;
        }
        return str;
    }
}
