package com.ematou.wxservice.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ematou.wxservice.common.constant.WeChatConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

/**
 * 微信API请求工具类
 * @author lhm
 * @version 1.0
 * 2021-05-13 11:10
 */
@Component
public class WeChatApiRestTemplate {

    private static final Logger logger = LoggerFactory.getLogger(WeChatApiRestTemplate.class);

    @Autowired
    RestTemplate restTemplate;

    /**
     * 请求微信API，返回体带有errcode和errmsg字段的调这个方法
     * @param url       url地址
     * @param params    参数
     * @return          响应信息
     */
    public String getForRest(String url, Object...params) {
        String res;
        Integer errcode;
        String errmsg;
        try {
            res = restTemplate.getForObject(url, String.class, params);

            JSONObject response = JSON.parseObject(res);
            errcode = response.getObject(WeChatConstant.RESPONSE_ERROR_CODE, Integer.class);
            errmsg = response.getObject(WeChatConstant.RESPONSE_ERROR_MSG, String.class);
            if (errcode != 0 || !errmsg.equalsIgnoreCase(WeChatConstant.RESPONSE_OK)) {
                logger.error("请求微信API失败，请求方法：GET\nurl：\n" + url + "\n请求参数：" + Arrays.toString(params) + "\nerror code：" + errcode + "\nerror message：" + errmsg);
            }
        } catch (Exception e) {
            logger.error("请求微信API失败，请求方法：GET\nurl：\n" + url + "\n请求参数：" + Arrays.toString(params) + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：GET\nurl：\n" + url + "\n请求参数：" + Arrays.toString(params) + "\n异常信息：" + e.getMessage());
        }
        return res;
    }

    /**
     * 返回体不带有errcode和errmsg字段
     * @param url       url地址
     * @param params    参数
     * @return          响应信息
     */
    public String getForOther(String url, Object...params) {
        String res;
        try {
            res = restTemplate.getForObject(url, String.class, params);
        } catch (Exception e) {
            logger.error("请求微信API失败，请求方法：GET\nurl：\n" + url + "\n请求参数：" + Arrays.toString(params) + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：GET\nurl：\n" + url + "\n请求参数：" + Arrays.toString(params) + "\n异常信息：" + e.getMessage());
        }
        return res;
    }

    /**
     * 请求微信API，返回体带有errcode和errmsg字段的调这个方法
     * @param url       url地址
     * @param body      请求体
     * @return          响应信息
     */
    public String postForRest(String url, Object body) {
        String res;
        Integer errcode;
        String errmsg;
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            HttpEntity<Object> request = new HttpEntity<>(body, headers);
            res = restTemplate.postForObject(url, request, String.class);

            JSONObject response = JSON.parseObject(res);
            errcode = response.getObject(WeChatConstant.RESPONSE_ERROR_CODE, Integer.class);
            errmsg = response.getObject(WeChatConstant.RESPONSE_ERROR_MSG, String.class);
            if (errcode != 0 || !errmsg.equalsIgnoreCase(WeChatConstant.RESPONSE_OK)) {
                logger.error("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求体：" + body + "\nerror code：" + errcode + "\nerror message：" + errmsg);
            }
        } catch (Exception e) {
            logger.error("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求体：" + body + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求体：" + body + "\n异常信息：" + e.getMessage());
        }
        return res;
    }


    /**
     * 返回体不带有errcode和errmsg字段
     * @param url       url地址
     * @param body      请求体
     * @return          响应信息
     */
    public String postForOther(String url, Object body) {
        String res;
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            HttpEntity<Object> request = new HttpEntity<>(body, headers);
            res = restTemplate.postForObject(url, request, String.class);
        } catch (Exception e) {
            logger.error("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求体：" + body + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求体：" + body + "\n异常信息：" + e.getMessage());
        }
        return res;
    }

    /**
     * 上传永久素材
     * @author zhushouping
     * @since 1.0.0
     * @date 2023/8/15
     * @return
     */
    public String postByStream(String url, File file){

        BufferedReader reader = null;
        String result = null;
        try {
            URL urlObj = new URL(url);
            //连接
            HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setUseCaches(false); // post方式不能使用缓存

            // 设置请求头信息
            con.setRequestProperty("Connection", "Keep-Alive");
            con.setRequestProperty("Charset", "UTF-8");
            // 设置边界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

            // 请求正文信息
            // 第一部分：
            StringBuilder sb = new StringBuilder();
            sb.append("--"); // 必须多两道线
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"media\";filelength=\""
                    + file.length() + "\";filename=\"" + file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");
            byte[] head = sb.toString().getBytes("utf-8");
            // 获得输出流
            OutputStream out = new DataOutputStream(con.getOutputStream());
            // 输出表头
            out.write(head);

            // 文件正文部分
            // 把文件以流文件的方式 推入到url中
            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();
            // 结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
            out.write(foot);
            out.flush();
            out.close();
            StringBuffer buffer = new StringBuffer();
            // 定义BufferedReader输入流来读取URL的响应
            reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            if (result == null) {
                result = buffer.toString();
            }
        } catch (MalformedURLException e) {
            logger.error("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求文件：" + file.getName() + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求文件：" + file.getName() + "\n异常信息：" + e.getMessage());
        } catch (UnsupportedEncodingException e) {
            logger.error("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求文件：" + file.getName() + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求文件：" + file.getName() + "\n异常信息：" + e.getMessage());
        } catch (IOException e) {
            logger.error("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求文件：" + file.getName() + "\n异常信息：" + e.getMessage());
            throw new RuntimeException("请求微信API失败，请求方法：POST\nurl：\n" + url + "\n请求文件：" + file.getName() + "\n异常信息：" + e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return result;
    }

}
