package com.iflytek.aicloud.http;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.iflytek.aicloud.common.sign.Hmac256Signature;
import com.iflytek.aicloud.common.util.AuthUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.SignatureException;
import java.util.Base64;
import java.util.Map;

public class AppClient {
    private static final Logger logger = LoggerFactory.getLogger(AppClient.class);
    public static final int STATUS = 3;
    private static String resourcePath;


    private final String appId;
    private final String apiKey;
    private final String apiSecret;
    private final String host;

    static {
        try {
            resourcePath = AppClient.class.getResource("/").toURI().getPath();
            if (resourcePath != null) {
                resourcePath = resourcePath.replaceAll("target/classes", "src/main/resources");
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
    public AppClient(String appId, String apiKey, String apiSecret, String host) {
        this.appId = appId;
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
        this.host = host;
    }


    public String doRequest(JSONObject requestData, Map<String, String> requestPathMap) throws IOException, SignatureException {
        URL realUrl = new URL(buildAuthRequestUrl());
        URLConnection connection = realUrl.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
        httpURLConnection.setDoInput(true);
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Content-type","application/json");

        OutputStream out = httpURLConnection.getOutputStream();
        String newRequestData = this.buildRequestData(requestData, requestPathMap);
        out.write(newRequestData.getBytes());
        out.flush();

        logger.info("send data is :{}", newRequestData);

        InputStream is;
        try{
            is = httpURLConnection.getInputStream();
        }catch (Exception e){
            is = httpURLConnection.getErrorStream();
            logger.error("request message is {}, code is:{}", httpURLConnection.getResponseMessage(), readAllBytes(is));
        }

        String respData = readAllBytes(is);
        logger.info("respData:{}", respData);
        return respData;
    }

    /**
     * 生成鉴权接口url
     */
    public String buildAuthRequestUrl() throws MalformedURLException, SignatureException {
        Hmac256Signature signature = new Hmac256Signature(this.apiKey, this.apiSecret, this.host, "POST");
        return AuthUtil.generateRequestUrl(signature);
    }

    /**
     * 构造请求数据
     */
    public String buildRequestData(JSONObject requestData, Map<String, String> requestPathMap) throws IOException {
        for (Map.Entry<String, String> entry : requestPathMap.entrySet()) {
            String jsonPath = entry.getKey();
            String filePath = entry.getValue();

            File file = new File(resourcePath + filePath);
            byte[] fileByteFromFile = FileUtils.readFileToByteArray(file);

            JSONPath.set(requestData, jsonPath, Base64.getEncoder().encodeToString(fileByteFromFile));
            String statusJsonPath = jsonPath.substring(0, jsonPath.lastIndexOf(".")) + ".status";
            JSONPath.set(requestData, statusJsonPath, STATUS);
        }

        JSONPath.set(requestData, "$.header.app_id", this.appId);
        JSONPath.set(requestData, "$.header.status", STATUS);

        return requestData.toString();
    }

    /**
     * 将流中的数据转化为String
     */
    private String readAllBytes(InputStream is) throws IOException {
        return IOUtils.toString(is, StandardCharsets.UTF_8);
    }
}
