package com.chinacreator.video.restful.service;


import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.bean.OrderLog;
import com.chinacreator.video.exception.BusinessException;
import com.chinacreator.video.mapper.CommConfDao;
import com.chinacreator.video.mapper.DictionaryDao;
import com.chinacreator.video.restful.bean.BackBusiOrderRec;
import com.chinacreator.video.restful.bean.BackOrderLog;
import com.chinacreator.video.restful.dao.BackBusiOrderDao;
import com.chinacreator.video.service.CommonService;
import com.chinacreator.video.util.URLUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 后向产品异步处理
 * @author xu.zhou
 * @date 20200817
 */
@Component
public class BackBusiOrderAsynService {

	private static Logger busilog = Logger.getLogger("woread");
    

	@Autowired
	private BackBusiOrderDao backBusiOrderDao;

    @Autowired
    private CommonService commonService;


    @Autowired
    private DictionaryDao dictionaryDao;

    @Autowired
    private CommConfDao commConfDao;


	/**
	 * 业务办理
	 * @param orderInfo
	 * @return
	 * @throws Exception
	 */
	public String orderBusi(OrderInfo orderInfo)throws Exception {
		if( "0".equals( orderInfo.getType())){//订购
			orderInfo.setStatus("0"); ////设置为订购
            orderInfo.setOrderstatus("3");
			return this.order(orderInfo);
		}else{
			throw new BusinessException("8000", "不支持操作类型，"+orderInfo.getType(), new String[0]);
		}
	}


    /**
     * 填充BackBusiOrderRec
     * @param orderInfo
     * @return
     * @throws Exception
     */
    private BackBusiOrderRec getOrderRecBean(OrderInfo orderInfo) throws Exception{
        BackBusiOrderRec bean = new BackBusiOrderRec();
        bean.setLogid(orderInfo.getReorderid());
        bean.setId(backBusiOrderDao.generateID());
        bean.setArea(orderInfo.getArea());
        bean.setCpid(orderInfo.getCpid());
        bean.setSpid(orderInfo.getSpid());
        bean.setOrderid(orderInfo.getOrderid());
        bean.setProvince(orderInfo.getProvince());
        bean.setUserid(orderInfo.getUserid());
        bean.setChannel(orderInfo.getChannel());
        bean.setSubchannel((orderInfo.getSubchannel() != null && !"null".equals(orderInfo.getSubchannel())) ? orderInfo.getSubchannel() : "");
        bean.setVipstatus("4"); //默认设置为不赠送
        bean.setType(orderInfo.getType()+"");
        if("1".equals(bean.getType())){//退订
            bean.setVipstatus(""); //设置为空
        }
        return bean;
    }
	/**
	 * 订购业务
	 * @param orderInfo
	 * @return
	 */
	public String order(OrderInfo orderInfo)throws Exception {
		String errorcode = "-1";
		String errorinfo = "";
		String result = "-1";
		BackBusiOrderRec bean = getOrderRecBean(orderInfo);
		try {
			orderInfo.setType("0"); //设置为订购
			List<HashMap> confList = backBusiOrderDao.getBackBusiConf(orderInfo.getCpid(), orderInfo.getSpid());
			//[{PWD=kijkfds, CHANNEL=test_01, VIPTYPE=2, VIPPOOL=vip_yout, SPID=1168, BUSITYPE=3, CPID=youtu}]
			HashMap confHm = confList.get(0);
			String busiType = confHm.get("BUSITYPE")+"";
			//是否为复合产品，0是，为空或为1时不是
			String hasfh = confHm.get("HASFH") == null ? "": confHm.get("HASFH")+"";
   		   //调能力平台标识：0调能力平台并以结果落订购关系，1调能力平台其结果不影响订购关系，为空时不调能力平台
			String hasshare = confHm.get("HASSHARE") == null ? "": confHm.get("HASSHARE")+"";
			bean.setBusitype(busiType);

			this.hasDupliOrderid(orderInfo);//判断是否重复订单ID

			this.hasMutual(orderInfo); //已办理互斥业务

			String newEndtime = ""; 	//业务结束时间
			String starttime = ""; 		//业务开始时间
			Map<String, String> resMap = this.getBusiTime(orderInfo);
			newEndtime = resMap.get("endtime");
			starttime = resMap.get("starttime");
			//赠送会员状态，0成功，1待赠送，2赠送中，3失败
			//bean.setVipstatus("1");
			//办理结果编码，0成功，1待处理，2处理中，其他为异常
			bean.setResultcode("2");
			bean.setResultinfo("处理中");
			if("2".equals(busiType)){ //免流
				bean.setVipstatus("4"); //设置为不赠送
				bean.setStarttime(starttime);
				bean.setEndtime(newEndtime);
				backBusiOrderDao.addOrderRec(bean); //添加订购记录

				orderInfo.setEndtime(newEndtime);
				//设置订购时间
				this.setOrderTime(orderInfo);
				//调能力平台
				//this.shareOrder(orderInfo, hasshare);

				backBusiOrderDao.order(orderInfo); //新增或更新订购关系
			}else {
			    throw new BusinessException("9001","当前只能订购纯免流产品");
            }
			result = "0";
			errorcode = "0";
			errorinfo = "成功";
		} catch (Exception e) {
			e.printStackTrace();
			busilog.error("userid:"+orderInfo.getUserid()+"订购出现异常，"+e);

			if ((e instanceof BusinessException)) {
				errorcode = ((BusinessException) e).getErrorcode();
				errorinfo = ((BusinessException) e).getMessage();
			}else{
				errorcode = "8000";
				errorinfo ="系统忙，"+e.getMessage();
			}
			if(errorinfo != null && errorinfo.length()>2000){
				errorinfo = errorinfo.substring(0, 2000);
			}
			throw e;
		} finally {
			bean.setResultcode(errorcode);
			bean.setResultinfo(errorinfo);
			if(bean.getResultinfo().indexOf("重复订单") == -1){
				try{
					backBusiOrderDao.addOrderRec(bean); //添加订购记录
				}catch(Exception e){
					busilog.info(orderInfo.getUserid()+"，更新订购记录表出现异常，"+e.getMessage());
				}
			}
			orderInfo.setOrderchannel(orderInfo.getChannel());
			saveLog(orderInfo, errorcode, errorinfo);
            if("0".equals(errorcode)){
                HashMap<String, Object> remap = commonService.getOrderStatus(orderInfo.getUserid(),orderInfo.getSpid());
                String relid = (String)remap.get("RELID"); //订购关系表ID
                if(relid == null || "".equals(relid)){
                    relid = commConfDao.generateId();
                }
                orderInfo.setId(relid);
                //添加订单ID与订购关系的关联记录
                commonService.addRelidRec(orderInfo);
            }
		}
		return result;
	}

    /**
     * 调能力平台
     * @param orderInfo
     * @param hasshare //调能力平台标识：0调能力平台并以结果落订购关系，1调能力平台其结果不影响订购关系，为空时不调能力平台，
     * @throws Exception
     */
    private void shareOrder(OrderInfo orderInfo, String hasshare) throws Exception{
        if("0".equals(hasshare) || "1".equals(hasshare)){
            String shareErcode = "0";
            String shareErnfo = "成功";
            if("0".equals(hasshare)){//以能力平台调用结果落订购关系的要设置渠道为SHARE，此渠道记录在订购关系表和订购日志表中
                orderInfo.setChannel("SHARE");
            }else{
                orderInfo.setChannel("");
            }
            try {
                this.order(orderInfo.getUserid(),orderInfo.getCpid(),orderInfo.getSpid());
            } catch (BusinessException e) {
                e.printStackTrace();
                shareErcode = e.getErrorcode();
                shareErnfo = e.getMessage();
                if("0".equals(hasshare)){
                    throw new BusinessException("8888","调用能力共享平台订购接口失败");
                }
            } finally {
                saveBackShareLog(orderInfo,shareErcode,shareErnfo);
            }
        }
    }

    /**
     * 写后向订购能力平台日志
     * @param orderInfo
     * @param errorcode
     * @param errorinfo
     */
    private void saveBackShareLog(OrderInfo orderInfo,String errorcode,String errorinfo){
        BackOrderLog bso = new BackOrderLog();
        bso.setUserid(orderInfo.getUserid());
        bso.setErrorcode(errorcode);
        bso.setErrorinfo(errorinfo);
        bso.setCpid(orderInfo.getCpid());
        bso.setSpid(orderInfo.getSpid());
        try {
            backBusiOrderDao.addShareOrderLog(bso);
        } catch (Exception e) {
            e.printStackTrace();
            busilog.error("userid："+orderInfo.getUserid()+"，写后向订购能力平台日志出现异常，"+e.getMessage());
        }

    }

    /**
     * 订购
     * @param userid
     * @param cpid
     * @param spid
     * @throws BusinessException
     */
    public void order(String userid,String cpid,String spid) throws BusinessException{
        String result ="";
        String url = "";
        try{
            url = dictionaryDao.getValue("shareOrderUrl");
            result = URLUtil.get(url+"?cpid="+cpid+"&spid="+spid+"&userid="+userid,30000);
        }catch (Exception e) {
            if(e.getMessage().indexOf("connect timed out")!= -1) { //如果连接超时就再重试一次
                try {
                    result = URLUtil.get(url+"?cpid="+cpid+"&spid="+spid+"&userid="+userid,30000);
                    busilog.info(userid+"重试:"+result);
                    if(result.indexOf("您已订购，请勿重复")!= -1){ //包含您已订购，请勿重复订购
                        result = "{\"resultCode\":0,\"resultInfo\":\"成功！\",\"data\":null}";
                    }
                }catch (Exception e1){
                    throw new BusinessException("9170", "调用能力共享平台订购接口异常！");
                }
            }else {
                throw new BusinessException("9170", "调用能力共享平台订购接口异常");
            }
        }
        JSONObject obj = JSONObject.fromObject(result);
        if(!obj.getString("resultCode").equals("0")){
            throw new BusinessException(obj.getString("resultCode"), obj.getString("resultInfo"));
        }
    }

    /**
     * 写订购日志
     * @param orderInfo
     * @param errorcode
     * @param errorinfo
     */
    public void saveLog(OrderInfo orderInfo, String errorcode, String errorinfo) {
        try {
            BackOrderLog orderLog = new BackOrderLog();
            orderLog.setApptype(orderInfo.getApptype());
            orderLog.setArea(orderInfo.getArea());
            orderLog.setChannel(orderInfo.getOrderchannel());
            orderLog.setOrderstatus(Integer.parseInt(orderInfo.getOrderstatus()));
            orderLog.setStatus(Integer.parseInt(orderInfo.getStatus()));
            orderLog.setCpid(orderInfo.getCpid());
            orderLog.setIsexperience(orderInfo.getIsexperience());
            orderLog.setOrdertype(orderInfo.getOrdertype() + "");
            orderLog.setProvince(orderInfo.getProvince());
            orderLog.setArea(orderInfo.getArea());
            orderLog.setSpid(orderInfo.getSpid());
            orderLog.setUserid(orderInfo.getUserid());
            orderLog.setErrorcode(errorcode);
            orderLog.setErrorinfo(errorinfo);
            if(!orderInfo.getTimes().isEmpty()){
                orderLog.setTimes((System.currentTimeMillis()-NumberUtils.toLong(orderInfo.getTimes()))+"");
            }
            this.backBusiOrderDao.addOrderLog(orderLog);
        } catch (Exception e) {
            e.printStackTrace();
            busilog.error("userid："+orderInfo.getUserid()+"，写订购日志出现异常，"+e.getMessage());
        }
    }

    /**
     * 设置当前时间
     * @param orderInfo
     * @throws Exception
     */
    private void setOrderTime(OrderInfo orderInfo) throws Exception{
        String currtime = this.backBusiOrderDao.getCurrentTime();
        orderInfo.setOrdertime(currtime);
        orderInfo.setEffecttime(currtime);
    }

    /**
     * 判断是否有相同订单
     * @param orderInfo
     * @return true是，false否
     */
    private void hasDupliOrderid(OrderInfo orderInfo) throws Exception{
        List<BackBusiOrderRec> list = backBusiOrderDao.findOrderRecByOrderid(orderInfo.getOrderid());
        if(list != null && list.size() > 0){
            throw new BusinessException("9001", "重复订单", new String[0]);
        }
    }
    /**
     * 判断业务是否互斥
     * @param orderInfo
     * @throws Exception
     */
    private void hasMutual(OrderInfo orderInfo) throws Exception{
        boolean result = false;
        List<OrderInfo> listOrderInfo = backBusiOrderDao.findByUser(orderInfo.getUserid());

        if (listOrderInfo != null && listOrderInfo.size() > 0
                && !StringUtils.isEmpty(orderInfo.getMutex())) {
            String[] mutexSpids = orderInfo.getMutex().trim().split(",");
            for (String mutexSpid : mutexSpids) {
                for (OrderInfo oldOrderInfo : listOrderInfo) {
                    if (!oldOrderInfo.getSpid().equals(orderInfo.getSpid()) && oldOrderInfo.getSpid().equals(mutexSpid)) {
                        result = true;
                        break;
                    }
                }
            }

        }
        if(result){
            throw new BusinessException("9003","已办理互斥业务", new String[0]);
        }
    }
    /**
     * 查询本地订购关系表当前是否有已生效的订购关系
     * @param orderInfo
     * @return
     * @throws Exception
     */
    private Map hasEffect(OrderInfo orderInfo) throws Exception{
        Map reMap = new HashMap();
        boolean hasEffect = false;
        boolean hasEffectMonth=false;
        Map currOrderInfo = null;
        String currentTime = backBusiOrderDao.getCurrentTime();
        //查询用户本地订购关系表未失效的订购数据
        currOrderInfo = backBusiOrderDao.findByUserAndSpid(orderInfo.getUserid(),orderInfo.getCpid(),orderInfo.getSpid());
        if(currOrderInfo != null){//本地有订购关系
            if(Long.parseLong(currOrderInfo.get("ENDTIME").toString()) >= Long.parseLong(currentTime)){ //结束时间大于或等于当前时间，订购关系有效
                hasEffect = true;
            }
            if(currentTime.substring(0,6).equals(currOrderInfo.get("ENDTIME").toString().substring(0,6))){ //本月订购的
                hasEffectMonth = true;
            }

        }
        reMap.put("hasEffect", hasEffect);
        reMap.put("currOrderInfo", currOrderInfo);
        reMap.put("hasEffectMonth",hasEffectMonth);
        return reMap;
    }
    /**
     * 获取开始时间和结束时间
     * @param orderInfo
     * @return
     * @throws Exception
     */
    private Map<String, String> getBusiTime(OrderInfo orderInfo)throws Exception{
        Map<String, String> resMap = new HashMap<String, String>();
        String starttime = ""; //业务开始时间
        String endtime = "";   //业务结束时间
        String currEndtime = "";
        Map reMap = this.hasEffect(orderInfo);
        HashMap confHm = backBusiOrderDao.getBackBusiConf(orderInfo.getCpid(), orderInfo.getSpid()).get(0);
        //只针对日包的
        if ((Boolean)reMap.get("hasEffectMonth")){
            if("4".equals(confHm.get("ENDTYPE"))){
                throw new BusinessException("9005","本月已订购，请勿重复订购");
            }
        }
        if((Boolean)reMap.get("hasEffect")){ //存在有效订购关系
            if("1".equals(confHm.get("ENDTYPE"))){
                throw new BusinessException("9005","本月已订购，请勿重复订购");
            }
            Map currOrderInfo = (Map)reMap.get("currOrderInfo");
            currEndtime = (String)currOrderInfo.get("ENDTIME");
        }
        //[{PWD=kijkfds, NETDAYS=31, CHANNEL=test_01, NETDAYS=2, SPID=1168, BUSITYPE=3, CPID=youtu}]
        //String busiType = confHm.get("BUSITYPE")+"";
        //业务类型，1会员，2免流，3会员+免流
        //ENDTYPE: 1:结束时间到月底且不能重复订购,2:结束时间到月底且能重复订购，结束时间累加一个月,3:结束时间到月底,能重复订购,结束时间不累加。其余结束时间按netdays算且能重复订购
        //免流或免流+会员两种产品要以netdays参数来确定endtime
        if("2".equals(confHm.get("BUSITYPE")) || "3".equals(confHm.get("BUSITYPE"))){
            if(currEndtime != null && !"".equals(currEndtime)){

                if("3".equals(confHm.get("ENDTYPE"))){
                    endtime = backBusiOrderDao.endtimeTheMonthLastDay();
                }else if("2".equals(confHm.get("ENDTYPE"))){
                    endtime = backBusiOrderDao.endtimeNextMonthLastDay(currEndtime);
                }else{
                    endtime = backBusiOrderDao.endtimeParamDay(confHm.get("NETDAYS")+"", currEndtime);
                }
            }else{
                if("1".equals(confHm.get("ENDTYPE")) || "2".equals(confHm.get("ENDTYPE"))|| "3".equals(confHm.get("ENDTYPE"))){
                    endtime = backBusiOrderDao.endtimeTheMonthLastDay(); //特殊产品的结束时间只到本月底
                }else {
                    endtime = backBusiOrderDao.currParamDay(confHm.get("NETDAYS")+"");
                }
            }
            if("1".equals(confHm.get("ENDTYPE")) || "2".equals(confHm.get("ENDTYPE")) || "3".equals(confHm.get("ENDTYPE"))){
                starttime = backBusiOrderDao.getKsStartTime(); //特殊产品开始时间就是当天
            }else{
                starttime = backBusiOrderDao.getStartTime(endtime,confHm.get("NETDAYS")+"");
            }
        }

        resMap.put("starttime", starttime);
        resMap.put("endtime", endtime);
        return resMap;
    }

    public boolean getBusiCount(String spid) {
        Integer count=backBusiOrderDao.getBusiCount(spid);
        if (count==null || count==0){
            return false;
        }else {
            return true;
        }

    }
}
