package com.heyu.api.baidu;


import com.heyu.api.baidu.request.*;
import com.heyu.api.data.constants.ApiConstants;
import com.heyu.api.data.constants.RedisConstans;
import com.heyu.api.data.utils.ApiR;
import com.heyu.api.data.utils.RedisUtils;
import com.heyu.api.data.utils.SpringContextUtils;
import com.heyu.api.data.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;

@Slf4j
public abstract class BaiduBaseHandle<P, Result> {

    public final static List<String> trueOrFalse = Arrays.asList("true", "false");


    public final static OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
    /**
     * 获取uri
     */
    public abstract String getUri();

    /**
     * 较验参数
     */
    public abstract String check(P p);

    /**
     * 获取内容
     */
    public abstract String getContent(P p);

    public ApiR<Result> handle(P p, Class... resultClazz) {
        String result = null;
        try {
            String error = check(p);
            if (StringUtils.isNotBlank(error)) {
                log.error("BaseBaiduHandle check:{}", error);
                return ApiR.error(error);
            }

            String content = getContent(p);
            if (StringUtils.isBlank(content)) {
                log.error("请求内容为空，未知异常:{}", error);
                return ApiR.error("请求内容为空，未知异常");
            }
            if (content.startsWith("&")) {
                content = content.substring(1);
            }

            Request request = createRequest(content);

            Response response = HTTP_CLIENT.newCall(request).execute();
            result = response.body().string();
            Object resp = result(result);
            if (resp != null) {
                return ApiR.setData(resp);
            }

            Class clazz = this.getClass();
            //getGenericSuperclass()获得带有泛型的父类
            //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
            Type type = clazz.getGenericSuperclass();
            //ParameterizedType参数化类型，即泛型
            ParameterizedType parameterizedType = (ParameterizedType) type;
            //getActualTypeArguments获取参数化类型的数组，泛型可能有多个
            if (parameterizedType.getActualTypeArguments() != null && parameterizedType.getActualTypeArguments().length == 2) {
                Class p1 = (Class) parameterizedType.getActualTypeArguments()[1];
                Result data = (Result) com.alibaba.fastjson.JSONObject.parseObject(result, p1);
                return ApiR.setData(data);
            }

            return null;
        } catch (IOException e) {
            log.error("BaseBaiduHandle 异常", e);
        } finally {
            log.info("BaseBaiduHandle result :{}", result);
        }
        log.error("BaseBaiduHandle handle 没有返回值。");
        return null;
    }

    /***
     * 创建create
     * @param content
     * @return
     */
    public Request createRequest(String content){
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        // image 可以通过 方法获取,如果Content-Type是application/x-www-form-urlencoded时,第二个参数传true
        RequestBody body = RequestBody.create(mediaType, content);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/" + getUri() + "?access_token=" + getBaiduAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        return request;
    }

    /**
     * 从用户的AK，SK生成鉴权签名（Access Token）
     *
     * @return 鉴权签名（Access Token）
     * @throws IOException IO异常
     */
    public static String getAccessToken(String API_KEY, String SECRET_KEY) throws Exception {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=" + API_KEY
                + "&client_secret=" + SECRET_KEY);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        return new org.json.JSONObject(response.body().string()).getString("access_token");
    }

    public Object result(String response) {

        return null;
    }

    /**
     * 获取百度token
     *
     *
     *     ak: zs9oN4gSuoS3eK8dVJg6jyKh
     *     sk: uHIRXkj6rbW1eXy8eRVCeP1e3cRQKXay
     * @return
     */
    public String getBaiduAccessToken() {
        try {
            RedisUtils redisUtils = SpringContextUtils.getBean(RedisUtils.class);

            String baiduApiKey = "zs9oN4gSuoS3eK8dVJg6jyKh";
            String baiduSecretKey = "uHIRXkj6rbW1eXy8eRVCeP1e3cRQKXay";

            String accessTokenKey = baiduApiKey + ":" + baiduSecretKey + ":token";
            String accessToken = redisUtils.get(accessTokenKey);
            if (StringUtils.isBlank(accessToken)) {
                accessToken = getAccessToken(baiduApiKey, baiduSecretKey);
                redisUtils.set(accessTokenKey, accessToken, RedisConstans.SECOND_OF_ONE_7_DAY);
            }
            return accessToken;
        } catch (Exception e) {
            log.error("getBaiduToken error", e);
        }
        log.error("getBaiduToken error token is null ");
        return null;
    }


    public String checkOfd(BaiduOfdRequest baiduOdfRequest) {
        if (StringUtils.isBlank(baiduOdfRequest.getImageBase64())
                && StringUtils.isBlank(baiduOdfRequest.getImageUrl())
                && StringUtils.isBlank(baiduOdfRequest.getPdfFile())
                && StringUtils.isBlank(baiduOdfRequest.getOfd_file())) {
            return "你的image , url , pdf_file 或 ofd_file不能都为空";
        }
        return null;
    }


    public String checkPdf(BaiduPdfRequest baiduOdfRequest) {
        if (StringUtils.isBlank(baiduOdfRequest.getImageBase64())
                && StringUtils.isBlank(baiduOdfRequest.getImageUrl())
                && StringUtils.isBlank(baiduOdfRequest.getPdfFile())) {
            return "你的image , url , pdf_file不能都为空";
        }
        return null;
    }


    public String checkProbabilityLocation(BProbabilityLocationRequest baiduOdfRequest) {
        if (StringUtils.isBlank(baiduOdfRequest.getImageBase64())
                && StringUtils.isBlank(baiduOdfRequest.getImageUrl())
                && StringUtils.isBlank(baiduOdfRequest.getPdfFile())
        ) {
            return "你的image , url , pdf_file不能都为空";
        }

        if (checkNotTrueFalse(baiduOdfRequest.getProbability())) {
            return "probability必须为" + ApiConstants.trueOrFalse + ",是否返回字段置信度";
        }
        if (checkNotTrueFalse(baiduOdfRequest.getLocation())) {
            return "location必须为" + ApiConstants.trueOrFalse + ",是否返回字段位置坐标";
        }

        return null;
    }


    public String checkSimpleProbabilityLocation(BSimpleProbabilityLocationRequest baiduOdfRequest) {
        if (StringUtils.isBlank(baiduOdfRequest.getImageBase64())
                && StringUtils.isBlank(baiduOdfRequest.getImageUrl())
        ) {
            return "你的image , url 不能都为空";
        }

        if (checkNotTrueFalse(baiduOdfRequest.getProbability())) {
            return "probability必须为" + ApiConstants.trueOrFalse + ",是否返回字段置信度";
        }
        if (checkNotTrueFalse(baiduOdfRequest.getLocation())) {
            return "location必须为" + ApiConstants.trueOrFalse + ",是否返回字段位置坐标";
        }

        return null;
    }


    public String checkImageUri(BaiduImageUrlRequest baiduOdfRequest) {
        if (StringUtils.isBlank(baiduOdfRequest.getImageBase64())
                && StringUtils.isBlank(baiduOdfRequest.getImageUrl())
        ) {
            return "你的image , url不能都为空";
        }
        return null;
    }

    public StringBuffer getImageContent(BaiduImageUrlRequest qrcodeReconizeRequest) {
        StringBuffer sb = new StringBuffer();
        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getImageBase64())) {
            sb.append("&image=" + qrcodeReconizeRequest.getImageBase64());
        }

        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getImageUrl())) {
            sb.append("&url=" + qrcodeReconizeRequest.getImageUrl());
        }
        return sb;
    }

    public StringBuffer getPdfContent(BaiduPdfRequest qrcodeReconizeRequest) {
        StringBuffer sb = getImageContent(qrcodeReconizeRequest);
        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getPdfFile())) {
            sb.append("&pdf_file=" + qrcodeReconizeRequest.getPdfFile());
            sb.append("&pdf_file_num=" + qrcodeReconizeRequest.getPdfFileNum());
        }
        return sb;
    }

    public StringBuffer getProbabilityLocationContent(BProbabilityLocationRequest qrcodeReconizeRequest) {
        StringBuffer sb = getImageContent(qrcodeReconizeRequest);
        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getPdfFile())) {
            sb.append("&pdf_file=" + qrcodeReconizeRequest.getPdfFile());
            sb.append("&pdf_file_num=" + qrcodeReconizeRequest.getPdfFileNum());
        }
        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getProbability())) {
            sb.append("&probability=").append(qrcodeReconizeRequest.getProbability());
        }

        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getLocation())) {
            sb.append("&location=").append(qrcodeReconizeRequest.getLocation());
        }
        return sb;
    }

    public StringBuffer getSimpleProbabilityLocationContent(BSimpleProbabilityLocationRequest qrcodeReconizeRequest) {
        StringBuffer sb = getImageContent(qrcodeReconizeRequest);

        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getProbability())) {
            sb.append("&probability=").append(qrcodeReconizeRequest.getProbability());
        }
        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getLocation())) {
            sb.append("&location=").append(qrcodeReconizeRequest.getLocation());
        }
        return sb;
    }

    public StringBuffer getOfdContent(BaiduOfdRequest qrcodeReconizeRequest) {
        StringBuffer sb = getPdfContent(qrcodeReconizeRequest);
        if (StringUtils.isNotBlank(qrcodeReconizeRequest.getOfd_file())) {
            sb.append("&ofd_file=" + qrcodeReconizeRequest.getOfd_file());
            sb.append("&ofd_file_num=" + qrcodeReconizeRequest.getOfd_file_num());
        }
        return sb;
    }


    public boolean checkNotTrueFalse(String value) {
        return !ApiConstants.trueOrFalse.contains(value);
    }

    public boolean checkNotFrontBack(String value) {
        return !ApiConstants.frontOrback.contains(value);
    }

    public boolean checkNotNormalOrRoll(String value) {
        return !ApiConstants.normalOrRoll.contains(value);
    }

    public boolean checkNotChnEngOrEng(String value) {
        return !ApiConstants.chnEngOREng.contains(value);
    }


    public String checkTaskId(BTaskIdRequest taskIdRequest) {
        if (StringUtils.isBlank(taskIdRequest.getTaskId())) {
            return "taskId不能为空";
        }
        return null;
    }

}
