package com.jianshui.income.utils.elephant;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.jianshui.common.core.domain.entity.Companyservice;
import com.jianshui.common.core.redis.RedisCache;
import com.jianshui.common.exception.jianshui.JianshuiServiceConfigErrorException;
import com.jianshui.common.exception.jianshui.JianshuiServiceException;
import com.jianshui.common.utils.StringUtils;
import com.jianshui.common.utils.jianshui.CommonUtils;
import com.jianshui.common.utils.http.HttpUtils;
import com.jianshui.common.utils.spring.SpringUtils;
import com.jianshui.income.constant.elephant.ElephantConstants;
import com.jianshui.system.domain.CompanyserviceProp;
import com.jianshui.system.mapper.CompanyserviceMapper;
import com.jianshui.system.service.ICompanyservicePropService;
import com.jianshui.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.core.env.Environment;
import sun.misc.BASE64Encoder;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.codec.binary.Base64;

/**
 * @Description 大象销项工具类 ，没有区分多用户
 * @Author 巩权林
 * @Date 2022-03-24 11:32
 **/
@Slf4j
public class ElephantUtils {


    private static String ELE_CHECK_URL;
    private static String ELE_CHECK_ENTCODE;

    static {
        Environment environment = SpringUtils.getBean(Environment.class);
        ELE_CHECK_URL = environment.getProperty("ele_check_url");
        ELE_CHECK_ENTCODE = environment.getProperty("elephant_entcode_check");
    }
    /**
     * 大象请求 云端版
     *
     * @param uri
     * @param data
     * @param devMode
     * @return
     */
    public static JSONObject sendRequest(String uri, JSONObject data, boolean devMode) {
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);

        boolean isDevMode = CommonUtils.isDevMode();

        /*String host = ElephantConstants.PROD_HOST;
        if (isDevMode || devMode) {
            host = ElephantConstants.DEV_HOST;
        }*/
        String url = ELE_CHECK_URL + uri;

        String token = getToken(devMode);
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        url += "?access_token=" + token; // 拼接token

        // 先处理下请求体
        JSONObject requestBody = new JSONObject();
        /*String entCode = configService.selectConfigByKey("elephant_entcode");
        requestBody.put("entCode", entCode);*/
        requestBody.put("entCode", ELE_CHECK_ENTCODE);
        requestBody.put("zipCode", 0); // 不压缩
        requestBody.put("encryptCode", 0); // 不加密

        // 处理下数据交换流水号
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String dataExchangeId = df.format(new Date());
        String randomString = Long.toString((long) (Math.random() * 9 * Math.pow(10, 14)) + (long) Math.pow(10, 14));
        requestBody.put("dataExchangeId", dataExchangeId + randomString); // 数据交换流水号
        BASE64Encoder encoder = new BASE64Encoder();
        byte[] contentByte = data.toJSONString().getBytes();

        requestBody.put("content", encoder.encode(contentByte));
        JSONObject result = null; // 返回的结果
        String stringRequest = "";
        HttpClient httpclient = null;
        PostMethod post = null;
        try {
            // 构造请求String
            stringRequest = requestBody.toJSONString();
            RequestEntity se = new StringRequestEntity(stringRequest, "application/json", "UTF-8");
            // 开始构造请求体
            httpclient = new HttpClient();
            post = new PostMethod(url);
            //设置编码方式
            post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
            // 设置请求体
            post.setRequestEntity(se);
            //执行
            httpclient.executeMethod(post);
            //接口返回信息
            InputStream inputStream = post.getResponseBodyAsStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            StringBuffer stringBuffer = new StringBuffer();
            String str = "";
            while ((str = br.readLine()) != null) {
                stringBuffer.append(str);
            }
            result = JSONObject.parseObject(stringBuffer.toString());
        } catch (Exception e) {
            result = null;
            e.printStackTrace();
            log.error("【销项】【大象接口】调用HttpsUtil.sendToNuoNuo Exception, url=" + url + ",request=" + stringRequest, e);
        } finally {
            //关闭连接，释放资源
            post.releaseConnection();
            ((SimpleHttpConnectionManager) httpclient.getHttpConnectionManager()).shutdown();
        }

        return result;
    }

    public static String getToken(boolean devMode) {
        RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        JSONObject temp = redisCache.getCacheObject(ElephantConstants.TOKEN_REDIS_KEY);

        // 如果不为空，且没有过期
        if (temp != null) {
            /*Long exprieTimeTemp = (Long) temp.get("exprieTime");
            if (System.currentTimeMillis() < exprieTimeTemp) {
                return (String) temp.get("access_token");
            }*/
            return (String) temp.get("access_token");
        }
        String appkey = configService.selectConfigByKey("elephant_appkey");
        if (appkey == null || "".equals(appkey)) {
            throw new JianshuiServiceConfigErrorException("未配置大象app key！");
        }
        String appSecret = configService.selectConfigByKey("elephant_secret");
        if (appSecret == null || "".equals(appSecret)) {
            throw new JianshuiServiceConfigErrorException("未配置大象app secret！");
        }
        boolean isDevMode = CommonUtils.isDevMode();

        /*String url = ElephantConstants.PROD_TOKEN_HOST;
        if (isDevMode || devMode) {
            url = ElephantConstants.DEV_TOKEN_HOST;
        }*/

        String url = ELE_CHECK_URL + "authen/token";

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appKey", appkey);
        jsonObject.put("appSecret", appSecret);
        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json");
        String info = HttpUtils.sendJsonPost(url, jsonObject, header);
        JSONObject obj = JSONObject.parseObject(info);
        /*Long exprieTime = System.currentTimeMillis();
        exprieTime = exprieTime + (int) obj.get("expires_in") * 1000L; // 过期时间
        obj.put("exprieTime", exprieTime);*/
        redisCache.setCacheObject(ElephantConstants.TOKEN_REDIS_KEY, obj,(int) obj.get("expires_in") - 60, TimeUnit.SECONDS);
        return (String) obj.get("access_token");
    }

    /**
     * 大象请求 大象部署版 1.2.4 无token
     *
     * @param uri            请求uri
     * @param methodName     文档里的"接口方法"
     * @param data           请求体
     * @param companyservice companyservice
     * @return
     */
    public static JSONObject sendRequestWithoutToken(String uri, String methodName, JSONObject data, Companyservice companyservice, boolean devMode) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        ICompanyservicePropService companyserviceProp = SpringUtils.getBean(ICompanyservicePropService.class);
        CompanyserviceProp secretIdProp = companyserviceProp.selectPropByKey(companyservice.getCompanyid(), "elephant_secret_id");
        if (secretIdProp == null) {
            throw new JianshuiServiceException("企业未配置属性，请联系管理员！");
        }
        String secretId = secretIdProp.getValue();
        CompanyserviceProp sercretKeyProp = companyserviceProp.selectPropByKey(companyservice.getCompanyid(), "elephant_secret_id");
        if (sercretKeyProp == null) {
            throw new JianshuiServiceException("企业未配置属性，请联系管理员！");
        }
        String sercretKey = secretIdProp.getValue();
        boolean isDevMode = CommonUtils.isDevMode();

        /*String host = ElephantConstants.PROD_HOST;
        if (isDevMode) {
            host = ElephantConstants.DEV_HOST;
        }*/
        String url = ELE_CHECK_URL + uri;

        String token = getToken(devMode);
        if (token == "") {
            return null;
        }
        // url += "?access_token=" + token; // 拼接token

        // 先处理下请求体
        JSONObject requestBody = new JSONObject();
        BASE64Encoder encoder = new BASE64Encoder();
        byte[] contentByte = data.toJSONString().getBytes();

        int randomInt = RandomUtil.randomInt(10, 100);
        requestBody.put("Nonce", Integer.toString(randomInt));
        requestBody.put("SecretId", secretId);
        requestBody.put("Timestamp", DateUtil.currentSeconds());
        requestBody.put("content", encoder.encode(contentByte));
        requestBody.put("encryptCode", 0); // 不加密
        requestBody.put("zipCode", 0); // 不压缩
        Iterator it = requestBody.keySet().iterator();
        String query = "";
        while (it.hasNext()) {
            String key = (String) it.next();
            String value = requestBody.getString(key);
            query += "&" + key + "=" + value;
        }
        query = StrUtil.removePrefix(query, "&");
        query = query.replace("_", ".");
        query = "POST" +
                ELE_CHECK_URL.replace("http://", "").replace("https://", "") +
                uri +
                methodName +
                query;
        String srcStr = query;
        SecretKeySpec keySpec = new SecretKeySpec(sercretKey.getBytes("UTF-8"), "HmacSHA1");
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(keySpec);
        byte[] signBytes = mac.doFinal(srcStr.getBytes("UTF-8"));
        String sign = Base64.encodeBase64URLSafeString(signBytes);
        requestBody.put("Signature", sign);

        JSONObject result = null; // 返回的结果
        String stringRequest = "";
        HttpClient httpclient = null;
        PostMethod post = null;
        try {
            // 构造请求String
            while (it.hasNext()) {
                String key = (String) it.next();
                String value = requestBody.getString(key);
                stringRequest += "&" + key + "=" + value;
            }
            stringRequest = StrUtil.removePrefix(query, "&");
            // RequestEntity se = new StringRequestEntity(stringRequest, "application/json", "UTF-8");
            // 开始构造请求体
            httpclient = new HttpClient();
            post = new PostMethod(url);
            //设置编码方式
            post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
            // 设置请求体
            // post.setRequestEntity(se);
            //执行
            httpclient.executeMethod(post);
            //接口返回信息
            InputStream inputStream = post.getResponseBodyAsStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            StringBuffer stringBuffer = new StringBuffer();
            String str = "";
            while ((str = br.readLine()) != null) {
                stringBuffer.append(str);
            }
            result = JSONObject.parseObject(stringBuffer.toString());

        } catch (Exception e) {
            result = null;
            e.printStackTrace();
            log.error("【销项】【大象接口】调用HttpsUtil.sendToNuoNuo Exception, url=" + url + ",request=" + stringRequest, e);
        } finally {
            //关闭连接，释放资源
            post.releaseConnection();
            ((SimpleHttpConnectionManager) httpclient.getHttpConnectionManager()).shutdown();
        }

        return result;
    }
}
