package com.xinelu.applet.utils;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.xinelu.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Map;

/**
 * @Description 快递鸟物流查询工具类
 * @Author 纪寒
 * @Date 2022-11-01 13:43:03
 * @Version 1.0
 */
@Slf4j
public class LogisticsUtil {

    /**
     * 发送POST请求
     *
     * @param url    请求地址
     * @param params 请求参数
     * @return 返回结果信息
     * @throws Exception 异常信息
     */
    public static String sendPost(String url, Map<String, String> params) throws Exception {
        OutputStreamWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            //发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");
            //设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.connect();
            //获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
            StringBuilder param = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (param.length() > 0) {
                    param.append("&");
                }
                param.append(entry.getKey());
                param.append("=");
                param.append(entry.getValue());
            }
            out.write(param.toString());
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            log.error("调用快递鸟识别单号异常，异常信息：{}", e.getMessage());
            throw new ServiceException("查询物流信息出错，请联系管理员！");
        } finally {
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }
        }
        return result.toString();
    }

    /**
     * sign签名生成
     *
     * @param content  内容
     * @param keyValue ApiKey
     * @param charset  编码方式
     * @return 签名信息
     * @throws Exception 异常信息
     */
    public static String encrypt(String content, String keyValue, String charset) throws Exception {
        if (keyValue != null) {
            return base64(logisticsMd5(content + keyValue, charset), charset);
        }
        return base64(logisticsMd5(content, charset), charset);
    }

    /**
     * 编码格式信息
     *
     * @param content 内容
     * @param charset 字符集
     * @return 编码结果信息
     * @throws Exception 异常信息
     */
    public static String urlEncoder(String content, String charset) throws Exception {
        return URLEncoder.encode(content, charset);
    }

    /**
     * base64编码
     *
     * @param content 内容
     * @param charset 编码方式
     * @return 编码结果信息
     * @throws Exception 异常信息
     */
    public static String base64(String content, String charset) throws Exception {
        return Base64.encode(content.getBytes(charset));
    }

    /**
     * MD5加密
     *
     * @param content 内容
     * @param charset 编码方式
     * @return 结果
     * @throws Exception 异常信息
     */
    public static String logisticsMd5(String content, String charset) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(content.getBytes(charset));
        byte[] result = md.digest();
        StringBuilder sb = new StringBuilder(32);
        for (byte b : result) {
            int val = b & 0xff;
            if (val <= 0xf) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(val));
        }
        return sb.toString().toLowerCase();
    }
}
