package com.dxhy.jxpt.baseService.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.dxhy.api.model.config.sys.SysEnterpriseConfigDto;
import com.dxhy.common.constant.CoreConstants;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.FplxEnum;
import com.dxhy.common.util.InvoiceUtil;
import com.dxhy.common.util.StringHelper;
import com.dxhy.common.util.pojo.Authorize;
import com.dxhy.common.util.pojo.BaseQueJson;
import com.dxhy.common.util.pojo.GlobalInfo;
import com.dxhy.jxpt.baseService.sign.dao.SignCheckLogDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

/**
 *
 * 调用接口查验发票
 *
 * @author jiaohongyang
 */
@Component("baseserviceInvoiceQueryUtil")
@Slf4j

public class InvoiceQueryUtil {

    /**
     * 查验接口调用成功状态码
     */
    private static final String QUERY_SUCC = "0000";

    /**
     * 查验结果一致状态码
     */
    private static final String DATA_SUCC = "0001";

    public static final String RESULT_CODE = "resultCode";
    public static final String RETURN_CODE = "returnCode";
    public static final String RESULT_TIP = "resultTip";

    @Resource
    private SignCheckLogDao checkDao;

    /**
     * 获取发票信息
     *
     * @param invoiceCode
     *            发票代码，不能为空
     * @param invoiceNo
     *            发票号码，不能为空
     * @param invoiceDate
     *            开票日期，不能为空
     * @param invoiceAmount
     *            金额，专票、机动车不能为空
     * @param checkCode
     *            校验码，其它票种不能为空
     * @return 返回
     *
     */
    public JSONObject queryInvoice(String invoiceCode, String invoiceNo, String invoiceDate, String invoiceAmount,
        String checkCode, String taxNo,String invoiceType) {

        JSONObject invoiceResult = new JSONObject();

        JSONObject queryResult =
            callQueryInterface(invoiceCode, invoiceNo, invoiceDate, invoiceAmount, checkCode, taxNo,invoiceType);
        if (queryResult != null) {
            JSONObject returnStateInfo = queryResult.getJSONObject("returnStateInfo");
            if (QUERY_SUCC.equals(returnStateInfo.get(RETURN_CODE))) {

                JSONObject dataResult = JSONObject.parseObject(Base64.decodeStr(queryResult.getString("data")));
                if (dataResult.containsKey(RESULT_CODE)) {
                    if (DATA_SUCC.equals(dataResult.get(RESULT_CODE))) {
                        // 查验成功且发票信息一致，直接返回
                        invoiceResult = dataResult;
                    } else {
                        // 返回错误码及错误信息
                        if (dataResult.containsKey(RESULT_TIP)
                            && !StringHelper.isBlank(dataResult.getString(RESULT_TIP))) {
                            invoiceResult.put("returnCode", dataResult.get(RESULT_CODE));
                            invoiceResult.put("returnMessage", dataResult.getString(RESULT_TIP));
                            if(StringUtils.isNotEmpty(dataResult.getString("invoiceType"))){
                                invoiceResult.put("invoiceType", dataResult.getString("invoiceType"));
                            }
                        } else {
                            invoiceResult.put("returnCode", "2011");
                            invoiceResult.put("returnMessage", "其它异常");
                        }
                    }
                } else {
                    invoiceResult.put("returnCode", "2011");
                    invoiceResult.put("returnMessage", "其它异常");
                }
            } else {
                invoiceResult = returnStateInfo;
            }
        }
        return invoiceResult;
    }

    /**
     * 调用互联网查验接口获取发票信息
     *
     * @param invoiceCode
     *            发票代码，不能为空
     * @param invoiceNo
     *            发票号码，不能为空
     * @param invoiceDate
     *            开票日期，不能为空
     * @param invoiceAmount
     *            金额，专票、机动车不能为空
     * @param checkCode
     *            校验码，其它票种不能为空
     * @return 异常
     */
    private JSONObject callQueryInterface(String invoiceCode, String invoiceNo, String invoiceDate,
        String invoiceAmount, String checkCode, String taxNo,String invoiceType) {
        JSONObject invoiceResult = new JSONObject();
        String collectDataStr;
        // 请求通用头
        GlobalInfo globalInfo = new GlobalInfo();
        // 请求通用
        Authorize authorize = new Authorize();
        BaseQueJson bqj = new BaseQueJson();

        DynamicContextHolder.push(DbConstant.BASICS_READ);
        //根据标识判断是否需要获取数据库权限数据
        if(CoreConstants.enterprisePermissionFlag){
            SysEnterpriseConfigDto deptEntity = checkDao.findIdAndKey(taxNo);
            if(deptEntity!=null){
                CoreConstants.aceId= deptEntity.getAceId();
                CoreConstants.aceKey= deptEntity.getAceKey();
            }
        }
        try {
            InvoiceUtil iu = new InvoiceUtil(invoiceCode);
            JSONObject requestData = new JSONObject();
            requestData.put("buyerTaxNo", taxNo);
            if(FplxEnum.QDZZP.getFplxDm().equals(invoiceType) || FplxEnum.QDPP.getFplxDm().equals(invoiceType)){
                requestData.put("invoiceType", "31");
                requestData.put("invoiceCode", "");
            }else {
                requestData.put("invoiceType", iu.getFplxdm());
                requestData.put("invoiceCode", invoiceCode);
            }
            requestData.put("invoiceNo", invoiceNo);
            requestData.put("invoiceDate", invoiceDate.replaceAll("-", ""));
            requestData.put("invoiceAmount", invoiceAmount);
            requestData.put("checkCode", checkCode);

            String dataStr = requestData.toJSONString();
            String base64Data = Base64.encode(dataStr);

            // 封装参数
            globalInfo.setAppId(CoreConstants.appId);
            globalInfo.setVersion(CoreConstants.version);
            String exchangeId = getDataExchangeId();
            globalInfo.setDataExchangeId(exchangeId);
            globalInfo.setInterfaceCode(CoreConstants.invoiceCheckOne);
            globalInfo.setEnterpriseCode(CoreConstants.enterpriseCode);
            authorize.setAppSecId(CoreConstants.aceId);

            String appSec =
                makeAppSec(base64Data, exchangeId, CoreConstants.invoiceCheckOne,CoreConstants.aceId, CoreConstants.aceKey);
            authorize.setAppSec(appSec);
            bqj.setData(base64Data);
            bqj.setAuthorize(authorize);
            bqj.setGlobalInfo(globalInfo);
            collectDataStr = JSONObject.toJSONString(bqj);
            log.debug("查验封装参数：" + collectDataStr);
            log.info("请求地址:{}",CoreConstants.collectUrl);
            String responseJson = HttpUtil.post(CoreConstants.collectUrl, collectDataStr, 30000);
            if (StringHelper.isBlank(responseJson)) {
                JSONObject returnStateInfo = new JSONObject();
                returnStateInfo.put("returnCode", "2011");
                returnStateInfo.put("returnMessage", "其它异常");
                invoiceResult.put("returnStateInfo", returnStateInfo);
            } else {
                invoiceResult = JSONObject.parseObject(responseJson);
            }
            log.debug("查验返回结果：" + responseJson);
        } catch (Exception e) {
            log.error("调用查验接口出错！", e);
            JSONObject returnStateInfo = new JSONObject();
            returnStateInfo.put("returnCode", "2011");
            returnStateInfo.put("returnMessage", "其它异常");
            invoiceResult.put("returnStateInfo", returnStateInfo);
        }
        return invoiceResult;
    }

    /**
     * 获取时间戳
     *
     * @return String
     */
    public String getDataExchangeId() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        StringBuilder sb = new StringBuilder();
        Random rand = new Random();
        int count = 9;
        for (int i = 0; i < count; i++) {
            sb.append(rand.nextInt(10));
        }
        String data = sb.toString();
        return CoreConstants.enterpriseCode + simpleDateFormat.format(new Date()) + data;
    }

    /**
     * 加密方法
     */
    public String makeAppSec(String data, String dataExchangeId, String interfaceCode, String secretId,
        String secretKey) {
        String srcStr =
            "POST/rest/invoice/dii?authorize={\"appSecId\":\"" + secretId + "\"}&globalInfo={\"appId\":\"" + CoreConstants.appId
                + "\",\"version\":\"" + CoreConstants.version + "\",\"interfaceCode\":\"" + interfaceCode + "\",\"enterpriseCode\":\""
                + CoreConstants.enterpriseCode + "\",\"dataExchangeId\":\"" + dataExchangeId + "\"}&" + "data=" + data + "";
        log.info("待加密的请求：" + srcStr);
        String appSec = null;
        SecretKeySpec keySpec;
        Mac mac;
        try {
            keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
            mac = Mac.getInstance("HmacSHA1");
            mac.init(keySpec);
            byte[] singBytes;
            singBytes = mac.doFinal(srcStr.getBytes(StandardCharsets.UTF_8));
            appSec = Base64.encode(singBytes);
        } catch (Exception e) {
           log.info("业务处理异常：{}", e);
        }
        return appSec;
    }
}
