package org.dromara.settlement.common.bank.zhaoshang;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.HashMap;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.GsonBuilder;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.settlement.api.domain.Result;
import org.dromara.settlement.service.impl.ZhaoShangServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



public class ZhaoShangUtil {
	private static final Logger log = LoggerFactory.getLogger(ZhaoShangUtil.class);

	private static class SingletonHolder {
		private static final ZhaoShangUtil INSTANCE = new ZhaoShangUtil();
	}

	private ZhaoShangUtil() {
		Security.addProvider(new BouncyCastleProvider());
	}

	public static final ZhaoShangUtil getInstance() {
		return SingletonHolder.INSTANCE;
	}

    public static void main(String[] args) {
        new ZhaoShangServiceImpl().createAccount(0,"1", "1", "1");
    }

    public Result<String> request(ZhaoShangConfig config, String funcode, String reqid, JsonObject body) {
    	// AES加密
		String AesPlainxt = "";
		String res = "";
		try {
			JsonObject jObject = new JsonObject();
			JsonObject head = new JsonObject();
			head.addProperty("funcode", funcode);
			head.addProperty("userid", config.UID);
			head.addProperty("reqid", reqid);
			JsonObject request = new JsonObject();
			request.add("body", body);
			request.add("head", head);
			jObject.add("request", request);

			JsonObject object = new JsonObject();
			// 签名
			object.addProperty("sigdat", "__signature_sigdat__");
			// object.put("sigtim", GetTime());

			object.addProperty("sigtim",  DCHelper.getTime());
			jObject.add("signature", object);
			String source = DCHelper.serialJsonOrdered(jObject);
			log.info("签名原文: " + source);
			//String data = signRsa2048(getPrivateKeyFromBytes(config.prikeyStr, "PKCS"),source.getBytes());
			String data = new String(java.util.Base64.getEncoder().encode(DCCryptor.CMBSM2SignWithSM3(getID_IV(config.UID), java.util.Base64.getDecoder().decode(config.prikeyStr), source.getBytes(StandardCharsets.UTF_8))));
			log.info("签名结果: " + data);
			object.addProperty("sigdat", data);
			//jObject.put("signature", object);

			AesPlainxt = DCHelper.serialJsonOrdered(jObject);
			log.info("加密前req:  " + AesPlainxt);
			//String req = encryptAES256Str(AesPlainxt, config.AESKEY.getBytes());
			String req = new String(java.util.Base64.getEncoder().encode(DCCryptor.CMBSM4EncryptWithCBC(config.AESKEY.getBytes(), getID_IV(config.UID), AesPlainxt.getBytes(StandardCharsets.UTF_8))));
			log.info("加密后req:  " + req);

			// 发送请求
			HashMap<String, String> map = new HashMap<>();
			map.put("UID", config.UID);
			map.put("DATA", URLEncoder.encode(req, "utf-8"));
			map.put("FUNCODE", funcode);
	        map.put("ALG", "SM");
			res = DCHelper.doPostForm(config.URL, map);
			log.info("res:  " + res);
		} catch (Exception e) {
            e.printStackTrace();
			// TODO 自动生成的 catch 块
			log.error("招商银行api调用出错（"+ JSONObject.toJSONString(config)+","+funcode+","+reqid+","+JSONObject.toJSONString(body)+"）：",e);
		}
        Result<String> rtn = new Result<String>();
        rtn.setResult(AesPlainxt);
        rtn.setRtnData(res);
        return rtn;
    }

    public Result<ZhaoShangResponse> response(ZhaoShangConfig config,String response){
        // 解密请求
    	Result<ZhaoShangResponse> rtn = new Result<ZhaoShangResponse>();
    	if (StringUtils.isBlank(response)) {
    		rtn.addError("响应内容不能为空");
    		return rtn;
		}
        try {
			//String resplain = decryptAES256(response, config.AESKEY.getBytes(), true);
        	String resplain = new String(DCCryptor.CMBSM4DecryptWithCBC(config.AESKEY.getBytes(), getID_IV(config.UID), java.util.Base64.getDecoder().decode(response)), StandardCharsets.UTF_8);
			rtn.setResult(response);
			log.info("res decrypt: " + resplain);
			JsonObject object2 = new GsonBuilder().create().fromJson(resplain, JsonObject.class);
			JsonObject object3 = object2.getAsJsonObject("signature");
			String resSign = object3.get("sigdat").getAsString();
			object3.addProperty("sigdat", "__signature_sigdat__");
			object2.add("signature", object3);
			String resSignSource = DCHelper.serialJsonOrdered(object2);
			log.info("验签原文: " + resSignSource);
			rtn.setResult(resSignSource);
			log.info("验签签名值: " + resSign);
			//Boolean verify = signRsa2048Verify(resSignSource.getBytes(), Base64.decode(resSign), getPublicKeyFromBytes(config.pubkeyStr));
			Boolean verify = DCCryptor.CMBSM2VerifyWithSM3(getID_IV(config.UID), java.util.Base64.getDecoder().decode(config.pubkeyStr), resSignSource.getBytes(StandardCharsets.UTF_8), java.util.Base64.getDecoder().decode(resSign));
			log.info("验签结果: " + verify);
			if (verify) {
				JsonObject responseObj = object2.getAsJsonObject("response");
				JsonObject responseHead = responseObj.getAsJsonObject("head");
				ZhaoShangResponse data = new ZhaoShangResponse();
				data.setData(responseObj.getAsJsonObject("body"));
				data.setReqid(responseHead.get("reqid").getAsString());
				data.setResultcode(responseHead.get("resultcode").getAsString());
				data.setResultmsg(responseHead.get("resultmsg").getAsString());
				rtn.setRtnData(data);
			}else {
				rtn.addError("验签失败");
			}
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			log.error("解析招商银行响应出错（"+JSONObject.toJSONString(config)+","+response+"）：",e);
		}
        return rtn;
    }

    private byte[] getID_IV(String uid) {
        String userid = uid + "0000000000000000";
        return userid.substring(0, 16).getBytes();
    }
}
