package com.yeejoin.amos.boot.module.jxiop.biz.jxdz.utils;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.module.jxiop.biz.jxdz.vo.NeedDataVO;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.List;
import java.util.Objects;

/**
 * 江西电建工具类
 */
@Component
@Slf4j
public class JXDZUtils {
    @Value("${coreIp:iiet-jepcc.powerchina.cn:8088}")
    String coreIp;
    @Value("${jxdzIp:122.70.153.215:9003}")
    String jxdzIp;
    @Value("${jxdzTokenUserName:jiangxi_epc}")
    String jxdzTokenUserName;
    @Value("${jxdzTokenPassword:123456}")
    String jxdzTokenPassword;
    @Value("${jxdzPublicKey:04508e9c4df8463c784df2dde2536e792851a8f3fd0e5ff29b7bf1a5d9e3f566aa49a7a5fe7683e3dc4dc30dd7bc8773838a9e4fbcf7dfac53461c8777a6aed691}")
    String publicKey;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    AmosRequestContext amosRequestContext;
    public static  String XZ_CODE="PWC20123608280010";
    public static  String GF_CODE="PPC17063608260011";

    private String dataEncrypt(String obj, String publicKey) {
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(),
                sm2ECParameters.getN(), sm2ECParameters.getH());
        ECPoint pukPoint = sm2ECParameters.getCurve()
                .decodePoint(Hex.decode(publicKey));
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
        SM2Engine sm2Engine = new SM2Engine(mode);
        // 设置sm2为加密模式
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
        byte[] arrayOfBytes = null;
        byte[] in = obj.getBytes(StandardCharsets.UTF_8);
        try {
            arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Base64.encode(arrayOfBytes);
    }


    /**
     * 获取token
     * @return
     */
    private String getToken() {
        String url = "http://" + jxdzIp + "/auth/justLogin";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username", jxdzTokenUserName);
        jsonObject.put("password", jxdzTokenPassword);
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(jsonObject, headers);
        try {
            ResponseEntity<JSONObject> result = restTemplate.postForEntity(url, httpEntity, JSONObject.class);
            if (HttpStatus.OK == result.getStatusCode()) {
                JSONObject body = result.getBody();
                if (HttpStatus.OK.value() == body.getInteger("code")) {
                    JSONObject data = body.getJSONObject("data");
                    return data.getString("access_token");
                } else {
                    throw new BadRequest("获取token失败,失败原因[" + body + "]");
                }
            } else {
                throw new BadRequest("获取token失败,失败原因[" + result + "]");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("获取token失败,失败原因[" + e.getMessage() + "]");
        }
    }

    /**
     * 发送GET请求
     * @param url
     * @return
     */
    public JSONObject sendCoreGetRequest(String url) {
        String reqUrl = "http://" + coreIp + url;
        HttpHeaders headers = new HttpHeaders();
        headers.set("Token", amosRequestContext.getToken());
        headers.set("Product", amosRequestContext.getProduct());
        headers.set("Appkey", amosRequestContext.getAppKey());
        HttpEntity entity = new HttpEntity<>(headers);
        log.info("发送GET请求,请求地址{}", reqUrl);
        try {
            ResponseEntity<JSONObject> response = restTemplate.exchange(reqUrl, HttpMethod.GET, entity, JSONObject.class);
            if (HttpStatus.OK == response.getStatusCode()) {
                log.info("发送请求成功，请求返回体{}", response.getBody());
                return response.getBody();
            } else {
                throw new BadRequest("返回接口异常,失败原因[" + response + "]");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("发送GET请求失败,失败原因[" + e.getMessage() + "]");
        }
    }

    /**
     * 发送GET请求
     * @param url
     * @return
     */
    public JSONObject sendJXDZGetRequest(String url) {
        String reqUrl = "http://" + jxdzIp + url;
        log.info("发送GET请求,请求地址{}", reqUrl);
        HttpEntity entity = new HttpEntity<>(buildHttpHeaders());
        try {
            ResponseEntity<JSONObject> response = restTemplate.exchange(reqUrl, HttpMethod.GET, entity, JSONObject.class);
            if (HttpStatus.OK == response.getStatusCode()) {
                log.info("发送请求成功，请求返回体{}", response.getBody());
                return response.getBody();
            } else {
                throw new BadRequest("返回接口异常,失败原因[" + response + "]");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("发送GET请求失败,失败原因[" + e.getMessage() + "]");
        }
    }

    /**
     * 发送Post请求
     * @param url
     * @param accessType
     * @param needDataVO
     * @param data
     */
    public void sendJXDZPostRequest(String url, Integer accessType, NeedDataVO needDataVO, List data) {
        String reqUrl = "http://" + jxdzIp + url;
        log.info("发送POST请求,请求地址{}", reqUrl);
        HttpEntity<JSONObject> entity = new HttpEntity<>(buildBody(needDataVO.getPlatformId(), needDataVO.getDateTime(), data, accessType, needDataVO.getReaccessId()), buildHttpHeaders());
        try {
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(reqUrl, entity, JSONObject.class);
            if (HttpStatus.OK == response.getStatusCode()) {
                JSONObject body = response.getBody();
                if (HttpStatus.OK.value() == body.getInteger("code")) {
                    log.info("发送JXDZ请求成功，请求返回体{}", response.getBody());
                } else {
                    log.info("发送JXDZ请求失败，请求返回体{}", response.getBody());
                    throw new BadRequest("发送JXDZ请求失败,失败原因[" + response.getBody() + "]");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("发送POST请求失败,失败原因[" + e.getMessage() + "]");
        }
    }

    private HttpHeaders buildHttpHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        String authorization = "Bearer " + getToken();
        headers.set("Authorization", authorization);
        return headers;
    }

    /**
     * 构建请求体
     * @param platformId
     * @param time
     * @param data
     * @param accessType
     * @param reaccessId
     * @return
     */
    private JSONObject buildBody(Long platformId, Long time, List data, Integer accessType, Long reaccessId) {
        JSONObject body = new JSONObject();
        body.put("accessType", accessType);
        body.put("encryptData", buildEncryptData(platformId, time, data, reaccessId));
        return body;
    }

    /**
     * 加密数据
     * @param platformId
     * @param time
     * @param data
     * @param reaccessId
     * @return
     */
    private String buildEncryptData(Long platformId, Long time, List data, Long reaccessId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("platformId", platformId);
        if (!Objects.isNull(reaccessId)) {
            jsonObject.put("reaccessId", reaccessId);
        }
        jsonObject.put("time", time);
        jsonObject.put("data", data);
        return dataEncrypt(jsonObject.toJSONString(), publicKey);
    }
}
