package com.chinacreator.video.restful.service;

import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.exception.BussinessException;
import com.chinacreator.video.mapper.ChannelDao;
import com.chinacreator.video.mapper.CommConfDao;
import com.chinacreator.video.mapper.DictionaryDao;
import com.chinacreator.video.mapper.SbChannelDao;
import com.chinacreator.video.service.CommonService;
import com.chinacreator.video.util.MD5;
import com.chinacreator.video.util.URLUtil;
import com.chinacreator.video.validate.*;
import net.sf.json.JSONObject;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.HashMap;

/**
 * 手百渠道适配服务类
 *
 * @author zhengrong.yan
 * @date 20210609
 */
@Component
public class SbChannelService {

    @Autowired
    private ChannelValidate channelValidate;

    @Autowired
    private IpValidate ipValidate;

    @Autowired
    private MobValidate mobValidate;

    @Autowired
    private TimetampValidate timetampValidate;

    @Autowired
    private SignValidate signValidate;

    @Autowired
    private ParamValidate paramValidate;

    @Autowired
    private CommConfDao commConfDao;

    @Autowired
    private CommonService commonService;

    @Autowired
    private SbChannelDao sbChannelDao;

    @Autowired
    private DictionaryDao dictionaryDao;

    @Autowired
    private ChannelDao channelDao;

    private static Logger logger = Logger.getLogger(SbChannelService.class);

    private static Logger log = Logger.getLogger("sbchannel");

    public void busiCheck(OrderInfo orderInfo) throws Exception {
        //timetamp验证
        timetampValidate.validate(orderInfo.getTimestamp());
        //渠道验证
        channelValidate.validate(orderInfo.getChannel());
        //ip验证
        ipValidate.volidate(orderInfo);
        //签名验证
        signValidate(orderInfo);
        //手机号码验证
        mobValidate.validate(orderInfo);
        //并发访问控制
        vistVali(orderInfo);
    }

    /**
     * 拼接签名信息 orderid+channel+timestamp
     *
     * @param
     * @return
     */
    public String getSign(OrderInfo orderInfo) throws Exception {
        StringBuilder strb = new StringBuilder();
        String userid = orderInfo.getUserid();
        strb.append(userid);
        strb.append(orderInfo.getCpid());
        strb.append(orderInfo.getSpid());
        strb.append(orderInfo.getChannel());
        strb.append(orderInfo.getTimestamp());
        return strb.toString();
    }

    /**
     * 签名验证
     *
     * @param
     * @throws Exception
     */
    public void signValidate(OrderInfo orderInfo) throws Exception {
        String lcalsign = getSign(orderInfo);
        String channel = orderInfo.getChannel();
        lcalsign += channelDao.queryChannel(channel).getPassword();
        System.out.println("local-->" + lcalsign);
        lcalsign = MD5.MD5Encode(lcalsign);
        System.out.println("orderinfo==>" + orderInfo.getSignature());
        System.out.println("lcalsign===>" + lcalsign);
        if (!lcalsign.equals(orderInfo.getSignature())) {
            throw new BussinessException("10006", "签名校验失败");
        }
    }

    /**
     * 业务处理
     *
     * @param orderInfo
     */
    public JSONObject busiOper(OrderInfo orderInfo) throws Exception {
        String resultcode = "0";
        String resultinfo = "";
        String jsonParams = "";
        JSONObject data = null;
        HashMap map = new HashMap();
        try {
            String token = orderInfo.getToken();
            if(token==null || "".equals(token)){
                token = "";
            }
            //是否订购成功
            HashMap<String, Object> remap = sbChannelDao.findOrderStatus(orderInfo.getUserid());
            if(remap!=null) {
                String relid = (String) remap.get("ID"); //订购关系表ID
                if (relid == null || "".equals(relid)) {
                    relid = commConfDao.generateId();
                }
                orderInfo.setId(relid);
                if ("0".equals(remap.get("STATUS"))) {//已订购
                    //调接口
                    String url = dictionaryDao.getValue("sbchannelUrl");
                    String pwd = dictionaryDao.getValue("sbchannelKey");
                    com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
                    json.put("token", token);
                    String s = sha256_HMAC("token=" + token, pwd);
                    json.put("sign", s);
                    jsonParams = json.toString();

                    /*添加到表*/
                    map.put("id", sbChannelDao.getNo());
                    map.put("orderid", orderInfo.getId());
                    map.put("userid", orderInfo.getUserid());
                    map.put("cpid", orderInfo.getCpid());
                    map.put("spid", orderInfo.getSpid());
                    map.put("token", token);
                    map.put("request", jsonParams);
                    sbChannelDao.addSbchannelRec(map);
                    /**end**/

                    String result = URLUtil.postJson(url, jsonParams);
                    log.info("url=====>" + url);
                    log.info("request====>" + jsonParams);
                    log.info("result====>" + result);
                    if (!"".equals(result) && result != null) {
                        JSONObject resjson = JSONObject.fromObject(result);
                        resultcode = resjson.get("errno") == null ? "" : resjson.get("errno").toString();
                        resultinfo = resjson.get("errmsg") == null ? "" : resjson.get("errmsg").toString();
                        if ("0".equals(resultcode)) {
                            data = resjson.getJSONObject("data");
                        } else {
                            throw new BussinessException(resultcode, resultinfo);
                        }
                    } else {
                        throw new BussinessException("8000", "解析json出错");
                    }
                    return data;
                } else {
                    throw new BussinessException("9007", "未订购或者已退订或已失效");
                }
            }else{
                throw new BussinessException("9007", "未订购或者已退订或已失效");
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (e instanceof BussinessException) {
                resultcode = ((BussinessException) e).getCode();
                resultinfo = ((BussinessException) e).getMessage();
            } else {
                resultcode = "8000";
                resultinfo = "出现异常，" + e.toString();
            }
            throw e;
        }finally {
            //更新表
            map.put("resultcode", resultcode);
            map.put("resultinfo", resultinfo.length()>4000?resultinfo.substring(0,2000):resultinfo);
            if(map.get("id")!=null) {
                sbChannelDao.upSbchannelRec(map);
            }
        }
    }


    /**
     * 验证访问限制，1分钟内同一业务只能办理一次
     *
     * @param orderInfo
     * @throws Exception
     */
    private void vistVali(OrderInfo orderInfo) throws Exception {
        String[] params = new String[3];
        params[0] = orderInfo.getChannel();
        params[1] = orderInfo.getUserid();
        params[2] = orderInfo.getSpid();
        if (commonService.vistVali2(params, "sbchannel")) {
            throw new BussinessException("8001", "指定时间内重复请求");
        }
    }

    /**
     * 将加密后的字节数组转换成字符串
     *
     * @param b 字节数组
     * @return 字符串
     */
    public  static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b!=null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                hs.append('0');
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }
    /**
     * sha256_HMAC加密
     * @param message 消息
     * @param secret  秘钥
     * @return 加密后字符串
     */
    public static String sha256_HMAC(String message, String secret) {
        String hash = "";
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            hash = byteArrayToHexString(bytes);
        } catch (Exception e) {
            System.out.println("Error HmacSHA256 ===========" + e.getMessage());
        }
        return hash;
    }
}
