package org.springblade.modules.app.client;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wn.common.validator.Validator;
import org.springblade.modules.app.common.vo.*;
import org.springblade.modules.app.constant.Constants;
import org.springblade.modules.app.entity.ApiLog;
import org.springblade.modules.app.service.IApiLogService;
import org.springblade.modules.app.utils.ErrorMsg;
import lombok.extern.slf4j.Slf4j;
import org.springblade.modules.app.vo.CarPush;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * <p>
 * 作用描述：
 * </p>
 *
 * @author lq
 * @since 2020/4/21 3:24 下午
 */
@Slf4j
@Service
@RefreshScope
public class ZmtClientService {

    @Value("${xyb.private.Key}")
    private String privateKey;
    @Value("${zmt.base.url}")
    private String baseUrl;
    @Value("${zmt.subject.url}")
    private String subjectUrl;
    @Value("${zmt.east.supplier.url}")
    private String eastSupplierUrl;
    @Value("${zmt.check.point.url}")
    private String checkPointUrl;
    @Value("${zmt.registered.url}")
    private String registeredUrl;
    @Value("${zmt.registered.deal.url}")
    private String registeredDealUrl;
    @Value("${zmt.registered.cancel.url}")
    private String registeredCancelUrl;
    @Value("${zmt.trajectory.receive.url}")
    private String trajectoryUrl;
    @Value("${zmt.car.push.url}")
    private String carPush;

    @Autowired
    private IApiLogService apiLogService;

    /**
     * 获取用户信息
     *
     * @param
     * @return void
     * @author FUXINSHENG
     * @date 2021/12/21 9:24
     */
    public OutApiSyncUserResultVO getSubject(OutApiSyncUserParamVO userParamVO) {
        Map<String, Object> paramMap = getParams(JSON.toJSONString(userParamVO));

        //发送http请求
        log.info(Constants.HEADER + "获取调运主体用户信息， params：{}", JSON.toJSONString(paramMap));
        String result = HttpUtil.get(baseUrl + subjectUrl, paramMap);
        log.info(Constants.HEADER + "获取调运主体用户信息，result：{}", result);

        OutApiSyncResultVO outApiSyncResultVO = JSON.parseObject(result, OutApiSyncResultVO.class);
        Validator.isTrue(Constants.ZMT_CUCCESS_CODE.equals(outApiSyncResultVO.getCode()), ErrorMsg.NEW(outApiSyncResultVO.getCode(), outApiSyncResultVO.getMessage()));
        return JSON.parseObject(outApiSyncResultVO.getData(), OutApiSyncUserResultVO.class);
    }

    /**
     * 获取用户信息
     *
     * @param
     * @return void
     * @author FUXINSHENG
     * @date 2021/12/21 9:24
     */
    /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    public List<OutApiSyncSupplierResultVO> getEastSupplier(OutApiSyncSupplierParamVO supplierParamVO) {
        Map<String, Object> paramMap = getParams(JSON.toJSONString(supplierParamVO));

        log.info(Constants.HEADER + "获取供东部区生猪养殖企业和六省内供货方信息，params：{}", JSON.toJSONString(paramMap));
        String result = HttpUtil.get(baseUrl + eastSupplierUrl, paramMap);
        log.info(Constants.HEADER + "获取供东部区生猪养殖企业和六省内供货方信息，result：{}", result);

        OutApiSyncResultVO outApiSyncResultVO = JSON.parseObject(result, OutApiSyncResultVO.class);
        Validator.isTrue(Constants.ZMT_CUCCESS_CODE.equals(outApiSyncResultVO.getCode()), ErrorMsg.NEW(outApiSyncResultVO.getCode(), outApiSyncResultVO.getMessage()));
        return JSON.parseArray(outApiSyncResultVO.getData(), OutApiSyncSupplierResultVO.class);
    }

    /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    public List<OutApiSyncCheckPointResultVO> getCheckPoint(Long orgId) {

        JSONObject jsonString = new JSONObject();
        jsonString.put("orgId", orgId);
        Map<String, Object> paramMap = getParams(jsonString.toJSONString());

        log.info(Constants.HEADER + "获取所有道路检查站信息，params：{}", JSON.toJSONString(paramMap));
        String result = HttpUtil.get(baseUrl + checkPointUrl, paramMap);
        log.info(Constants.HEADER + "获取所有道路检查站信息，result：{}", result);

        OutApiSyncResultVO outApiSyncResultVO = JSON.parseObject(result, OutApiSyncResultVO.class);
        Validator.isTrue(Constants.ZMT_CUCCESS_CODE.equals(outApiSyncResultVO.getCode()), ErrorMsg.NEW(outApiSyncResultVO.getCode(), outApiSyncResultVO.getMessage()));
        return JSON.parseArray(outApiSyncResultVO.getData(), OutApiSyncCheckPointResultVO.class);
    }

    /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    public OutApiSyncRecordResultVO postRegistered(OutApiSyncRecordParamVO recordParamVO) {
        Map<String, Object> paramMap = getParams(JSON.toJSONString(recordParamVO));

        log.error(Constants.HEADER + "备案申请，params：{}", paramMap);
        String result = HttpUtil.post(baseUrl + registeredUrl, paramMap);
        log.error(Constants.HEADER + "备案申请，result：{}", result);

        OutApiSyncResultVO outApiSyncResultVO = JSON.parseObject(result, OutApiSyncResultVO.class);
        Validator.isTrue(Constants.ZMT_CUCCESS_CODE.equals(outApiSyncResultVO.getCode()), ErrorMsg.NEW(outApiSyncResultVO.getCode(), outApiSyncResultVO.getMessage()));
        return JSON.parseObject(outApiSyncResultVO.getData(), OutApiSyncRecordResultVO.class);
    }

    /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    public void postRegisteredDeal(OutApiSyncAcceptNumParamVO acceptNumParamVO) {
        Map<String, Object> paramMap = getParams(JSON.toJSONString(acceptNumParamVO));

        log.info(Constants.HEADER + "备案接收，params：{}", JSON.toJSONString(paramMap));
        String result = HttpUtil.post(baseUrl + registeredDealUrl, paramMap);
        log.info(Constants.HEADER + "备案接收，result：{}", result);
    }

    /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    public void postRegisteredCancel(OutApiSyncAcceptNumParamVO acceptNumParamVO) {
        ApiLog apiLog = new ApiLog();
        apiLog.setUrl(baseUrl + registeredCancelUrl);
        apiLog.setReqData(JSON.toJSONString(acceptNumParamVO));
        Map<String, Object> paramMap = getParams(JSON.toJSONString(acceptNumParamVO));
        log.info(Constants.HEADER + "备案废除，params：{}", JSON.toJSONString(paramMap));
        String result = HttpUtil.post(baseUrl + registeredCancelUrl, paramMap);
        apiLog.setResData(result);
        apiLogService.save(apiLog);
        log.info(Constants.HEADER + "备案废除，result：{}", result);
    }

     /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    public String postCarPush(CarPush push) {
        ApiLog apiLog = new ApiLog();
        apiLog.setUrl(baseUrl + carPush);
        apiLog.setReqData(JSON.toJSONString(push));
        Map<String, Object> paramMap = getParams(JSON.toJSONString(push));
        log.info(Constants.HEADER + "车牌号推送，params：{}", JSON.toJSONString(paramMap));
        String result = HttpUtil.post(baseUrl + carPush, paramMap);
        apiLog.setResData(result);
        apiLogService.save(apiLog);
        log.info(Constants.HEADER + "车牌号推送，result：{}", result);
        return result;
    }

    /**
     * step1、创建模拟数据
     * step2、进行加密封装
     * step3、进行通知；restTemp
     * step4、返回值解析 ResultDTO
     */
    @Async
    public void postTrajectoryReceive(OutApiSyncTrajectoryParamVO trajectoryParamVO) {

        Map<String, Object> paramMap = getParams(JSON.toJSONString(trajectoryParamVO));

        log.info(Constants.HEADER + "轨迹信息接收，registeredUuid：{}", trajectoryParamVO.getRegisteredUuid());
        String result = HttpUtil.post(baseUrl + trajectoryUrl, paramMap);
        log.info(Constants.HEADER + "轨迹信息接收，result：{}", result);
    }

    public String getImag(String imgUrl, String regex) {
        int idx = imgUrl.lastIndexOf(regex);
        if (idx == -1) {
            return "";
        }
        return imgUrl.substring(idx + 1);
    }

    public String getImageBase64(String imgUrl) {//将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        URL url = null;
        HttpURLConnection httpUrl = null;
        InputStream in = null;
        byte[] bytes = new byte[1024];
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        //读取图片字节数组
        try {
            url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            in = httpUrl.getInputStream();
            int len = -1;
            while ((len = in.read(bytes)) != -1) {
                data.write(bytes, 0, len);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //对字节数组Base64编码
        return Base64.encode(data.toByteArray());
    }

    public Map<String, Object> getParams(String busContent) {
        HashMap<String, Object> paramMap = new HashMap<>(16);
        paramMap.put("charset", "UTF-8");
        paramMap.put("version", "1.0.0");
        paramMap.put("utc_timestamp", String.valueOf(System.currentTimeMillis()));
        paramMap.put("bus_content", busContent);
        String sign = null;
        try {
            sign = sign(paramMap);
        } catch (Exception e) {
            e.printStackTrace();
            Validator.notNull(null, ErrorMsg.NEW("999999", "签名生成失败" + JSON.toJSONString(paramMap)));
        }
        paramMap.put("signature", sign);
        return paramMap;
    }


    public String sign(Map<String, Object> parameters) {
        //业务处理结果加签
        byte[] data = getSignContent(parameters).getBytes();
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey, null);
        //签名
        byte[] signed = sign.sign(data);
        // 返回 json 格式响应报文
        return Base64.encode(signed);
    }


    public String getSignContent(Map<String, Object> sortedParams) {
        StringBuilder content = new StringBuilder();
        List<String> keys = new ArrayList<>(sortedParams.keySet());
        Collections.sort(keys);
        int index = 0;
        for (String key : keys) {
            String value = sortedParams.get(key).toString();
            if (cn.hutool.core.lang.Validator.isNotEmpty(key) && cn.hutool.core.lang.Validator.isNotEmpty(value)) {
                content.append(index == 0 ? "" : "&").append(key).append("=").append(value);
                index++;
            }
        }
        return content.toString();
    }
}
