package com.cusc.nirvana.user.rnr.fp.common.cloud;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.cusc.nirvana.common.encrypt.sign.HMAC;
import com.cusc.nirvana.common.result.Response;
import com.cusc.nirvana.user.rnr.fp.common.FpIgnoreBase64ImgJsonNoEncryptFilter;
import com.cusc.nirvana.user.rnr.fp.common.FpIgnoreBase64ImgJsonSerializeFilter;
import com.cusc.nirvana.user.rnr.fp.dto.OcrNpRespDTO;
import com.cusc.nirvana.user.util.CuscStringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

@Service
@Slf4j
public class CloudService<T> {

    @Resource
    private RestTemplate noBalanceRestTemplateRnrFp;

    @Autowired
    private CloudConstant cloudConstant;

    public <T> Response<T> postForResponse(String url, Object rq, Class<T> rsClazz) {
        if(url.equals(CloudMethod.LIVENESS)){
            return postForResponseNoEncrypt(url,rq,rsClazz);
        }
        String rqUrl = cloudConstant.getHOST() + url;
        try {
            log.info("openapi key : {}", cloudConstant.getENCRYPT_KEY());
            String encryptrq = Sm4DemoUtils.encryptEcbPaddingHexString(cloudConstant.getENCRYPT_KEY(), JSON.toJSONString(rq));
            HttpHeaders headers = headers();
            HttpEntity httpEntity = new HttpEntity(encryptrq, headers);
            log.info("send 2 cloud begin , url : {}, rq : {},  header : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonSerializeFilter()),
                    headers.toString());
            long startTime = System.currentTimeMillis();
            ResponseEntity<String> entity =
                    noBalanceRestTemplateRnrFp.exchange(rqUrl, HttpMethod.POST, httpEntity, String.class);
            long endTime = System.currentTimeMillis();
            if (entity != null && entity.getStatusCodeValue() == 200) {
                log.info("send 2 cloud success code 200, url : {}, rq : {}, body : {}, times : {}",
                        rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()), entity.getBody(), endTime - startTime);
                Response<String> result = JSON.parseObject(entity.getBody(), new TypeReference<Response<String>>(String.class) {
                }.getType());
                T t = null ;
                if (null != result) {
                	String data;
                	if (result.getCode() == 200) {
                		data = Sm4DemoUtils.decryptEcbPaddingString(cloudConstant.getDECRYPT_KEY(), result.getData());
					} else {
                		data = result.getData();
					}
					t = JSON.parseObject(data, rsClazz);
				}

                Response<T> finalresult = new Response<T>(result.getMsg(), result.getCode(), t, result.getSuccess(), result.getException());
                finalresult.setAttachment(result.getAttachment());
                return finalresult;
            } else {
                log.info("send 2 cloud fail, url : {}, rq : {}, times : {}, entity : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()),
                        endTime - startTime, null == entity ? null : JSON.toJSONString(entity, new FpIgnoreBase64ImgJsonSerializeFilter()));
                return Response.createError("网络异常");
            }
        } catch (Exception e) {
            log.error("send 2 cloud error, url : {}, rq : {}, e : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()), e);
            return Response.createError("系统异常");
        }
    }

    public <T> Response<T> postForResponseNoEncrypt(String url, Object rq, Class<T> rsClazz) {
        String rqUrl = cloudConstant.getHOST() + url;
        try {
            log.info("openapi key : {}", cloudConstant.getENCRYPT_KEY());
            HttpHeaders headers = headers();
            HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(rq), headers);
            log.info("send 2 cloud begin , url : {}, rq : {},  header : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonSerializeFilter()),
                    headers.toString());
//            log.info("send 2 cloud begin , url : {}, rq : {}, header : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()),
//                    headers.toString());
            long startTime = System.currentTimeMillis();
            ResponseEntity<String> entity =
                    noBalanceRestTemplateRnrFp.exchange(rqUrl, HttpMethod.POST, httpEntity, String.class);
            long endTime = System.currentTimeMillis();
            if (entity != null && entity.getStatusCodeValue() == 200) {
                log.info("send 2 cloud success code 200, url : {}, rq : {}, body : {}, times : {}",
                        rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()), entity.getBody(), endTime - startTime);
                Response<T> result = JSON.parseObject(entity.getBody(), new TypeReference<Response<T>>(rsClazz) {
                }.getType());
                return result;
            } else {
                log.info("send 2 cloud fail, url : {}, rq : {}, times : {}, entity : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()),
                        endTime - startTime, null == entity ? null : JSON.toJSONString(entity, new FpIgnoreBase64ImgJsonSerializeFilter()));
                return Response.createError("网络异常");
            }
        } catch (Exception e) {
            log.error("send 2 cloud error, url : {}, rq : {}, e : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()), e);
            return Response.createError("系统异常");
        }
    }

    public <T> Response<List<T>> postForResponseList(String url, Object rq, Class<T> rsClazz) {
        String rqUrl = cloudConstant.getHOST() + url;
        try {
            HttpEntity httpEntity = new HttpEntity(
                    Sm4DemoUtils.encryptEcbPaddingHexString(cloudConstant.getENCRYPT_KEY(), JSON.toJSONString(rq)),
                    headers());
            log.info("send 2 cloud begin , url : {}, rq : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonSerializeFilter()));
            long startTime = System.currentTimeMillis();
            ResponseEntity<String> entity =
                    noBalanceRestTemplateRnrFp.exchange(rqUrl, HttpMethod.POST, httpEntity, String.class);
            long endTime = System.currentTimeMillis();
            if (entity != null && entity.getStatusCodeValue() == 200) {
                log.info("send 2 cloud success code 200, url : {}, rq : {}, body : {}, times : {}",
                        rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()), entity.getBody(), endTime - startTime);
                Response<String> result = JSON.parseObject(entity.getBody(), new TypeReference<Response<String>>(String.class) {
                }.getType());
                String data = Sm4DemoUtils.decryptEcbPaddingString(cloudConstant.getDECRYPT_KEY(), result.getData());
                List<T> t = JSON.parseArray(data, rsClazz);
                Response<List<T>> finalresult = new Response<List<T>>(result.getMsg(), result.getCode(), t, result.getSuccess(), result.getException());
                finalresult.setAttachment(result.getAttachment());
                return finalresult;
            } else {
                log.info("send 2 cloud fail, url : {}, rq : {}, times : {}, entity : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()),
                        endTime - startTime, null == entity ? null : JSON.toJSONString(entity, new FpIgnoreBase64ImgJsonSerializeFilter()));
                return Response.createError("网络异常");
            }
        } catch (Exception e) {
            log.error("send 2 cloud error, url : {}, rq : {}, e : {}", rqUrl, JSON.toJSONString(rq, new FpIgnoreBase64ImgJsonNoEncryptFilter()), e);
            return Response.createError("系统异常");
        }
    }

    /**
     * 生成请求头
     *
     * @return
     */
    public HttpHeaders headers() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(SignConstants.APP_ID, cloudConstant.getAPPID());
        httpHeaders.add(SignConstants.NONCE_STR, CuscStringUtils.generateUuid());
        httpHeaders.add(SignConstants.TIMESTAMP, String.valueOf(System.currentTimeMillis()));
        httpHeaders.add(SignConstants.VERSION, cloudConstant.getVERSION());
        httpHeaders.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
        StringBuilder sb = new StringBuilder();
        sb.append(SignConstants.APP_ID + cloudConstant.getAPPID());
        sb.append(SignConstants.NONCE_STR + httpHeaders.get(SignConstants.NONCE_STR).get(0));
        sb.append(SignConstants.TIMESTAMP + httpHeaders.get(SignConstants.TIMESTAMP).get(0));
        sb.append(SignConstants.VERSION + httpHeaders.get(SignConstants.VERSION).get(0));
        String scret = HMAC.sign(sb.toString(), cloudConstant.getAPPSCRET(), HMAC.Type.HmacSHA256);
        httpHeaders.add(SignConstants.SIGN, scret);
        return httpHeaders;
    }
}
