package cn.qg.qaplatform.process;

import cn.qg.qaplatform.encrypt.kdsp.AESUtil;
import cn.qg.qaplatform.encrypt.kdsp.RSA;
import cn.qg.qaplatform.encrypt.yxm.DESUtils;
import cn.qg.qaplatform.utils.HttpClientUtils;
import cn.qg.qaplatform.entity.vo.EncryptRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jayway.jsonpath.JsonPath;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.net.URISyntaxException;
import java.util.*;

/**
 * 电商购买类
 * @author libo
 */
@Slf4j
public class Purchase {

    /**
     * kdsp 配置的私钥及 ios端对应的公钥
     * 以_kdsp 结尾的存在于kdsp 端，以_ios结尾的存在于ios端
     */
    static String private_key_ios_101_kdsp = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIZ/jCc0lcdcznjCybFPCGmI9oCnbvMzdCyta7X4Y4ygIOYAQ5vaNiPI2HAEh5X15jR/Cgr4x9YHLBuifKnJezWPmX+ZOYVFDwhlj7FkXS3TVyiuegykomdyg2LCpz06eyLAY+rMiz+ItqUGiemmqFZKfSD328VLaqCvRac5aWotAgMBAAECgYA8E1Kt3F4ee4S6Cf9/FFcklInOc3sqZEw6/IdE85q7oHaxZWLNhY1zNG4AsvVA9WILBsecmPzhy7hW66AVUqqWXA8jLIg/J3UyIRQo1sH9cX+3iERhNZluxXzxcX/UXrVQihyEFWZbehtpXFfPq1F7XzkTKy8qSodRLO79F8Tc/QJBAOF2vZ4Ah8GhiZP/KMYX7Q1fY5x/zTKmnNs1fJGDoRmgcF47Inzf2Ovjo+do/QdCf+Bzki6WG0AOpIHKksuw5r8CQQCYtttPfP8FKRxumcczNmkaKDWjrKElwRcGef5OuNBb7Crso9gUY+sL9/4kQHfmBfCS6KVbAA56RSdeSWFYZDYTAkA58pbRoTlDHw2JKC+Gmmem5Dlp478NoZz3Ckw16irht0aqMXCvv6i1GBDsTSObVhAf1BRiPNpMIHdPlI0eJR1pAkA7Oge6P0cEcFpHhrpb4UlHzLpo3QWuh8FvUJbRXxnn3KMVHcIqvkmlXauh0aLugfU4dKPUtCPpRbKr/ZeUWWEjAkAN5D5hH16RwrR6KN8W7t0gnlwOECPD8KbBQeWSja9r8C/yWMmr4RsWirBoDSYu4IG8jnrNcmYk8l1eAWmNyJWe";
    static String public_key_ios_101_ios = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGf4wnNJXHXM54wsmxTwhpiPaAp27zM3QsrWu1+GOMoCDmAEOb2jYjyNhwBIeV9eY0fwoK+MfWBywbonypyXs1j5l/mTmFRQ8IZY+xZF0t01cornoMpKJncoNiwqc9OnsiwGPqzIs/iLalBonppqhWSn0g99vFS2qgr0WnOWlqLQIDAQAB";


    /**
     * ios端配置的私钥 及 kdsp 端对应的公钥
     * 以_kdsp 结尾的存在于kdsp 端，以_ios结尾的存在于ios端
     */
    static String private_key_ios_101_ios = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAINPX+KdtJJYHHgLrurdJOK4mAGeP/RST69ATX1Ir4YBasxmIL7XMRtgJHjwrUZv7v3c4M/RQSSwUXQP5NLE7ns4uZUm/JZoG1zgmq43IqyuwTLlitwYn221DWToehmKp9uC1WhK84EfkCDtinqLA7Rslh9FrlKkVHyus2eONPm7AgMBAAECgYB43wzthqwcdj0mh+Ko0Y5NoQxTmP9YAJjXQoLSC6F+4jkUFAKaiW3rvDF2nl1yVEETsEnFIuMrSZ6BDsxc8+htb458A/kMXdyNvE1eaSnYd5Y0kPX+IyaX6+fTHfGF7SvEs4gHKJFW+G1UQ0veDTeUlNGQVwj5eVnAj+UhWuKWSQJBAN0SFsi/jnc5moqH7F/SNUKNtSCOhRaz/RjEdTjHHWpCYmK8RP+cfHJp4Cb7P/jG0XEFFQSS5FIjQn6ujAfiSH8CQQCYDqFjWxhViONtjnuovqBIKGxppk5SA22leSa53Bads26HKpsIHsFQvr3fXMe2BEUsGFYN20mlouQP7BHn1NDFAkBpJ0KJKHyWf2LgA/lONsm4p3kBTGlHvENmNYRghm2abosn1c+oGgIj1fKV+Cqcpc1XyggOTeSmoTju0w2ublb3AkAOt4PJQPzW8nvIk7zGNUUAFuF/TDhSWcCX/mTQIkwSEVbGQEpm+8sMDJoF703pAPrM7MIPb0Tughh+rgOBo6hdAkEAz7Q1UnZSwr2+2sgKUnMxUVCPTt/ImyWXukU8Uys8hT3i8XFex7dTaAd8XG3Zc77amaXvIBqxo5I6jKbzJCZUwA==";
    static String public_key_ios_101_kdsp = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDT1/inbSSWBx4C67q3STiuJgBnj/0Uk+vQE19SK+GAWrMZiC+1zEbYCR48K1Gb+793ODP0UEksFF0D+TSxO57OLmVJvyWaBtc4JquNyKsrsEy5YrcGJ9ttQ1k6HoZiqfbgtVoSvOBH5Ag7Yp6iwO0bJYfRa5SpFR8rrNnjjT5uwIDAQAB";

    static String deviceId = "D69C97EC-AC7F-4C5D-AC14-50933E990795";

    /**
     * 模拟IOS 端加密
     */
    public static EncryptRequest encryptOrderReq4IOS(String orderSubmitFormStr) throws Exception {

        String randomKey = AESUtil.getRandomKey();
        String orderSubmitReqAesEncrypt = AESUtil.encryptToBase64(orderSubmitFormStr, randomKey);
        String encryptKeyRsaEncrypt = RSA.encryptToBase64(randomKey, public_key_ios_101_ios);

        String appId = "101";
        String nonce = UUID.randomUUID().toString();
        String timeStamp = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");

        String content = nonce + appId + timeStamp + orderSubmitFormStr;
        String sign = RSA.sign(content, private_key_ios_101_ios);

        EncryptRequest request = new EncryptRequest();
        request.setAppId(appId);
        request.setNonce(nonce);
        request.setBody(orderSubmitReqAesEncrypt);
        request.setEncryptKey(encryptKeyRsaEncrypt);
        request.setSign(sign);
        request.setTimestamp(timeStamp);

        return request;
    }

    /**
     * 登录
     * @param namespace 环境
     * @param phoneNo 手机号
     * @return
     */
    public static String loginApp(String namespace, String phoneNo) {
        String url = "http://sappbackend-" + namespace + ".liangkebang.net/auth/fast-login";
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        headers.put("version", "7.9.00");
        headers.put("channel", 214);
        headers.put("appName", "xinyongqianbao");
        headers.put("idfa", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("device_id", deviceId);
        params.put("createdFrom", 214);
        params.put("username", phoneNo);
        params.put("vcode", "000000");
        JSONObject response = HttpClientUtils.doPost(url, params, headers);
        log.info("登录App：{}", response);
        return JsonPath.read(response, "$.token");
    }

    /**
     * 获取地址列表
     * @param namespace 环境
     * @param token 登录token
     * @return
     * @throws URISyntaxException
     */
    public static Integer getAddressList(String namespace, String token) throws URISyntaxException {
        String url = "http://talos-" + namespace + ".liangkebang.net/api/kdsp/addr/receiver/list";
        Map<String, Object> headers = new HashMap<>();
        headers.put("x-auth-token", token);
        JSONObject response = HttpClientUtils.doGetReturnJson(url, null, headers);
        log.info("获取地址列表响应：" + response);
        List<Map<String, Object>> addressIdList = JsonPath.read(response, "$.data.addrReceiverList[*].addrReceiverId");
        if (addressIdList.size() == 0) {
            return addAddress(namespace, token);
        }
        log.info("获取地址信息：" + response);
        return JsonPath.read(response, "$.data.addrReceiverList[0].addrReceiverId");
    }

    /**
     * 新增地址
     * @param namespace 环境
     * @param token
     * @return
     */
    public static Integer addAddress(String namespace, String token) {
        String url = "http://talos-" + namespace + ".liangkebang.net/api/kdsp/addr/receiver/add_edit";
        Map<String, Object> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("x-auth-token", token);
        headers.put("x-user-terminal", "IOS");
        Map<String, Object> params = new HashMap<>();
        params.put("cityId", "2800");
        params.put("provinceId", "1");
        params.put("countyId", "55816");
        params.put("townId", "");
        params.put("detail", "中国电子大厦B座");
        params.put("receiverName", "量化派");
        params.put("receiverPhoneNo", "18311069063");
        params.put("addrDefault", "1");
        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("新增地址：" + response);
        return JsonPath.read(response, "$.data.addrReceiverId");
    }

    /**
     * 确认订单
     * @param namespace 环境
     * @param token 用户token
     * @param skuNo sku no
     * @param addrReceiverId 地址id
     * @return
     */
    public static Map<String, Object> confirmOrder(String namespace, String token, String skuNo, Integer addrReceiverId) {
        String url = "http://talos-" + namespace + ".liangkebang.net/api/kdsp/shop-cart/order-confirm/page/v2";
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("x-auth-token", token);
        headers.put("x-user-terminal", "IOS");
        List<Map<String, Object>> skuList = new ArrayList<>();
        List<String> couponActivityUseIdList = new ArrayList<>();
        Map<String, Object> skuMap = new HashMap<>();
        skuMap.put("skuNum", 1);
        skuMap.put("skuSource", 1);
        skuMap.put("skuId", skuNo);
        skuList.add(skuMap);
        params.put("selectedSkuList", skuList);
        params.put("defaultUseCashCoupon", true);
        params.put("defaultUseFreightFeeCoupon", true);
        params.put("couponActivityUseIdList", couponActivityUseIdList);
        params.put("defaultUseActivityCoupon", true);
        params.put("defaultUseCoupon", true);
        params.put("addrReceiverId", addrReceiverId);
        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("确认订单返回结果：" + response);
        // 构造确认订单参数
        Map<String, Object> result = new HashMap<>();
        result.put("totalFreightFee", JsonPath.read(response, "$.data.calcFeeInfo.totalFreightFee").toString());
        result.put("totalFee", JsonPath.read(response, "$.data.calcFeeInfo.totalPayFee").toString());
        result.put("receiverId", addrReceiverId);
        List<Map<String, Object>> resultSkuList = new ArrayList<>();
        Map<String, Object> skuMap2 = new HashMap<>();
        skuMap2.put("skuNo", skuNo);
        skuMap2.put("count", 1);
        resultSkuList.add(skuMap2);
        result.put("skuList", resultSkuList);
        return result;
    }

    /**
     * 提交订单
     * @param namespace 环境
     * @param token token
     * @param params 请求参数
     * @return
     * @throws Exception
     */
    public static String submitOrder(String namespace, String token, Map<String, Object> params) throws Exception {
        String requestStr = JSON.toJSONString(params);
        log.info("确认订单加密前的数据：" + requestStr);
        String url = "http://talos-" + namespace + ".liangkebang.net/api/kdsp/order-info/e/submit";

        Map<String, Object> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        EncryptRequest request = encryptOrderReq4IOS(requestStr);
        log.info("确认订单加密后的数据：" + JSON.toJSONString(request));

        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(request), headers);
        log.info("提交订单返回结果：" + response);
        return JsonPath.read(response, "$.data.orderNo");
    }

    public static String queryPayStatus(String namespace, String token, String orderNo) {
        String url = "http://talos-" + namespace + ".liangkebang.net/open/checkout/pay_status/query";
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        params.put("orderNo", orderNo);

        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("支付状态返回：" + response);
        return JsonPath.read(response, "$.data.payStatus");
    }

    public static void openCheckout(String namespace, String token, String orderNo) {
        String url = "http://talos-" + namespace + ".liangkebang.net/open/checkout";
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();

        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        params.put("orderNo", orderNo);

        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("/open/checkOut返回响应：" + response);
    }

    public static void payReissueContract(String namespace, String token) {
        String url = "http://talos-" + namespace + ".liangkebang.net/open/checkout/payReissueContract";
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();

        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        List<String> templateIdList = new ArrayList<>();
        templateIdList.add("412");
        templateIdList.add("494");
        templateIdList.add("495");

        params.put("templateIdList", templateIdList);

        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("合同签署返回结果：" + response);
    }

    public static String checkoutPrePay(String namespace, String token, String orderNo) {
        String url = "http://talos-" +namespace + ".liangkebang.net/open/checkout/prepay";
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();

        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        params.put("orderNo", orderNo);
        params.put("payMethod", 1);

        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("预支付返回结果：" + response);
        return JsonPath.read(response, "$.data.flowOrderNo");
    }

    public static String vccAccountSalt(String namespace, String token) throws URISyntaxException {
        String url = "http://talos-" + namespace + ".liangkebang.net/vcc/account/salt";
        Map<String, Object> headers = new HashMap<>();

        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        JSONObject response = HttpClientUtils.doGetReturnJson(url, null, headers);
        log.info("vcc加盐返回结果：" + response);
        return JsonPath.read(response, "$.data.payPwdSalt");
    }

    public static Integer checkoutPay(String namespace, String token, String orderNo, String flowOrderNo, String payPwdSalt) {
        String url = "http://talos-" + namespace + ".liangkebang.net/open/checkout/pay";
        Map<String, Object> headers = new HashMap<>();

        headers.put("Content-Type", "application/json");
        headers.put("x-user-terminal", "IOS");
        headers.put("x-auth-token", token);
        headers.put("scDeviceId", "D69C97EC-AC7F-4C5D-AC14-50933E990795");
        headers.put("vccChannel", 214);
        headers.put("version", "7.9.00");
        headers.put("appName", "xinyongqianbao");

        Map<String, Object> params = new HashMap<>();
        params.put("orderNo", orderNo);
        params.put("flowOrderNo", flowOrderNo);
        params.put("password", DESUtils.encrypt("123456", payPwdSalt));

        JSONObject response = HttpClientUtils.doPostJson(url, JSON.toJSONString(params), headers);
        log.info("支付返回结果：" + response);
        return JsonPath.read(response, "$.data.creditPayInfo.creditPayStatus");
    }


    public static void main(String[] args) throws Exception {
        String namespace = "test1";
        String token = loginApp(namespace, "18300002000");
        Integer addressId = getAddressList(namespace, token);
        Map<String, Object> submitParams = confirmOrder(namespace, token, "26423184333313", addressId);
        String orderNo = submitOrder(namespace, token, submitParams);
        String payStatus = queryPayStatus(namespace, token, orderNo);
        openCheckout(namespace, token, orderNo);
        payReissueContract(namespace, token);
        String flowOrderNo = checkoutPrePay(namespace, token, orderNo);
        String payPwdSalt = vccAccountSalt(namespace, token);
        Integer creditPayStatus = checkoutPay(namespace, token, orderNo, flowOrderNo, payPwdSalt);
    }

}
