package com.chinacreator.video.restful.controller;

import com.alibaba.fastjson.JSONObject;
import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.exception.BusinessException;
import com.chinacreator.video.restful.service.QueryUserAvaService;
import org.apache.commons.lang.StringUtils;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/queryUser")
public class QueryUserAvaController {

   //private final String PRI_KEY_PATH = QueryUserAvaController.class.getClassLoader().getResource("private_pkcs8.pem").getPath();
   //private String PUBLIC_KEY_PATH = QueryUserAvaController.class.getClassLoader().getResource("public_pkcs8.pem").getPath();
    private String PRI_KEY_PATH="private_pkcs8.pem";
    private String PUBLIC_KEY_PATH="public_pkcs8.pem";
    // 渠道密钥，腾讯提供，具体咨询产品经理
    @Value("${tencent.SECRET}")
    private  String SECRET ;
    // 接口名，此处为linlang
    @Value("${tencent.METHOD}")
   private  String METHOD ;
    // 渠道名，腾讯提供，具体咨询产品经理
    @Value("${tencent.CHANNEL}")
    private  String CHANNEL;
    private Logger log = Logger.getLogger("queryUserAva");

    @Autowired
    private QueryUserAvaService queryUserAvaService;
    @PostMapping("/avaInfo")
    public String queryUserInfo(@RequestBody String param) throws Exception {
        if (StringUtils.isEmpty(param)){
            throw new BusinessException("9001","参数不能为空");
        }
        OrderInfo orderInfo = JSONObject.parseObject(param, OrderInfo.class);
        //参数校验
        queryUserAvaService.busiCheck(orderInfo);
        String userid = orderInfo.getUserid();
        String privateKey = readFile(PRI_KEY_PATH);
        String publicKey = readFile(PUBLIC_KEY_PATH);
        PrivateKey pri = genPrivateKey(privateKey);
        PublicKey pub = genPublicKey(publicKey);

        Map<String, Object> map = new HashMap<>();
        String srcurl = null;
        String sign = null;
        try {
            String channelId = CHANNEL;
            String method = METHOD;
            long timestamp = System.currentTimeMillis() / 1000;
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("phone", userid);
            paramsMap.put("area_code", 86);
            String params = JSONObject.toJSONString(paramsMap);
            srcurl = "channel_id=" + channelId + "&method=" + method + "&params=" + params + "&timestamp=" + timestamp + "&" + this.SECRET;
            map.put("channel_id", channelId);
            map.put("method", method);
            map.put("params", params);
            map.put("timestamp", timestamp);
            sign = sign(srcurl, pri);
            map.put("sign", sign);
            log.info("请求参数:" + map);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("请求参数生成异常==="+e.getMessage());
            throw new BusinessException("8000","请求参数生成异常==="+e.getMessage());
        }
        // RSA验签
        boolean signBool = verify(srcurl, pub, sign);
        if (!signBool) {
            log.info( "验签失败");
            throw new BusinessException("1007", "验签失败");
        }
        String result = null;
        String url = queryUserAvaService.getTencentAvaUrl("tencentAvaUrl");
        try {
            result = sendPost(url, JSONObject.toJSONString(map));
        } catch (Exception e) {
            e.printStackTrace();
            log.info("调腾讯接口出现异常" + e.getMessage());
            throw new BusinessException("9001", "腾讯接口出现异常");
        }

        Map resultMap = JSONObject.parseObject(result, Map.class);
        resultMap.put("resultcode","0");
        resultMap.put("errorinfo","");
        Map msg = (Map) resultMap.get("msg");
        if (msg == null) {
            resultMap.put("resultcode","9002");
            resultMap.put("errorinfo","请求错误");
            return  JSONObject.toJSONString(resultMap);
        }
        Integer bindFlag = (Integer) msg.get("bind_flag");
        if (bindFlag == 0) {
            log.info("userid==="+userid+"======返回结果==="+resultMap);
            return  JSONObject.toJSONString(resultMap);
        }
        Map account = (Map) msg.get("account");
        account.put("avatar", URLDecoder.decode((String) account.get("avatar"), "GBK"));
        msg.put("account", account);
        resultMap.put("msg", msg);
        log.info("userid==="+userid+"======返回结果==="+resultMap);
        return JSONObject.toJSONString(resultMap);
    }


    /**
     * 从文件读取私钥和公钥
     * 私钥必须为pkcs8的格式，即以-----BEGIN PRIVATE KEY-----开头
     * 公钥可以为pkcs8也可以为pkcs1格式，两者内容相同
     *
     * @param filePath 文件路径
     * @return 私钥字符串或公钥字符串
     */
    private  String readFile(String filePath) {
        try {
            //InputStream in = new FileInputStream(filePath);
            InputStream in = this.getClass().getClassLoader().getResourceAsStream(filePath);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            StringBuilder buffer = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                if (line.charAt(0) != '-') {
                    buffer.append(line);
                }
            }
            return buffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 从公钥字符串生成公钥对象
     *
     * @param publicKey 公钥字符串
     * @return 公钥对象
     */
    public PublicKey genPublicKey(String publicKey) {
        try {
            byte[] bytes = new BASE64Decoder().decodeBuffer(publicKey);
            KeyFactory factory = KeyFactory.getInstance("rsa");
            X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
            return factory.generatePublic(spec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 从私钥字符串生成私钥对象
     *
     * @param privateKey 私钥字符串
     * @return 私钥对象
     */
    public  PrivateKey genPrivateKey(String privateKey) {
        try {
            byte[] bytes = new BASE64Decoder().decodeBuffer(privateKey);
            KeyFactory factory = KeyFactory.getInstance("rsa");
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
            return factory.generatePrivate(spec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 私钥签名，签名算法使用SHA256withRSA
     *
     * @param data       待签名数据
     * @param privateKey 私钥
     * @return 签名结果
     */
    public  String sign(String data, PrivateKey privateKey) throws Exception {
        byte[] keyBytes = privateKey.getEncoded();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey key = keyFactory.generatePrivate(keySpec);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(key);
        signature.update(data.getBytes());
        return new String(new sun.misc.BASE64Encoder().encode(signature.sign()).replaceAll("\\n",""));  // 对签名内容进行Base64编码加密
    }

    /**
     * 公钥验签，验签算法为SHA256withRSA
     *
     * @param srcData   原始字符串
     * @param publicKey 公钥
     * @param sign      签名
     * @return 是否验签通过
     */
    public boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
        byte[] keyBytes = publicKey.getEncoded();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey key = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(key);
        signature.update(srcData.getBytes());
        return signature.verify(new BASE64Decoder().decodeBuffer(sign)); // 对验签结果进行Base64编码解密
    }

    /**
     * 向指定URL发送POST方式的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数
     * @return URL 代表远程资源的响应
     */
    public String sendPost(String url, String param) {
        String result = "";
        try {
            URL realUrl = new URL(url);
            //打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            //设置通用的请求属性
            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/json");

            //conn.setRequestProperty("Host","vip.video.qq.com");
            //发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            //获取URLConnection对象对应的输出流
            PrintWriter out = new PrintWriter(conn.getOutputStream());
            //发送请求参数
            out.print(param);
            //flush输出流的缓冲
            out.flush();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result += "\n" + line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常" + e);
            e.printStackTrace();
        }
        return result;
    }

}