package com.chinacreator.video.restful.service;

import com.chinacreator.video.bean.ChannelBean;
import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.exception.BussinessException;
import com.chinacreator.video.mapper.ChannelDao;
import com.chinacreator.video.mapper.ColorSealDao;
import com.chinacreator.video.mapper.CommConfDao;
import com.chinacreator.video.mapper.DictionaryDao;
import com.chinacreator.video.service.CommonService;
import com.chinacreator.video.util.DesUtil;
import com.chinacreator.video.util.MD5;
import com.chinacreator.video.util.URLUtil;
import com.chinacreator.video.validate.ChannelValidate;
import com.chinacreator.video.validate.IpValidate;
import com.chinacreator.video.validate.MobValidate;
import com.chinacreator.video.validate.TimetampValidate;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhengrong.yan
 * @date 20201114
 */
@Component
public class ColorSealService {

    @Autowired
    private ChannelValidate channelValidate;

    @Autowired
    private IpValidate ipValidate;

    @Autowired
    private MobValidate mobValidate;

    @Autowired
    private TimetampValidate timetampValidate;

    @Autowired
    private CommConfDao commConfDao;

    @Autowired
    private CommonService commonService;

    @Autowired
    private ColorSealDao colorSealDao;

    @Autowired
    private ChannelDao channelDao;

    @Autowired
    private DictionaryDao dictionaryDao;

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

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

    private static Logger log2 = Logger.getLogger("colorsealset");

    private static Logger log3 = Logger.getLogger("colorsealverify");

    public void busiCheck(com.alibaba.fastjson.JSONObject inputObj, int type) throws Exception {
        OrderInfo orderInfo = setBean(inputObj);

        paramValidate(orderInfo);//公共参数验证

        String ringid = "";
        if (type == 1) {//一键设置时需要传递ringid
            ringid = inputObj.getString("ringid");
            if ("".equals(ringid)) {
                throw new BussinessException("80016", "彩铃一键设置缺少彩铃id参数");
            }
        }

        //timetamp验证
        timetampValidate.validate(orderInfo.getTimestamp());
        //渠道验证
        channelValidate.validate(orderInfo.getChannel());
        //ip验证
        ipValidate.volidate(orderInfo);
        //签名验证
        signValidate(orderInfo, type, ringid);
        //手机号码验证
        mobValidate(orderInfo);
        //并发访问控制
//        vistVali(orderInfo, type);
    }

    /*
     * 设置到bean里
     *
     * */
    public OrderInfo setBean(com.alibaba.fastjson.JSONObject inputObj) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserid(inputObj.getString("userid"));
        orderInfo.setTimestamp(inputObj.getString("timestamp"));
        orderInfo.setChannel(inputObj.getString("channel"));
        String subchannel = inputObj.getString("subchannel");
        if (subchannel != null && !"".equals(subchannel)) {
            orderInfo.setSubchannel(subchannel);
        } else {
            orderInfo.setSubchannel(inputObj.getString("channel"));
        }
        orderInfo.setCpid(inputObj.getString("cpid"));
        orderInfo.setSpid(inputObj.getString("spid"));
        //orderInfo.setType(inputObj.getString("type"));
        if (inputObj.getString("type") != null && !"".equals(inputObj.getString("type"))) {
            System.out.println("settype!!!");
            orderInfo.setType(inputObj.getString("type"));
        }
        orderInfo.setSignature(inputObj.getString("signature"));
        if (inputObj.getString("isreverse") != null && !"".equals(inputObj.getString("isreverse"))) {
            orderInfo.setStatus(inputObj.getString("isreverse"));
        }
        return orderInfo;
    }


    /**
     * 彩铃通知
     *
     * @param orderInfo
     */
    public String clnotify(OrderInfo orderInfo) throws Exception {
        String errorcode = "0";
        String errorinfo = "";
        String jsonParams = "";
        String spname = "";
        HashMap map = new HashMap();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {

            String userid = orderInfo.getUserid();
            String cpid = orderInfo.getCpid();
            String spid = orderInfo.getSpid();
            String consumeType = orderInfo.getType();//订购还是退订 订购1，退订2
            List<HashMap> spInfoList = commConfDao.findSpInfo(spid);
            if (spInfoList != null && spInfoList.size() > 0) {
                HashMap hm = spInfoList.get(0);
                if (hm.get("SPNAME") != null && !"".equals(hm.get("SPNAME"))) {
                    spname = hm.get("SPNAME").toString();
                }
            }
            HashMap relation = commConfDao.findOrderRela(userid, cpid, spid);
            if (relation != null && relation.size() > 0) {
                String status = relation.get("STATUS") == null ? "" : relation.get("STATUS").toString();
                //订购关系表状态 status 0：订购 1 退订 但暂未到失效时间 2 退订 已过期
                System.out.println("Status===>" + status);
                System.out.println("consumtype===>" + consumeType);
                if (!"".equals(status)) {
                    JSONObject json = new JSONObject();
                    if ("1".equals(consumeType) && "0".equals(status)) {//订购时 必须和订购关系表中的状态一致
                        json.put("subTime", relation.get("ORDERTIME"));//订购时间
                        json.put("startTime", relation.get("ORDERTIME"));//生效时间
                    } else if ("2".equals(consumeType) && "1".equals(status)) {   //退订时是否只能根据status todo *********
                        json.put("unsubTime", relation.get("CANCELTIME"));//退订时间
                        if (relation.get("ENDTIME") == null || "".equals(relation.get("ENDTIME"))) {
                            String lastday = getMonthLastDay();
                            json.put("expireTime", lastday);//失效时间
                        } else {
                            json.put("expireTime", relation.get("ENDTIME"));//失效时间
                        }
                    } else {
                        throw new BussinessException("8003", "订购状态与订购关系表中不一致");
                    }

                    String isreverse = "0";
                    if (orderInfo.getStatus() != null && !"".equals(orderInfo.getStatus())) {
                        isreverse = orderInfo.getStatus();
                    }

                    /*添加到表*/
                    map.put("id", colorSealDao.getNo());
                    map.put("userid", userid);
                    map.put("cpid", cpid);
                    map.put("spid", spid);
                    map.put("orderid", relation.get("ID"));
                    map.put("ordertype", consumeType);
                    map.put("interface", "colorsealnotify");
                    map.put("isreverse", isreverse);//是否是从反向通知过来的
                    map.put("channel", orderInfo.getSubchannel());
                    colorSealDao.addColorSealRec(map);
                    /*end*/

                    //调接口
                    String url = dictionaryDao.getValue("colorsealNotifyUrl");
                    json.put("callNumber", userid);
                    json.put("orderId", relation.get("ID"));
                    json.put("comsumeType", consumeType);
                    json.put("productId", spid);
                    json.put("productName", spname);
                    json.put("productType", "MangoTV");//写死
                    jsonParams = json.toString();
                    System.out.println(jsonParams);
                    String appkey = "3000008034";
                    String sec = "7F36701AC59E64DA";
                    String timestamp = sdf.format(new Date());
                    String digest = md5("appkey" + appkey + "timestamp" + timestamp + sec);
                    String args = "?appkey=" + appkey + "&timestamp=" + timestamp + "&digest=" + digest;
                    url += args;
                    System.out.println("url====>" + url);
                    String result = URLUtil.postJson(url, jsonParams);
                    log.info(url);
                    log.info(jsonParams.toString());
                    System.out.println(result);
                    JSONObject resjson = JSONObject.fromObject(result);
                    if (resjson != null && resjson.size() > 0) {
                        String resultcode = resjson.get("returnCode").toString();
                        String description = resjson.get("description") == null ? "" : resjson.get("description").toString();
                        if (!"000000".equals(resultcode)) {
                            //retry
                            int retry = 0;
                            while (!"000000".equals(resultcode)) {
                                result = URLUtil.postJson(url, jsonParams);
                                resjson = JSONObject.fromObject(result);
                                resultcode = resjson.get("returnCode").toString();
                                retry++;
                                log.info("restry===>" + retry + "    result==>" + result);
                                if (retry == 3) {
                                    break;
                                }
                                Thread.currentThread().sleep(1000);//等待两秒
                            }
                            //取最后一次的
                            description = resjson.get("description") == null ? "" : resjson.get("description").toString();
                            //更新表
                            map.put("resultcode", resultcode);
                            map.put("resultinfo", description);
                            map.put("retry", retry);
                            colorSealDao.upColorSealRec(map);
                            throw new BussinessException(resultcode, description);
                        }
                        //一次成功的更新表
                        map.put("resultcode", resultcode);
                        map.put("resultinfo", description);
                        map.put("retry", 0);
                        colorSealDao.upColorSealRec(map);
                    }
                    log.info("notifyurl==>" + url + "  result==>" + result);
                } else {
                    throw new BussinessException("8004", "订购关系表中无数据");
                }
            } else {
                throw new BussinessException("8004", "订购关系表中无数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (e instanceof BussinessException) {
                errorcode = ((BussinessException) e).getCode();
                errorinfo = ((BussinessException) e).getMessage();
            } else {
                errorcode = "8000";
                errorinfo = "出现异常，" + e.toString();
            }
            throw e;
        } finally {
            if (map.get("id") != null && !"".equals(map.get("id"))) {
                return map.get("id").toString();
            }
            return "";
        }
    }

    /**
     * 彩铃一键设置
     *
     * @param orderInfo
     */
    public void clset(OrderInfo orderInfo, String ringid) throws Exception {
        String errorcode = "0";
        String errorinfo = "";
        String jsonParams = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            String userid = orderInfo.getUserid();
            String cpid = orderInfo.getCpid();
            String spid = orderInfo.getSpid();
            HashMap relation = commConfDao.findOrderRela(userid, cpid, spid);
            if (relation != null && relation.size() > 0) {
                String status = relation.get("STATUS") == null ? "" : relation.get("STATUS").toString();
                //订购关系表状态 status 0：订购 1 退订 但暂未到失效时间 2 退订 已过期
                if (!"".equals(status)) {
                    String isreverse = "0";
                    if (orderInfo.getStatus() != null && !"".equals(orderInfo.getStatus())) {
                        isreverse = orderInfo.getStatus();
                    }
                    /*添加到表*/
                    HashMap map = new HashMap();
                    map.put("id", colorSealDao.getNo());
                    map.put("userid", userid);
                    map.put("cpid", cpid);
                    map.put("spid", spid);
                    map.put("orderid", relation.get("ID"));
                    map.put("ordertype", "");//一键设置无ordertype
                    map.put("interface", "colorsealset");
                    map.put("isreverse", isreverse);//是否是从反向通知过来的
                    map.put("channel", orderInfo.getSubchannel());
                    colorSealDao.addColorSealRec(map);
                    /*end*/

                    JSONObject json = new JSONObject();
                    String url = dictionaryDao.getValue("colorsealSetUrl");
                    json.put("phoneNumber", userid);
                    json.put("ringId", ringid);
                    json.put("isSms", true);
                    jsonParams = json.toString();
                    System.out.println(jsonParams);
                    String appkey = "3000008034";
                    String sec = "7F36701AC59E64DA";
                    String timestamp = sdf.format(new Date());
                    String digest = md5("appkey" + appkey + "timestamp" + timestamp + sec);
                    String args = "?appkey=" + appkey + "&timestamp=" + timestamp + "&digest=" + digest;
                    url += args;
                    System.out.println("url====>" + url);
                    log2.info(url);
                    log2.info(jsonParams.toString());
                    String result = URLUtil.postJson(url, jsonParams);
                    System.out.println(result);
                    JSONObject resjson = JSONObject.fromObject(result);
                    if (resjson != null && resjson.size() > 0) {
                        String resultcode = resjson.get("returnCode").toString();
                        String description = resjson.get("description") == null ? "" : resjson.get("description").toString();
                        if (!"0000".equals(resultcode)) {
                            //retry
                            int retry = 0;
                            while (!"0000".equals(resultcode)) {
                                result = URLUtil.postJson(url, jsonParams);
                                resjson = JSONObject.fromObject(result);
                                resultcode = resjson.get("returnCode").toString();
                                retry++;
                                log2.info("restry===>" + retry + "    result==>" + result);
                                if (retry == 3) {
                                    break;
                                }
                                Thread.currentThread().sleep(1000);//等待两秒
                            }
                            //取最后一次的
                            description = resjson.get("description") == null ? "" : resjson.get("description").toString();
                            //更新表
                            map.put("resultcode", resultcode);
                            map.put("resultinfo", description);
                            map.put("retry", retry);
                            colorSealDao.upColorSealRec(map);
                            throw new BussinessException(resultcode, description);
                        }
                        //一次成功的更新表
                        map.put("resultcode", resultcode);
                        map.put("resultinfo", description);
                        map.put("retry", 0);
                        colorSealDao.upColorSealRec(map);
                    }
                    log2.info("seturl==>" + url + "  result==>" + result);
                } else {
                    throw new BussinessException("8004", "订购关系表中无数据");
                }
            } else {
                throw new BussinessException("8004", "订购关系表中无数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (e instanceof BussinessException) {
                errorcode = ((BussinessException) e).getCode();
                errorinfo = ((BussinessException) e).getMessage();
            } else {
                errorcode = "8000";
                errorinfo = "出现异常，" + e.toString();
            }
            throw e;
        }
    }

    /**
     * 彩铃是否可以设置
     *
     * @param orderInfo
     */
    public void verify(OrderInfo orderInfo) throws Exception {
        String errorcode = "0";
        String errorinfo = "";
        String jsonParams = "";
        String spname = "";
        HashMap map = new HashMap();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {

            String userid = orderInfo.getUserid();
            String cpid = orderInfo.getCpid();
            String spid = orderInfo.getSpid();
            String consumeType = "1";//订购还是退订 订购1，退订2
            List<HashMap> spInfoList = commConfDao.findSpInfo(spid);
            if (spInfoList != null && spInfoList.size() > 0) {
                HashMap hm = spInfoList.get(0);
                if (hm.get("SPNAME") != null && !"".equals(hm.get("SPNAME"))) {
                    spname = hm.get("SPNAME").toString();
                }
            }
                /*添加到表*/
                map.put("id", colorSealDao.getNo());
                map.put("userid", userid);
                map.put("cpid", cpid);
                map.put("spid", spid);
                map.put("orderid", "");
                map.put("ordertype", consumeType);
                map.put("interface", "colorsealverify");
                map.put("isreverse", "0");//是否是从反向通知过来的
                map.put("channel", orderInfo.getSubchannel());
                colorSealDao.addColorSealRec(map);
                /*end*/
                //调接口
                String url = dictionaryDao.getValue("colorsealVerifyUrl");

                JSONObject json = new JSONObject();
                json.put("callNumber", userid);
                jsonParams = json.toString();
                System.out.println(jsonParams);
                String appkey = "3000008034";
                String sec = "7F36701AC59E64DA";
                String timestamp = sdf.format(new Date());
                String digest = md5("appkey" + appkey + "timestamp" + timestamp + sec);
                String args = "?appkey=" + appkey + "&timestamp=" + timestamp + "&digest=" + digest;
                url += args;
                System.out.println("url====>" + url);
                String result = URLUtil.postJson(url, jsonParams);
                log3.info(url);
                log3.info(jsonParams.toString());
                System.out.println(result);
                JSONObject resjson = JSONObject.fromObject(result);
                if (resjson != null && resjson.size() > 0) {
                    String resultcode = resjson.get("returnCode").toString();
                    String description = resjson.get("description") == null ? "" : resjson.get("description").toString();
                    //取最后一次的
                    description = resjson.get("description") == null ? "" : resjson.get("description").toString();
                    //更新表
                    map.put("resultcode", resultcode);
                    map.put("resultinfo", description);
                    map.put("retry", 0);
                    colorSealDao.upColorSealRec(map);
                    if (!"000000".equals(resultcode)) {
                        throw new BussinessException(resultcode, description);
                    }
                }
                log3.info("verifyurl==>" + url + "  result==>" + result);

        } catch (Exception e) {
            e.printStackTrace();
            if (e instanceof BussinessException) {
                errorcode = ((BussinessException) e).getCode();
                errorinfo = ((BussinessException) e).getMessage();
            } else {
                errorcode = "8000";
                errorinfo = "出现异常，" + e.toString();
            }
            throw e;
        }
    }


    /**
     * 彩铃查询
     *
     * @param orderInfo
     */
    public void query(OrderInfo orderInfo) throws Exception {
        String errorcode = "0";
        String errorinfo = "";
        String jsonParams = "";
        String spname = "";
        HashMap map = new HashMap();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            String userid = orderInfo.getUserid();
            //查表
            Map res = colorSealDao.isSuccess(userid);
            if (res != null && res.size() > 0) {
                String resultcode = res.get("RESULTCODE").toString();
                String description = res.get("RESULTINFO").toString();
                if (!"0000".equals(resultcode)) {
                    throw new BussinessException(resultcode, description);
                }
            }else{
                Map res2 = colorSealDao.hasOrder(userid);
                if (res2 != null && res2.size() > 0) {
                    throw new BussinessException("9997", "该手机号存在订单，但未找到设置彩铃结果");
                }else {
                    throw new BussinessException("9998", "该手机号未查询到相关订单");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (e instanceof BussinessException) {
                errorcode = ((BussinessException) e).getCode();
                errorinfo = ((BussinessException) e).getMessage();
            } else {
                errorcode = "8000";
                errorinfo = "出现异常，" + e.toString();
            }
            throw e;
        }
    }


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

    private void paramValidate(OrderInfo orderInfo) throws Exception {
        if (orderInfo != null) {
            if (orderInfo.getUserid() == null || orderInfo.getSpid() == null ||
                    orderInfo.getCpid() == null || orderInfo.getChannel() == null ||
                    orderInfo.getSignature() == null) {
                throw new BussinessException("80015", "参数异常");
            }
        }
    }


    /**
     * 拼接签名信息 orderid+channel+timestamp
     *
     * @param
     * @return
     */
    public String getSign(OrderInfo orderInfo, int type, String ringid) 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());
        if (type == 1 && !"".equals(ringid)) {
            strb.append(ringid);
        }
        strb.append(orderInfo.getTimestamp());
        return strb.toString();
    }

    /**
     * 签名验证
     *
     * @param
     * @throws Exception
     */
    public void signValidate(OrderInfo orderInfo, int type, String ringid) throws Exception {
        String lcalsign = getSign(orderInfo, type, ringid);
        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
     * @throws Exception
     */
    private void mobValidate(OrderInfo orderInfo) throws Exception {
        String userid = orderInfo.getUserid();
        if (StringUtils.isEmpty(userid)) {
            throw new BussinessException("10007", "手机号不能为空");
        }
        ChannelBean channelBean = channelDao.queryChannel(orderInfo.getChannel());
        try {
            userid = DesUtil.decode(userid, channelBean.getPassword());//解密
            if (isValid(userid) && userid.length() == 11) {
                orderInfo.setUserid(userid);//重新设置手机号码为源码
            } else {
                throw new BussinessException("10009", "手机号错误");
            }
        } catch (Exception e) {
            if (e instanceof BussinessException) {
                throw e;
            } else {
                throw new BussinessException("10008", "手机号加密错误");
            }
        }
    }

    private boolean isValid(String usermob) {
        if (usermob == null) {
            return false;
        }
        usermob = usermob.replaceAll("[\\s-]", "");

        return usermob.matches(".*(1\\d{10}).*");
    }

    public static String md5(String str) {
        try {
            MessageDigest alga = MessageDigest.getInstance("MD5");
            alga.update(str.getBytes());
            byte[] digesta = alga.digest();
            return byte2hex(digesta);
        } catch (Exception e) {
        }
        return "";
    }

    public static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0xFF);
            if (stmp.length() == 1)
                hs = hs + "0" + stmp;
            else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    private String getMonthLastDay() {
        //设置时间格式
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        //获得实体类
        Calendar ca = Calendar.getInstance();
        //设置最后一天
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        //最后一天格式化
        String lastDay = format.format(ca.getTime());
        return lastDay + "235959";
    }

    public static void main(String[] args) {
        JSONObject json = new JSONObject();
        String jsonParams = "";
//        json.put("callNumber", "userid");
//        json.put("orderId","ID");
//        json.put("consumeType","consumeType");
//        json.put("productId","spid");
//        json.put("productName", "spname");
//        json.put("productType", "");
        jsonParams = "{\"callNumber\":\"userid\",\"orderId\":\"ID\",\"consumeType\":\"consumeType\",\"productId\":\"spid\",\"productName\":\"spname\",\"productType\":\"\"}";
        System.out.println(jsonParams);
        System.out.println("-----------------");
        System.out.println(JSONObject.fromObject(jsonParams));
        System.out.println(md5("appkey=3000008034&timestamp=20201116105905"));

    }
}
