package com.chinacreator.video.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.QueenCardDao;
import com.chinacreator.video.util.MD5;
import com.chinacreator.video.util.RedisService;
import com.chinacreator.video.util.URLUtil;
import com.chinacreator.video.validate.BusiValidate;



/**
 * 女王卡服务处理
 * @author xu.zhou
 * @date 20200221
 */
@Component
public class QueenCardService {

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

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

    @Autowired
    private BusiValidate busiVali;

    @Autowired
    RedisService redisService;

    @Autowired
    private QueenCardDao queenCardDao;

    @Autowired
    private DictionaryDao dictionaryDao;

    @Autowired
    private ChannelDao channelDao;

    @Autowired
    private CommConfDao commConfDao;

    /**
     * 业务检查
     * @param orderInfo
     * @throws Exception
     */
    public void checkBusi(OrderInfo orderInfo) throws Exception {
        busiVali.valiTime(orderInfo);
        busiVali.valiChannel(orderInfo);
        signValidate(orderInfo);
        busiVali.valiMob(orderInfo);
        //orderInfo.setCpid("qryQcAuth");
        //orderInfo.setSpid("0000");
        busiVali.valiIp(orderInfo);
        checkMutual(orderInfo);
    }

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

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

    /**
     * 业务处理
     * @param orderInfo
     * @return 女王卡产品ID
     * @throws Exception
     */
    public String busiProcess(OrderInfo orderInfo)throws Exception {
        //女王卡产品编码，用于前台区分女王卡类型
        String productid = valiVipmon(orderInfo);

        //判断用户手机号码是否欠费
        qryEcb(orderInfo.getUserid());

        return productid;
    }

    /**
     * 验证领取月份
     * @param orderInfo
     * @return 女王卡产品ID
     * @throws Exception
     * 同一手机号码不会订购不同的女王卡
     */
    public String valiVipmon(OrderInfo orderInfo)throws Exception {
        String productid = ""; //女王卡产品编码，用于前台区分女王卡类型
        //当月是否已经领取
        valiCurrMonthVipStatus(orderInfo);
        //查询女王卡订购关系
        List<HashMap> orderList = queenCardDao.getOrder(orderInfo.getUserid());
        if(orderList != null && orderList.size()>0){//有女王卡订购
            HashMap hm = null;
            for(int i=0; i<orderList.size(); i++){
                hm = orderList.get(i);
                productid = (String)hm.get("PRODUCTID"); //获取产品编码
                try {
                    //遍历所有女王卡订购关系，判断是否有领取资格
                    vipmonSub(hm);
                    break; //只要有一个订购关系验证未抛异常，代表验证通过，跳出循环
                } catch (Exception e) {
                    if(e instanceof BussinessException) {
                        //如果有多条订购关系，只有最后一条仍是验证未通过才报异常
                        if((i+1) == orderList.size()){
                            throw e;
                        }
                    }else {
                        e.printStackTrace();
                        throw e;
                    }
                }
            }
        }else{
            throw new BussinessException("9011", "未订购");
        }

        //查询是否是老 产品id 90733280
        //是就去查询号码白名单表 是就正常执行  不是就抛出异常

        if("90733280".equals(productid)){
            int count = queenCardDao.isWhiteList(orderInfo.getUserid());

            if(count>0){

            }else{
                throw new BussinessException("9023", "抱歉，非女王卡首发版用户(佳琦直播间)无法领取");
            }
        }




        //查询产品是否开放
        valiSwitch(productid);

        //判断当前日号是否大于或等于5
        if(!valiDay()){
            throw new BussinessException("9012", "未到领取时间");
        }
        return productid;
    }

    /**
     * 查询产品是否开放
     * @param productid
     * @throws Exception
     */
    private void valiSwitch(String productid) throws Exception{
        //'90733280|0#000000|1', '新女王卡领取开关，格式：产品编码|开头标识，多个用#分隔，1关，0开'
        String queencardswitch = dictionaryDao.getValue("queencardswitch");
        if(queencardswitch != null && !"".equals(queencardswitch) && queencardswitch.length() != 0){
            String [] switchArray = queencardswitch.split("#");
            String [] tmpConf = null;
            boolean flag = false;
            for(String tmp : switchArray){
                tmpConf = tmp.split("\\|");
                if(productid.equals(tmpConf[0]) && "0".equals(tmpConf[1])){//产品配置为关闭状态
                    flag = true;
                    break;
                }
            }
            if(!flag){ //
                if(!"90733280".equals(productid)){
                    throw new BussinessException("9018", "禁止新女王卡用户领取");
                }else{
                    throw new BussinessException("9018", "禁止女王卡用户领取");
                }
            }
        }
    }

    private void vipmonSub(HashMap hm)
            throws BussinessException, ParseException {
        int maxvipmon = 12; //最大领取会员次数
        boolean hasvip = false; //是否可以领取
        String currMonth = new SimpleDateFormat("yyyyMM").format(new Date());
        String orderMonth = ((String)hm.get("ORDERTIME")).substring(0,6);
        String vipmon = (String)hm.get("VIPMON");
        if(vipmon != null && !"".equals(vipmon) && !"null".equals(vipmon)){ //有会员可领取月份记录
            String [] vipmonArray = vipmon.split(",");
            int vipmonArrayLen = vipmonArray.length; //月份个数
            if(vipmon.contains(currMonth)){ //可领取会员月份包含当前月，再判断当月是否领取过会员
                int index = 1;
                //判断当前月份是否在12个月之内
                for(int i=0; i<vipmonArrayLen; i++){
                    if(currMonth.equals(vipmonArray[i])){
                        index = i+1;
                        break;
                    }
                }
                if(index > 12){
                    throw new BussinessException("9021", "已超出领取时效，暂无法领取");
                }else{
                    hasvip = true;
                }
            }else if("0".equals(hm.get("STATUS"))){//已订购
                if(vipmonArrayLen >= maxvipmon){//可领取会员月份个数大于最大值
                    throw new BussinessException("9020", "会员领取次数已超过最大限制");
                }
                if(valiOrderDate((String)hm.get("ORDERTIME"), 0)){//当前月份大于订购月份
                    //获取剩余领取会员月份
                    int surpcnt = maxvipmon - vipmonArrayLen;
                    String surpvipmon = ""; //剩余领取会员月份
                    String tmp = "";
                    for(int i = 1; i <= surpcnt; i++){
                        tmp += ","+this.addMonth(orderMonth, i);
                    }

                    surpvipmon = tmp.substring(1);
                    if(surpvipmon.contains(currMonth)){
                        hasvip = true;
                    }else{
                        throw new BussinessException("9021", "已超出领取时效，暂无法领取");
                    }
                }else{
                    throw new BussinessException("9012", "已订购，但未到领取时间");
                }
            }else{//已退订, vipmon比当前月份小，或者vipmon比当前月份大
                //vipmon最小的月份比当前月份大
                if(Integer.parseInt(vipmonArray[0]) > Integer.parseInt(currMonth)){ //可领取会员最小月份大于当前月份
                    throw new BussinessException("9022", "已退订，未到领取时间");
                }
                //vipmon比当前月份小
                throw new BussinessException("9013", "已退订");
            }
        }else{//没会员可领取记录（从未退订，或者退订后又订购）
            if("0".equals(hm.get("STATUS"))){//已订购
                if(!valiOrderDate((String)hm.get("ORDERTIME"), 0)){//当前月份大于订购月份
                    throw new BussinessException("9012", "已订购，但未到领取时间");
                }
                //获取剩余领取会员月份
                String surpvipmon = ""; //剩余领取会员月份
                String tmp = "";
                for(int i = 1; i <= maxvipmon; i++){
                    tmp += ","+this.addMonth(orderMonth, i);
                }

                surpvipmon = tmp.substring(1);
                if(surpvipmon.contains(currMonth)){ //可领取月份包含当前月份
                    hasvip = true;
                }else{
                    throw new BussinessException("9021", "已超出领取时效，暂无法领取");
                }
            }else{//已退订，vipmon没数据证明是当月订购后当月又退订
                String cancelMonth = ((String)hm.get("CANCELTIME")).substring(0,6);
                if(orderMonth.equals(cancelMonth)){
                    throw new BussinessException("9013", "订购当月已退订");
                }

                //重新获取可领取会员月份，防止女王卡订购表vipmon数据未更新
                int pushmonth = differMonth(cancelMonth, orderMonth); //获取相差月份值
                //获取剩余领取会员月份
                String surpvipmon = ""; //剩余领取会员月份
                String tmp = "";
                for(int i = 1; i <= pushmonth; i++){
                    tmp += ","+this.addMonth(orderMonth, i);
                }
                surpvipmon = tmp.substring(1);
                if(surpvipmon.contains(currMonth)){
                    int vipindex = 0;
                    String [] vipmonArray = surpvipmon.split(",");
                    for(int i=0; i<vipmonArray.length; i++){
                        if(vipmonArray[i].equals(currMonth)){
                            vipindex = i+1;
                            break;
                        }
                    }
                    if(vipindex <= maxvipmon){//在订购日期的12个月内
                        hasvip = true;
                    }else{
                        throw new BussinessException("9013", "已退订且会员领取超出时效");
                    }
                }else{
                    throw new BussinessException("9013", "已退订且会员领取超出时效");
                }
            }
        }
    }

    /**
     * 获取两个日期相差月份
     * @param canceltime
     * @param ordertime
     * @throws ParseException
     */
    private int differMonth(String canceltime, String ordertime) throws ParseException{
        int months = 0;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        Calendar bef = Calendar.getInstance();
        Calendar aft = Calendar.getInstance();
        bef.setTime(sdf.parse(ordertime));
        aft.setTime(sdf.parse(canceltime));
        int month = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
        int year = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;

        months = year + month;
        logger.info("相差月份：months: " + months + ", year: " + year+", month: "+month);
        return months;
    }

    /**
     * 获取添加月份后的月份值
     * @param ordermonth 订购月份
     * @param amount 要增加的月份值
     * @return
     * @throws ParseException
     */
    private String addMonth(String ordermonth , int amount) throws ParseException{
        String res = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        Calendar ordertime = Calendar.getInstance();
        ordertime.setTime(sdf.parse(ordermonth));
        ordertime.add(Calendar.MONTH, amount);
        res =  sdf.format(ordertime.getTime());
        logger.info("添加月份后的月份值: "+res+", ordermonth: "+ordermonth+", amount: "+amount);
        return res;
    }

    /**
     * 验证当月会员领取状态
     * @param orderInfo
     * @throws Exception
     */
    public void valiCurrMonthVipStatus(OrderInfo orderInfo)throws Exception {
        List<HashMap> orderRelList = queenCardDao.findOrderRelaAll(orderInfo.getUserid());
        if(orderRelList != null && orderRelList.size()>0){
            for(HashMap hmdr : orderRelList){
                if(valiOrderDate((String)hmdr.get("ORDERTIME"), 3)){
                    throw new BussinessException("9015", "当月已领取");
                }
            }
        }
        List<HashMap> drawList = queenCardDao.getBackOrder(orderInfo.getUserid());
        int vipcount = 0; //已领取次数
        if(drawList != null && drawList.size()>0){
            //'赠送会员状态，0成功，1待赠送，2赠送中，3失败，4不赠送，5超时9070，6重试中，7重试失败，8已冻结';
            String vipstatus = "";
            //遍历所有当月订购的数据，只要有成功的，代表已领取
            for(HashMap tmp : drawList){
                if("0".equals(tmp.get("RESULTCODE"))){
                    vipcount ++;
                }
                vipstatus = (String)tmp.get("VIPSTATUS");
                if(valiOrderDate((String)tmp.get("ORDERTIME"), 3)){
                    if("0".equals(vipstatus)){
                        throw new BussinessException("9015", "当月已领取");
                    }else if("1".equals(vipstatus) || "2".equals(vipstatus) || "6".equals(vipstatus) || ("5".equals(vipstatus) && tmp.get("RETRYTIME") == null)){//1待赠送，2赠送中，6重试中
                        throw new BussinessException("9019", "业务正在办理中");
                    }
                }
            }
            //判断成功办理次数是否超过12次
            if(vipcount >= 12){
                throw new BussinessException("9021", "已超出领取时效，暂无法领取");
            }
        }
    }

    /**
     * 判断当前日号是否大于或等于5
     * @return
     */
    private boolean valiDay(){
        boolean res = false;
        //当前时间
        Calendar cal_curr = Calendar.getInstance();
        if(cal_curr.get(Calendar.DATE) >= 5){
            res = true;
        }
        return res;
    }

    /**
     * 判断订购月份是否大于或者等于当前月份
     * @param ordertime
     * @param type 0判断当前月份是否大于订购月份，1判断当前月份是否等于或大于退订月份,3 判断月份是否等于当前月份
     * @return
     */
    private boolean valiOrderDate(String ordertime, int type){
        boolean res = false;
        //当前年月
        String currDate = new SimpleDateFormat("yyyyMM").format(new Date());
        String tmpDate = ordertime.substring(0,6);
        if(type == 0){//订购，当前月份必须大于订购月份
            if(Long.parseLong(currDate) > Long.parseLong(tmpDate)){
                res = true;
            }
        }else if(type == 1){//退订，当前月份必须大于等于退订月份
            if(Long.parseLong(currDate) >= Long.parseLong(tmpDate)){
                res = true;
            }
        }else{
            if(Long.parseLong(currDate) == Long.parseLong(tmpDate)){
                res = true;
            }
        }

        return res;
    }

    /**
     * 判断是否当月退订
     * @param canceltime
     * @return
     * @throws Exception
     */
    private boolean valiCancelDate(String canceltime)throws Exception {
        boolean res = false;
        //当前年月
        String currDate = new SimpleDateFormat("yyyyMM").format(new Date());
        String tmpDate = canceltime.substring(0,6);
        if(Long.parseLong(currDate) == Long.parseLong(tmpDate)){
            res = true;
        }
        return res;
    }

    /**
     * 查询三户接口，判断用户是否欠费
     * @param userid
     * @throws Exception
     */
    private void qryEcb(String userid)throws Exception {
        String result = null;
        try {
            result = URLUtil.get(
                    dictionaryDao.getValue("ecbUrl") + "?userid=" + userid + "&cpid=queenCard&spid=0000",
                    NumberUtils.toInt(dictionaryDao.getValue("ecbTimeout")));
            //result ="{\"errorInfo\":\"三户查询用户异常：欠费号码\",\"resultCode\":\"10002\",\"pacakge\":\"[POL064]新4G沃享流量王29档\",\"brand\":\"全球通\"}";
        } catch (Exception e) {
            throw new BussinessException("9017","查询是否欠费出现异常，"+e.getMessage());
        }
        if (result == null) {
            throw new BussinessException("9017","查询是否欠费失败，返回信息为空");
        }
        log.info("三户查询结果=>"+result);
        JSONObject obj = JSON.parseObject(result);
        if (!"0".equals(obj.get("resultCode")) && !"10003".equals(obj.get("resultCode"))){
            String errorInfo = obj.get("errorInfo").toString();
            if(errorInfo.contains("欠费")){
                throw new BussinessException("9016","手机号码欠费");
            }else{
                throw new BussinessException("9017","系统繁忙，请稍后再试");
            }

        }
    }

    /**
     * 获取订购数据
     * @param orderInfo
     * @return
     */
    public List<HashMap> qryOrderRes(OrderInfo orderInfo)throws Exception {
        List<HashMap> orderList = new ArrayList<HashMap>();
        boolean hasorder = false;
        List<HashMap> drawList = queenCardDao.getBackOrder(orderInfo.getUserid());
        if(drawList != null && drawList.size()>0){
            for(HashMap hmdr : drawList){
                if("0".equals(hmdr.get("VIPSTATUS"))){//只要领取成功记录
                    hasorder = true;
                    //移除不必要的数据
                    hmdr.remove("CHANNEL");
                    hmdr.remove("PROVINCE");
                    hmdr.remove("AREA");
                    hmdr.remove("VIPSTATUS");
                    hmdr.remove("RETRYTIME");
                    hmdr.remove("RESULTINFO");
                    hmdr.remove("RESULTCODE");
                    orderList.add(hmdr);
                }
            }
        }
        if(!hasorder){
            throw new BussinessException("9014", "无订购成功记录");
        }
        return orderList;
    }

    public void checkBusiRes(OrderInfo orderInfo) throws Exception {
        busiVali.valiTime(orderInfo);
        busiVali.valiChannel(orderInfo);
        signValidate(orderInfo);
        busiVali.valiMob(orderInfo);
        busiVali.valiIp(orderInfo);

    }

    /**
     * 设置SP相关信息
     * @param orderInfo
     * @throws Exception
     */
    private void getMutex(OrderInfo orderInfo) throws Exception {
        List<HashMap> spInfoList = commConfDao.findSpInfo(orderInfo.getSpid());
        if (spInfoList != null && spInfoList.size() > 0) {
            HashMap hm = spInfoList.get(0);
            if(hm.get("MUTEX") != null && !"".equals(hm.get("MUTEX")) && !"null".equals(hm.get("MUTEX"))){
                orderInfo.setMutex(hm.get("MUTEX").toString());
            }
        }
    }

    private void checkMutual(OrderInfo orderInfo) throws Exception{
        getMutex(orderInfo);
        if(orderInfo.getMutex() != null){
            String[] mutexSpids = orderInfo.getMutex().trim().split(",");
            List<HashMap> orderList = commConfDao.findOrderRelaAll(orderInfo.getUserid());
            if (orderList != null && orderList.size() > 0) {
                for (String mutexSpid : mutexSpids) {
                    for (HashMap hm : orderList) {
                        if (hm.get("SPID") != null && !hm.get("SPID").equals(orderInfo.getSpid()) && hm.get("SPID").equals(mutexSpid)
                                && !"2".equals(hm.get("STATUS"))) {
                            throw new BussinessException("9010", "已办理互斥业务");
                        }
                    }
                }
            }
        }
    }
}
