package com.chinacreator.video.restful.service;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.bean.OrderInfo;
import com.chinacreator.video.restful.bean.ShangHaiObject;
import com.chinacreator.video.service.CommonService;
import com.chinacreator.video.util.MD5;
import com.chinacreator.video.util.RedisService;
import com.chinacreator.video.validate.ChannelValidate;
import com.chinacreator.video.validate.IpValidate;

/**
 * 2元上海权益
 *
 * @author zhouxu
 * @date 20190719
 */
@Component
public class ShangHaiOrderService {

    private static final Logger logger = LoggerFactory.getLogger(ShangHaiOrderService.class);

    private static final Logger log = LoggerFactory.getLogger("shanghai");

    @Autowired
    private CommConfDao commConfDao;

    @Autowired
    private ChannelValidate channelValidate;

    @Autowired
    private IpValidate ipValidate;

    @Autowired
    private ChannelDao channelDao;

    @Autowired
    RedisService redisService;

    @Autowired
    private DictionaryDao dictionaryDao;

    @Autowired
    private CommonService commonService;

    /**
     * 业务验证
     *
     * @param orderInfo
     * @throws Exception
     */
    public void checkBusi(ShangHaiObject inputObj, OrderInfo orderInfo) throws Exception {
        this.paramVali(inputObj, orderInfo);                                //验证参数
        this.valiTimetamp(orderInfo);                            //验证时间戳
        channelValidate.validate(orderInfo.getChannel());        //验证渠道
        this.valiMob(orderInfo);                                //验证手机号码
        this.valiSign(orderInfo);                                //验证签名
        ipValidate.volidate(orderInfo);                            //验证ip
//        this.checkProvince(orderInfo);                                   //上海权益接口增加省份限制  20220830去掉
        //this.checkMutual(orderInfo); 							//判断业务互斥
        this.replaceSpid(orderInfo);
        //省份办理限制验证
        commonService.valiChannelSpidLimit(orderInfo);
        this.ordercntlimit(orderInfo);
    }

    private void checkProvince(OrderInfo orderInfo) throws BussinessException {
        // 上海权益接口增加省份限制 1182、1183、1170、1172 只允许浙江省的用户订购
        String limitSpids = dictionaryDao.getValue("shanghaiLimitSpid");
        if (limitSpids.contains(orderInfo.getSpid())){
            final List<Map> areaInfo = commConfDao.getAreaInfo(orderInfo.getUserid().substring(0, 7));
            if(areaInfo != null && areaInfo.size()>0){
                Map areaMap = areaInfo.get(0);
                String province = (String)areaMap.get("PROVINCE");
                if (StringUtils.isEmpty(province) || !"浙江".equals(province)){
                    throw new BussinessException("10016", "该产品只允许浙江省用户订购");
                }
            }else {
                throw new BussinessException("10016", "该产品只允许浙江省用户订购");
            }
            log.error("spid：" + orderInfo.getSpid() + "=====" + "userid: " + orderInfo.getUserid() + "=====" + "areaInfo" + areaInfo);
        }
    }

    /**
     * 订购限制验证
     * <p>
     * 1053	畅视AI体验馆会员年卡0，每月限制上限：10万个
     * 1054 	畅视AI体验馆会员年卡3，每月限制上限：10万个
     * 1055 	畅视AI体验馆会员年卡5，每月限制上限：10万个
     *
     * @param orderInfo
     */
    private void ordercntlimit(OrderInfo orderInfo) throws Exception {
        long limitCount = 100000;
        String spid = orderInfo.getSpid();
        if ("1053".equals(spid) || "1054".equals(spid) || "1055".equals(spid)) {
            String limitKey = getLimitKey("yyyyMM");
            Object obj = redisService.hmGet("univideo_shanghai_" + spid, limitKey);
            if (obj != null && Long.parseLong(obj.toString()) >= limitCount) {
                throw new BussinessException("10033", "当月办理次数超过上限");
            }
        }
    }

    /**
     * 添加订购次数
     *
     * @param orderInfo
     */
    public void addordercnt(OrderInfo orderInfo) {
        try {
            String spid = orderInfo.getSpid();
            if ("1053".equals(spid) || "1054".equals(spid) || "1055".equals(spid)) {
                String limitKey = getLimitKey("yyyyMM");
                redisService.hincr("univideo_shanghai_" + spid, limitKey, 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(orderInfo.getUserid() + ":" + orderInfo.getSpid() + "添加订购次数出现异常" + e.getMessage(), e);
        }
    }

    private String getLimitKey(String dateFormat) {
        SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
        String limitKey = formatter.format(new Date());
        return limitKey;
    }

    /**
     * SPID转换，把业务转为后向产品
     *
     * @param orderInfo
     */
    private void replaceSpid(OrderInfo orderInfo) {
        //广东腾讯
        if ("115".equals(orderInfo.getSpid())) {
            orderInfo.setSpid("116");
        } else if ("1170".equals(orderInfo.getSpid())) { //畅视2元
            //SPID转换，把业务转为后向产品
            orderInfo.setSpid("1174");
        } else if ("1172".equals(orderInfo.getSpid())) {//畅视2元超级包
            orderInfo.setSpid("1175");
        }
    }

    /**
     * 验证timetamp
     *
     * @param inputObj
     * @throws Exception
     */
    private void valiTimetamp(OrderInfo orderInfo) throws Exception {
        SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        long currDate = new Date().getTime();
        //System.out.println("当前时间："+fm.format(new Date()));
        String time = orderInfo.getTimestamp(); //"2019-08-05 11:26:19 696"; 请求时间戳
        Date inDate = fm.parse(time);
        //System.out.println("输入时间："+fm.parse(time).toLocaleString());
        //获得这两个时间的毫秒值后进行处理(因为我的需求不需要处理时间大小，所以此处没有处理，可以判断一下哪个大就用哪个作为减数。)
        long diff = new Date().getTime() - inDate.getTime();
        //此处用毫秒值除以分钟再除以毫秒既得两个时间相差的分钟数
        long minute = diff / 60 / 1000;
        //System.out.println(minute);
        //System.out.println(minute>5); //当前时间大于时间戳分钟数超过5分钟
        //System.out.println(minute<-5); //当前时间小于时间戳超过5分钟
        if (minute > 5 || minute < -5) {
            throw new BussinessException("10002", "timestamp已失效");
        }
    }

    /**
     * 验证手机号码
     *
     * @param orderInfo
     * @throws Exception
     */
    private void valiMob(OrderInfo orderInfo) throws Exception {
        String userid = orderInfo.getUserid();
        if (StringUtils.isEmpty(userid) //为空
                || !isValid(userid)  //非全数字
                || userid.length() != 11) { //不是11位
            throw new BussinessException("10009", "手机号错误");
        }
/*		List<Map> areaList = commConfDao.getAreaInfo(orderInfo.getUserid().substring(0, 7));
		if(areaList != null && areaList.size()>0){
			//province, area
			Map areaMap = areaList.get(0);
			if(areaMap.get("PROVINCE") != null && !"".equals(areaMap.get("PROVINCE"))){
				orderInfo.setProvince(areaMap.get("PROVINCE").toString());
			}
			if(areaMap.get("AREA") != null && !"".equals(areaMap.get("AREA"))){
				orderInfo.setArea(areaMap.get("AREA").toString());
			}
		}*/
    }

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

    /**
     * 验证参数
     *
     * @param orderInfo
     * @throws BussinessException
     */
    private void paramVali(ShangHaiObject inputObj, OrderInfo orderInfo) throws Exception {
        String spids = dictionaryDao.getValue("shanghaitranspid"); //"115,1170,1172,1182,1183,1210,1211,1053,1054,1055";
        List<String> spidList = Arrays.asList(spids.split(","));
        //OrderInfo orderInfo = new OrderInfo();
        try {
            String transid = inputObj.getUni_bss_head().get("TRANS_ID").toString(); //序列号
            String timestamp = inputObj.getUni_bss_head().get("TIMESTAMP").toString();
            //orderInfo.setTimestamp(timestamp);
            JSONArray jSONArray = (JSONArray) inputObj.getUni_bss_body().getJSONObject("ACTIVE_COUPON_NO_REQ").get("ACCOUNT_PARAM");
            for (int i = 0; i < jSONArray.size(); i++) {
                Map tmpMap = (Map) jSONArray.get(i);
                if ("SIGNATURE".equals(tmpMap.get("KEY"))) {
                    orderInfo.setSignature(tmpMap.get("VALUE").toString());
                }
                if ("CPID".equals(tmpMap.get("KEY"))) {
                    orderInfo.setCpid(tmpMap.get("VALUE").toString());
                }
                if ("SPID".equals(tmpMap.get("KEY"))) {
                    orderInfo.setSpid(tmpMap.get("VALUE").toString());
                }
                if ("CHANNEL".equals(tmpMap.get("KEY"))) {
                    orderInfo.setChannel(tmpMap.get("VALUE").toString());
                }
                if ("TYPE".equals(tmpMap.get("KEY"))) {
                    orderInfo.setType(tmpMap.get("VALUE").toString());
                }
                if ("TIMESTAMP".equals(tmpMap.get("KEY"))) {
                    orderInfo.setTimestamp(tmpMap.get("VALUE").toString());
                }
            }
			/*
			JSONObject accountParam = (JSONObject)jSONArray.get(0);
			orderInfo.setChannel(accountParam.get("CHANNEL").toString());
			orderInfo.setCpid(accountParam.get("CPID").toString());
			orderInfo.setSpid(accountParam.get("SPID").toString());
			orderInfo.setType(accountParam.get("TYPE").toString());			
			orderInfo.setSignature(accountParam.get("SIGNATURE").toString());
			*/
			orderInfo.setOrdertime((String)inputObj.getUni_bss_body().getJSONObject("ACTIVE_COUPON_NO_REQ").get("ORDER_TIME"));
			orderInfo.setUserid((String)inputObj.getUni_bss_body().getJSONObject("ACTIVE_COUPON_NO_REQ").get("PHONE_NUMBER"));
			orderInfo.setOrderid((String)inputObj.getUni_bss_body().getJSONObject("ACTIVE_COUPON_NO_REQ").get("TRADE_ID"));
			//orderInfo.setReorderid(transid);
		} catch (Exception e1) {
			e1.printStackTrace();
			log.error("参数不合法，解析异常，"+e1);
			throw new BussinessException("80015", "参数不合法，解析异常，"+e1.getMessage());			
		}
		if(StringUtils.isEmpty(orderInfo.getTimestamp())
				|| StringUtils.isEmpty(orderInfo.getChannel())
				|| StringUtils.isEmpty(orderInfo.getCpid())
				|| StringUtils.isEmpty(orderInfo.getSpid())
				|| StringUtils.isEmpty(orderInfo.getSignature())
				|| StringUtils.isEmpty(orderInfo.getOrdertime())
				|| StringUtils.isEmpty(orderInfo.getUserid())
				//|| StringUtils.isEmpty(transid)
				) {
			throw new BussinessException("80015", "参数不合法，必填参数为空");
		}
		if(!"0".equals(orderInfo.getType()) 
				//&& !"1".equals(orderInfo.getType()) 
				//&& !"2".equals(orderInfo.getType())
				){
			throw new BussinessException("80015", "参数不合法，TYPE，只支持订购");
		}
		/**
		if(!"115".equals(orderInfo.getSpid()) 
				&& !"1170".equals(orderInfo.getSpid()) 
				&& !"1172".equals(orderInfo.getSpid())
				&& !"1182".equals(orderInfo.getSpid()) //20200525增加两个产品，都是后向
				&& !"1183".equals(orderInfo.getSpid())
                && !"1210".equals(orderInfo.getSpid())
                && !"1211".equals(orderInfo.getSpid())
                && !"1053".equals(orderInfo.getSpid())//畅视AI体验馆会员年卡0
                && !"1054".equals(orderInfo.getSpid())//畅视AI体验馆会员年卡3
                && !"1055".equals(orderInfo.getSpid())//畅视AI体验馆会员年卡5
        ***/
        if(!spidList.contains(orderInfo.getSpid())){
			throw new BussinessException("80015", "参数不合法，SPID");
		}
		
		//广东腾讯
		if("115".equals(orderInfo.getSpid())){
			if(!"0".equals( orderInfo.getType())){
				throw new BussinessException("80015", "参数不合法，TYPE，115只支持订购");
			}
		}		
		//畅视2元
		if("1170".equals(orderInfo.getSpid())){
			if(!"0".equals( orderInfo.getType())){
				throw new BussinessException("80015", "参数不合法，TYPE，1170只支持订购");
			}
		}
		//畅视2元超级包
		if("1172".equals(orderInfo.getSpid())){
			if(!"0".equals( orderInfo.getType())){
				throw new BussinessException("80015", "参数不合法，TYPE，1172只支持订购");
			}
		}
		
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
			sdf.parse(orderInfo.getOrdertime());
		} catch (Exception e) {
			throw new BussinessException("80015", "参数不合法，ORDER_TIME");
		}
		
		try {
			SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); 
			fm.parse(orderInfo.getTimestamp());
		} catch (Exception e) {
			throw new BussinessException("80015", "参数不合法，TIMESTAMP");
		}
		
		
/*		List<HashMap> spinfoList = commConfDao.findSpInfo(orderInfo.getSpid());
		orderInfo.setMutex("");
		if(spinfoList != null && spinfoList.size()>0){
			HashMap spinfoMap = spinfoList.get(0);
			if(spinfoMap.get("MUTEX") != null){
				orderInfo.setMutex(spinfoMap.get("MUTEX").toString());
			}		
		}*/
    }

    /**
     * 签名验证
     *
     * @param orderInfo
     * @throws Exception
     */
    private void valiSign(OrderInfo orderInfo) throws Exception {
        String lcalsign = getSign(orderInfo);
        lcalsign += channelDao.queryChannel(orderInfo.getChannel()).getPassword();
        //Md5(接入渠道+手机号码伪码+订单号+订单状态+产品编码+时间戳+密码)
        lcalsign = MD5.MD5Encode(lcalsign);
        if (!lcalsign.equals(orderInfo.getSignature())) {
            throw new BussinessException("10006", "签名校验失败");
        }
    }

    /**
     * 拼接签名信息 cpid+spid+userid+channel+timestamp
     *
     * @param orderInfo
     * @return
     */
    private String getSign(OrderInfo orderInfo) {
        if (orderInfo == null) {
            return "";
        }
        //Md5(CHANNEL+CPID+SPID+PHONE_NUMBER+TYPE+TIMESTAMP+PWD)
        StringBuilder strb = new StringBuilder();
        strb.append(orderInfo.getChannel());
        strb.append(orderInfo.getCpid());
        strb.append(orderInfo.getSpid());
        strb.append(orderInfo.getUserid());
        strb.append(orderInfo.getType());
        strb.append(orderInfo.getTimestamp());
        return strb.toString();
    }

    /**
     * json小写转大写
     *
     * @param jSONArray1 jSONArray1
     * @return JSONObject
     */
    public static JSONObject transToLowerObject(JSONObject jsonObj) {
        JSONObject reJSONObj = new JSONObject();
        Iterator it = jsonObj.keySet().iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            Object object = jsonObj.get(key);
            if (object.getClass().toString().endsWith("String")) {
                reJSONObj.put(key.toUpperCase(), object);
            } else if (object.getClass().toString().endsWith("JSONObject")) {
                reJSONObj.put(key.toUpperCase(), transToLowerObject((JSONObject) object));
            } else if (object.getClass().toString().endsWith("JSONArray")) {
                reJSONObj.put(key.toUpperCase(), transToArray(jsonObj.getJSONArray(key)));
            }
        }
        return reJSONObj;
    }

    /**
     * jsonArray转jsonArray
     *
     * @param jSONArray1 jSONArray1
     * @return JSONArray
     */
    public static JSONArray transToArray(JSONArray jsonArray) {
        JSONArray reJSONArray = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            Object obj = jsonArray.getJSONObject(i);
            if (obj.getClass().toString().endsWith("JSONObject")) {
                reJSONArray.add(transToLowerObject((JSONObject) obj));
            } else if (obj.getClass().toString().endsWith("JSONArray")) {
                reJSONArray.add(transToArray((JSONArray) obj));
            }
        }
        return reJSONArray;
    }

    /**
     * 判断业务是否互斥
     *
     * @param orderInfo
     * @throws Exception
     */
    private void checkMutual(OrderInfo orderInfo) throws Exception {
        boolean result = false;
        String spid = orderInfo.getSpid();
        if (orderInfo.getMutex() != null && !StringUtils.isEmpty(orderInfo.getMutex())) {
            String[] mutexSpids = orderInfo.getMutex().trim().split(",");
            //[{ORDERIDA=2019052, AREA=长沙, SPID=1167, PROVINCE=湖南, ID=201905241107578658666, ORDERCHANNEL=t, STATUS=1, ORDERTIME=20190524104129, USERID=18673197465, CPID=youtu}]
            //查询用户本地订购关系表未失效的订购数据
            List<HashMap> list = commConfDao.findOrderRelaAll(orderInfo.getUserid());
            if (list != null && list.size() > 0) {
                for (String mutexSpid : mutexSpids) {
                    for (HashMap hm : list) {
                        if (hm.get("SPID") != null && !hm.get("SPID").equals(spid) && hm.get("SPID").equals(mutexSpid)
                                && !"2".equals(hm.get("STATUS"))) {
                            result = true;
                            break;
                        }
                    }
                    if (result) {
                        break;
                    }
                }
            }
        }
        if (result) {
            throw new BussinessException("9003", "已办理互斥业务");
        }
    }
}
