package com.iformall.utils.car;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.enums.EnumCouponUnit;
import com.iformall.exception.MallinkException;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 尚安停车
 */
public class BoLinkUtil {
    private final static Logger logger = LoggerFactory.getLogger(BoLinkUtil.class);

    public static final String BOLINK_URL = "url";
    public static final String BOLINK_COMID = "comid";
    public static final String BOLINK_UNION_ID = "union_id";
    public static final String BOLINK_KEY = "key";
    public static final String BOLINK_CAR_NUMBER = "car_number";
    public static final String BOLINK_ORDER_ID = "order_id";
    public static final String BOLINK_PAY_TIME = "pay_time";
    public static final String BOLINK_ACT_TOTAL = "act_total";
    public static final String BOLINK_DEDUCTION_TIME = "deduction_time";
    public static final String BOLINK_DEDUCTION_MONEY = "deduction_money";

    public static final String URL = "https://yun.bolink.club";
    public static final String COMID = "30536";
    public static final String UNION_ID = "200389";
    public static final String KEY = "Y29PZH9KDT1V7Y1E";
    public static final String PARK_NUM = "京88888";

    public static final String BOLINK_DATA = "data";
    public static final String BOLINK_STATE = "state";
    public static final int BOLINK_SUCCESS = 1;
    public static final int BOLINK_FAIL = 0;
    public static final String BOLINK_ERROR = "errmsg";


    public static void main(String[] args) throws Exception {
        String carNumber = "京88888";

        String result = getStopFee(URL, COMID, UNION_ID, KEY, carNumber);


    }

    /**
     * md5算法
     * @param data
     * @return
     * @throws NoSuchAlgorithmException
     */

    public static String md5(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(data.getBytes());
        StringBuilder buf = new StringBuilder();
        byte[] bits = md.digest();
        for(int i=0;i<bits.length;i++){
            int a = bits[i];
            if(a<0) a+=256;
            if(a<16) buf.append("0");
            buf.append(Integer.toHexString(a));
        }
        return buf.toString();
    }

    /**
     * 签名
     * @param key
     * @param dataStr
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String getSign(String key, String dataStr) throws NoSuchAlgorithmException {
        StringBuilder sb = new StringBuilder();
        sb.append(dataStr).append(BOLINK_KEY).append("=").append(key);
        logger.debug(sb.toString());
        String signValue = md5(sb.toString()).toUpperCase();
        logger.debug("sign: " + signValue);
        return signValue;
    }

    public static boolean checkRespFailed(String resp) {
        if(resp.startsWith("<html>") || resp.startsWith("<!DOCTYPE html>")) {
            return true;
        }
        return false;
    }

    public static String getStopFee(String baseUrl, String comid, String unionId, String key, String carNumber) {
        String stopFeeUrl = "/zld/queryorderprice";
        String url = baseUrl + stopFeeUrl;
        Map<String, Object> params = new HashMap<>();
        params.put(BOLINK_COMID, comid);
        params.put(BOLINK_UNION_ID, unionId);
        params.put(BOLINK_CAR_NUMBER, carNumber);
        try {
            String sign = getSign(key, JSON.toJSONString(params));
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        try {
            String result = Proc(url, key, params);
            if(result == null) {
                throw new MallinkException(ErrorCode.CAR_CMD_FAIL);
            }
            if(checkRespFailed(result)) {
                throw new MallinkException(ErrorCode.CAR_CMD_FAIL);
            }
            return result;
        } catch (Exception e) {
            return null;
        }
    }

    public static String couponSend(String baseUrl, String comid, String unionId, String key,
                                    String carNumber,
                                    String orderId,
                                    String unit, String amount) {
        String couponUrl = "/zld/openservice/paynoticetopark";
        String url = baseUrl + couponUrl;
        Map<String, Object> params = new HashMap<>();
        params.put(BOLINK_COMID, comid);
        params.put(BOLINK_UNION_ID, unionId);
        params.put(BOLINK_CAR_NUMBER, carNumber);
        params.put(BOLINK_ORDER_ID, orderId);
        params.put(BOLINK_PAY_TIME, new Date().getTime());
        params.put(BOLINK_ACT_TOTAL, "0");
        if (unit.equals(EnumCouponUnit.MONEY.getCode())) {
            // 金额
            params.put(BOLINK_DEDUCTION_MONEY, amount);
        } else {
            // 小时
            params.put(BOLINK_DEDUCTION_TIME, amount);
        }
        try {
            String sign = getSign(key, JSON.toJSONString(params));
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        try {
            String result = Proc(url, key, params);
            if(result == null) {
                throw new MallinkException(ErrorCode.CAR_CMD_FAIL);
            }
            if(checkRespFailed(result)) {
                throw new MallinkException(ErrorCode.CAR_CMD_FAIL);
            }
            return result;
        } catch (Exception e) {
            return null;
        }
    }

    private static String Proc(String url, String key, Map<String, Object> paramMap) {
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept-Encoding", "UTF-8");

        StringBuilder sb = new StringBuilder();
        String sign = null;
        try{
            String dataStr = JSON.toJSONString(paramMap);
            sb.append("{\"data\":").append(dataStr);
            sign = getSign(key, dataStr);
            sb.append(",\"sign\":\"").append(sign).append("\"}");
        }catch(NoSuchAlgorithmException e) {
            logger.error(e.getLocalizedMessage());
        }

        String bodyStr = sb.toString();
        logger.info(bodyStr);

        final Base64.Encoder encoder = Base64.getEncoder();
        final Base64.Decoder decoder = Base64.getDecoder();

        try {
            byte[] bodyByte = bodyStr.getBytes("UTF-8");
            String encodeStr = encoder.encodeToString(bodyByte);
            StringEntity se = new StringEntity(encodeStr, Consts.UTF_8);
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,"UTF-8"));
            httpPost.setEntity(se);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        HttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
        }

        String result = null;

        //打印StatusLine
        logger.debug("StatusLine: " + response.getStatusLine());
        if (response.getStatusLine().getStatusCode() != 200) {
            logger.error("status error: " + response.getStatusLine().getReasonPhrase());
            throw new MallinkException(ErrorCode.CAR_CMD_FAIL);
        }
        try{
            //获取实体
            HttpEntity httpEntity= response.getEntity();
            String encodeResStr = EntityUtils.toString(httpEntity, "UTF-8");
            result = new String(decoder.decode(encodeResStr), "UTF-8");
            logger.debug(result);
            // {"data":{"errmsg":"查询价格返回超时，请联系车场管理员","state":0,"plate_number":"京88888"},"sign":"DE81DCA41E6C1ACA978906F998A7BC1D"}

        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
        }

        try {                //关闭流并释放资源
            httpClient.close();
        } catch (IOException e) {
            logger.error(e.getLocalizedMessage());
        }

        JSONObject resultObj = JSON.parseObject(result);
        String resSign = resultObj.getString("sign");
        if (!resSign.equals(sign)) {
            logger.error("data sign: " + resSign);
            throw new MallinkException(ErrorCode.BOLINK_SIGN_ERR);
        }

        return result;
    }




}

