package com.chinacreator.video.restful.service;

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.restful.dao.BackBusiConfDao;
import com.chinacreator.video.restful.dao.BackBusiOrderDao;
import com.chinacreator.video.service.CommonService;
import com.chinacreator.video.util.MD5;
import com.chinacreator.video.validate.ChannelValidate;
import com.chinacreator.video.validate.IpValidate;
import com.chinacreator.video.validate.TimetampValidate;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.tencentcloudapi.tsf.v20180326.models.TsfPageVmGroup;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.peer.ScrollbarPeer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class BackBusiConfService {

    @Autowired
    private BackBusiConfDao backBusiConfDao;

    @Autowired
    private ChannelValidate channelValidate;

    @Autowired
    private IpValidate ipValidate;

    @Autowired
    private TimetampValidate timetampValidate;

    @Autowired
    private CommonService commonService;

    @Autowired
    private ChannelDao channelDao;

    public void checkParams(Map<String, Object> params) throws Exception {
        if (params == null || params.size() == 0) {
            throw new BussinessException("10008", "参数不能为空");
        }
        Map spInfo = (Map) params.get("SP_INFO");
        if (spInfo == null || spInfo.size() == 0) {
            throw new BussinessException("10001", "SP_INFO参数不能为空");
        }
        //校验sp_info数据
        checkSpInfo(spInfo);
        //产品类型，1会员，2免流，3会员+免流
        String producType = (String) spInfo.get("PRODUCTYPE");
        //4 调能力平台
        String paytype = (String) spInfo.get("PAYTYPE");

        Map backbusi = (Map) spInfo.get("BACKBUSI");
        if (backbusi == null || backbusi.size() == 0) {
            throw new BussinessException("10002", "SP_INFO中{BACKBUSI}参数不能为空");
        }
        //校验后向表数据
        checkBackBusi(backbusi, producType, paytype);

        List<Map> syncSp = (List<Map>) spInfo.get("SYNC_SP");
        if ("2".equals(producType) || "3".equals(producType)) {
            if (syncSp == null || syncSp.size() == 0) {
                throw new BussinessException("10003", "SP_INFO中{SYNC_SP}参数不能为空");
            } else if (syncSp.size() > 1) {
                throw new BussinessException("10003", "SP_INFO中{SYNC_SP}参数不合法,单产品只能传一位");
            }
            checkSyncSp(syncSp.get(0));
        } else {
            if (syncSp != null && syncSp.size() > 0) {
                if (syncSp.get(0) != null && syncSp.get(0).size() > 0) {
                    throw new BussinessException("10003", "SP_INFO中{producType}参数为1,SYNC_SP不需要配置");
                }
            }
        }


        Map syncConf = (Map) spInfo.get("SYNC_CONF");
        if ("2".equals(producType) || "3".equals(producType)) {
            if (syncConf != null && syncConf.size() > 0) {
                checkSyncConf(syncConf);
            }
        } else {
            if (syncConf != null && syncConf.size() > 0) {
                throw new BussinessException("10003", "SP_INFO中{producType}参数为1,SYNC_CONF不需要配置");
            }
        }
        Map spAop = (Map) spInfo.get("SP_AOP");
        if ("4".equals(paytype)) {
            if (spAop == null || spAop.size() == 0) {
                throw new BussinessException("10004", "SP_INFO中{SP_AOP}参数不能为空");
            } else {
                //校验能力平台
                checkSpAop(spAop);
            }
        } else {
            if (spAop != null && spAop.size() > 0) {
                throw new BussinessException("10004", "调用能力平台,SP_INFO中{PAYTYPE}应为4,SP_AOP无效");
            }
        }

    }

    public void checkSpAop(Map spAop) throws BussinessException {
        String PRODUCTMODE = (String) spAop.get("PRODUCT_MODE");
        if (StringUtils.isEmpty(PRODUCTMODE)) {
            throw new BussinessException("10004", "SP_AOP中{PRODUCTMODE}参数不能为空");
        }
        String PACKAGE_ID = (String) spAop.get("PACKAGE_ID");
        if (StringUtils.isEmpty(PACKAGE_ID)) {
            throw new BussinessException("10004", "SP_AOP中{PACKAGE_ID}参数不能为空");
        }
        String ELEMENT_ID = (String) spAop.get("ELEMENT_ID");
        if (StringUtils.isEmpty(ELEMENT_ID)) {
            throw new BussinessException("10004", "SP_AOP中{ELEMENT_ID}参数不能为空");
        }
        String ELEMENT_TYPE_CODE = (String) spAop.get("ELEMENT_TYPE_CODE");
        if (StringUtils.isEmpty(ELEMENT_TYPE_CODE)) {
            throw new BussinessException("10004", "SP_AOP中{ELEMENT_TYPE_CODE}参数不能为空");
        } else if (!("D".equals(ELEMENT_TYPE_CODE) || "S".equals(ELEMENT_TYPE_CODE) || "A".equals(ELEMENT_TYPE_CODE) || "X S".equals(ELEMENT_TYPE_CODE) || "XS".equals(ELEMENT_TYPE_CODE))) {
            throw new BussinessException("10004", "SP_AOP中{ELEMENT_TYPE_CODE}参数不合法");
        }
    }

    public void checkSyncConf(Map syncConf) throws BussinessException {
        String STATUS = (String) syncConf.get("STATUS");
        if (StringUtils.isEmpty(STATUS)) {
            throw new BussinessException("10002", "SYNC_CONF中{STATUS}参数不能为空");
        } else {
            if (!("0".equals(STATUS) || "1".equals(STATUS))) {
                throw new BussinessException("10002", "SYNC_CONF中{STATUS}参数不合法");
            }
        }
        String SYNCSTATUS = (String) syncConf.get("SYNCSTATUS");
        if (StringUtils.isEmpty(SYNCSTATUS)) {
            throw new BussinessException("10002", "SYNC_CONF中{SYNCSTATUS}参数不能为空");
        } else {
            if (!("0".equals(SYNCSTATUS) || "1".equals(SYNCSTATUS))) {
                throw new BussinessException("10002", "SYNC_CONF中{SYNCSTATUS}参数不合法");
            }
        }
    }

    public void checkSyncSp(Map syncSp) throws BussinessException {
        String toSpid = (String) syncSp.get("TOSPID");
        if (StringUtils.isEmpty(toSpid)) {
            throw new BussinessException("10003", "SYNC_SP中{TOSPID}参数不能为空");
        } else {
            try {
                Integer.parseInt(toSpid);
            } catch (NumberFormatException e) {
                e.printStackTrace();
                throw new BussinessException("10003", "SYNC_SP中{TOSPID}参数不合法");
            }
        }
        String tocpid = (String) syncSp.get("TOCPID");
        if (StringUtils.isEmpty(tocpid)) {
            throw new BussinessException("10003", "SYNC_SP中{TOCPID}参数不能为空");
        }

        String STATUS = (String) syncSp.get("STATUS");
        if (StringUtils.isEmpty(STATUS)) {
            throw new BussinessException("10002", "SYNC_SP中{STATUS}参数不能为空");
        } else {
            if (!("0".equals(STATUS) || "1".equals(STATUS))) {
                throw new BussinessException("10002", "SYNC_SP中{STATUS}参数不合法");
            }
        }
    }

    public void checkBackBusi(Map backbusi, String producType, String paytype) throws BussinessException {
        String netdays = (String) backbusi.get("NETDAYS");
        if ("2".equals(producType) || "3".equals(producType)) {
            if (StringUtils.isEmpty(netdays)) {
                throw new BussinessException("10002", "BACKBUSI中{NETDAYS}参数不能为空");
            }
            try {
                int i = Integer.parseInt(netdays);
                if (i<1){
                    throw new BussinessException("10002", "BACKBUSI中{NETDAYS}参数不合法");
                }
            } catch (NumberFormatException e) {
                e.printStackTrace();
                throw new BussinessException("10002", "BACKBUSI中{NETDAYS}参数不合法");
            }
        } else {
            if (StringUtils.isNotEmpty(netdays)) {
                throw new BussinessException("10002", "纯会员BACKBUSI中{NETDAYS}参数必须为空");

            }
        }
        String STATUS = (String) backbusi.get("STATUS");
        if (StringUtils.isEmpty(STATUS)) {
            throw new BussinessException("10002", "BACKBUSI中{STATUS}参数不能为空");
        } else {
            if (!("0".equals(STATUS) || "1".equals(STATUS))) {
                throw new BussinessException("10002", "BACKBUSI中{STATUS}参数不合法");
            }
        }
        String VIPID = (String) backbusi.get("VIPID");
        if ("1".equals(producType) || "3".equals(producType)) {
            if (StringUtils.isEmpty(VIPID)) {
                throw new BussinessException("10002", "BACKBUSI中{VIPID}参数不能为空");
            }
        }else {
            if (StringUtils.isNotEmpty(VIPID)) {
                throw new BussinessException("10002", "非会员产品BACKBUSI中{VIPID}参数只能为空");
            }
        }
        String VIPPWD = (String) backbusi.get("VIPPWD");
        if ("1".equals(producType) || "3".equals(producType)) {
            if (StringUtils.isEmpty(VIPPWD)) {
                throw new BussinessException("10002", "BACKBUSI中{VIPPWD}参数不能为空");
            }
        }else {
            if (StringUtils.isNotEmpty(VIPPWD)) {
                throw new BussinessException("10002", "非会员产品BACKBUSI中{VIPPWD}参数只能为空");
            }
        }
        String HASSHARE = (String) backbusi.get("HASSHARE");
        if ("4".equals(paytype)) {

            if (StringUtils.isEmpty(HASSHARE)) {
                throw new BussinessException("10002", "BACKBUSI中{HASSHARE}参数不能为空");
            } else if (!("0".equals(HASSHARE) || "1".equals(HASSHARE))) {
                throw new BussinessException("10002", "BACKBUSI中{HASSHARE}参数不合法");
            }
        }else {
            if (StringUtils.isNotEmpty(HASSHARE)){
                throw new BussinessException("10002", "只有PAYTYPE为4时BACKBUSI中{HASSHARE}参数才可配置");
            }

        }
        String ENDTYPE = (String) backbusi.get("ENDTYPE");
        if ("2".equals(producType) || "3".equals(producType)) {

            if (StringUtils.isEmpty(ENDTYPE)) {
                //throw new BussinessException("10002", "BACKBUSI中{ENDTYPE}参数不能为空");
            } else {
                try {
                    int i = Integer.parseInt(ENDTYPE);
                    if (i < 1 || i > 4) {
                        throw new BussinessException("10002", "BACKBUSI中{ENDTYPE}参数不合法");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new BussinessException("10002", "BACKBUSI中{ENDTYPE}参数不合法");
                }
            }
        } else {
            if (StringUtils.isNotEmpty(ENDTYPE)) {
                throw new BussinessException("10002", "纯会员BACKBUSI中{ENDTYPE}参数必须为空");
            }
        }
    }


    public void checkSpInfo(Map spInfo) throws Exception {
        String cpid = (String) spInfo.get("CPID");
        if (StringUtils.isEmpty(cpid)) {
            throw new BussinessException("10001", "SP_INFO中{CPID}参数不能为空");
        }
        String spname = (String) spInfo.get("SPNAME");
        if (StringUtils.isEmpty(spname)) {
            throw new BussinessException("10001", "SP_INFO中{SPNAME}参数不能为空");
        }
        String price = (String) spInfo.get("PRICE");
        if (StringUtils.isEmpty(price)) {
            throw new BussinessException("10001", "SP_INFO中{PRICE}参数不能为空");
        } else {
            try {
                double v = Double.parseDouble(price);
                if(v<0){
                    throw new BussinessException("10001", "SP_INFO中{PRICE}参数不合法");
                }
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{PRICE}参数不合法");
            }
        }
        String producType = (String) spInfo.get("PRODUCTYPE");
        if (StringUtils.isEmpty(producType)) {
            throw new BussinessException("10001", "SP_INFO中{PRODUCTYPE}参数不能为空");
        } else {
            int i;
            try {
                i = Integer.parseInt(producType);
            } catch (NumberFormatException e) {
                e.printStackTrace();
                throw new BussinessException("10001", "SP_INFO中{PRODUCTYPE}参数不合法");
            }
            if (i < 1 || i > 3) {
                throw new BussinessException("10001", "SP_INFO中{PRODUCTYPE}参数不合法");
            }
        }
        String flowtype = (String) spInfo.get("FLOWTYPE");
        if (!"1".equals(producType)) {
            if (StringUtils.isEmpty(flowtype)) {
                throw new BussinessException("10001", "SP_INFO中{FLOWTYPE}参数不能为空");
            } else if (!("0".equals(flowtype) || "1".equals(flowtype))) {
                throw new BussinessException("10001", "SP_INFO中{FLOWTYPE}参数不合法");
            }
        }

        String maxflow = (String) spInfo.get("MAXFLOW");
        if ("1".equals(flowtype) && !"1".equals(producType)) {
            if (StringUtils.isEmpty(maxflow)) {
                throw new BussinessException("10001", "SP_INFO中{MAXFLOW}参数不能为空");
            } else {
                try {
                    double v = Double.parseDouble(maxflow);
                    if (v<0){
                        throw new BussinessException("10001", "SP_INFO中{MAXFLOW}参数不合法");
                    }
                } catch (NumberFormatException e) {
                    throw new BussinessException("10001", "SP_INFO中{MAXFLOW}参数不合法");
                }
            }
        }
        String paytype = (String) spInfo.get("PAYTYPE");
        if (StringUtils.isNotEmpty(paytype) && !"4".equals(paytype)) {
            throw new BussinessException("10001", "SP_INFO中{PAYTYPE}参数不合法");
        }

        String cptype = (String) spInfo.get("CPTYPE");
        if (StringUtils.isEmpty(cptype)){
            throw new BussinessException("10001", "SP_INFO中{CPTYPE}参数不能为空");
        }else {
            int i;
            try {
                 i = Integer.parseInt(cptype);
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{CPTYPE}参数不合法");
            }
            if (i<0||i>9){
                throw new BussinessException("10001", "SP_INFO中{CPTYPE}参数不合法");
            }
        }

        String isorder = (String) spInfo.get("ISORDER");
        if (StringUtils.isEmpty(isorder)){
            throw new BussinessException("10001", "SP_INFO中{ISORDER}参数不能为空");
        }else {
            int i;
            try {
                i = Integer.parseInt(isorder);
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{ISORDER}参数不合法");
            }
            if (i<0||i>1){
                throw new BussinessException("10001", "SP_INFO中{ISORDER}参数不合法");
            }
        }

        String isDianbo = (String) spInfo.get("IS_DIANBO");
        if (StringUtils.isEmpty(isDianbo)){
            throw new BussinessException("10001", "SP_INFO中{IS_DIANBO}参数不能为空");
        }else {
            int i;
            try {
                i = Integer.parseInt(isDianbo);
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{IS_DIANBO}参数不合法");
            }
            if (i<1||i>2){
                throw new BussinessException("10001", "SP_INFO中{IS_DIANBO}参数不合法");
            }
        }

        String isPrm = (String) spInfo.get("IS_PRM");
        if (StringUtils.isEmpty(isPrm)){
            throw new BussinessException("10001", "SP_INFO中{IS_PRM}参数不能为空");
        }else {
            int i;
            try {
                i = Integer.parseInt(isPrm);
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{IS_PRM}参数不合法");
            }
            if (i<0||i>2){
                throw new BussinessException("10001", "SP_INFO中{IS_PRM}参数不合法");
            }
        }

        String isMeal = (String) spInfo.get("IN_MEAL");
        if (StringUtils.isEmpty(isMeal)){
            throw new BussinessException("10001", "SP_INFO中{IN_MEAL}参数不能为空");
        }else {
            int i;
            try {
                i = Integer.parseInt(isMeal);
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{IN_MEAL}参数不合法");
            }
            if (i<1||i>2){
                throw new BussinessException("10001", "SP_INFO中{IN_MEAL}参数不合法");
            }
        }

        String incomeStyle = (String) spInfo.get("INCOME_STYLE");
        if (StringUtils.isEmpty(incomeStyle)){
            throw new BussinessException("10001", "SP_INFO中{INCOME_STYLE}参数不能为空");
        }else {
            int i;
            try {
                i = Integer.parseInt(incomeStyle);
            } catch (NumberFormatException e) {
                throw new BussinessException("10001", "SP_INFO中{INCOME_STYLE}参数不合法");
            }
            if (i<1||i>2){
                throw new BussinessException("10001", "SP_INFO中{INCOME_STYLE}参数不合法");
            }
        }
    }

    @Transactional
    public Map<String, String> addBakcBusiConf(Map<String, Object> params) throws Exception {
        Map spInfo = (Map) params.get("SP_INFO");
        String spid = genderSpid();
        String cpid = (String) spInfo.get("CPID");
        String spname = (String) spInfo.get("SPNAME");
        String productype = (String) spInfo.get("PRODUCTYPE");
        String price = (String) spInfo.get("PRICE");
        String paytype = (String) spInfo.get("PAYTYPE");
        if (StringUtils.isEmpty(paytype)) {
            paytype = "";
        }
        spInfo.put("SPID", spid);
        //插入sp_info表
        backBusiConfDao.insertSpInfo(spInfo);
        Map backbusi = (Map) spInfo.get("BACKBUSI");
        backbusi.put("CPID", cpid);
        backbusi.put("SPID", spid);
        backbusi.put("BUSITYPE", productype);
        backbusi.put("BUSINAME", spname);
        backbusi.put("PRICE", price);
        //插入backbusi表
        backBusiConfDao.insertBackBusi(backbusi);
        List<Map> list = (List<Map>) spInfo.get("SYNC_SP");
        if (list != null && list.size() > 0) {
            Map syncSp = list.get(0);
            if (syncSp != null && syncSp.size() > 0) {
                syncSp.put("CPID", cpid);
                syncSp.put("SPID", spid);
                syncSp.put("SPNAME", spname);
                backBusiConfDao.insertSyncSp(syncSp);
            }
        }
        Map syncConf = (Map) spInfo.get("SYNC_CONF");
        if (syncConf != null && syncConf.size() > 0) {
            syncConf.put("CPID", cpid);
            syncConf.put("SPID", spid);
            backBusiConfDao.insertSyncConf(syncConf);
        }

        Map spAop = (Map) spInfo.get("SP_AOP");
        if ("4".equals(paytype)) {
            spAop.put("SPID", spid);
            spAop.put("SPNAME", spname);
            try {
                backBusiConfDao.insertAop(spAop);
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage().contains("ORA-00001")){
                    throw  new BussinessException("8001","SP_AOP唯一约束,{PRODUCT_ID, PACKAGE_ID, ELEMENT_ID}不能重复");
                }
                throw e;
            }
        }

        backBusiConfDao.insertConf(cpid, spid);
        backBusiConfDao.insertHsParams(cpid, spid, JSONObject.toJSONString(params), productype, spname);
        HashMap<String, String> resp = new HashMap<>();
        resp.put("cpid", cpid);
        resp.put("spid", spid);

        return resp;
    }

    public String genderSpid() {
        String spid = "4";
        while (true) {
            String ran = String.valueOf((int) (Math.random() * 100000));
            ran = spid + ran;
            int cnt = backBusiConfDao.findBySpid(ran);
            if (cnt == 0 && ran.length() == 6) {
                spid = ran;
            }
            if (!"4".equals(spid)) {
                break;
            }
        }
        return spid;
    }

    public void check(Map<String, Object> params) throws Exception {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setTimestamp(String.valueOf(params.get("TIMESTAMP")));
        orderInfo.setChannel(String.valueOf(params.get("CHANNEL")));
        orderInfo.setSignature(String.valueOf(params.get("SIGN")));
        //timetamp验证
        timetampValidate.validate(orderInfo.getTimestamp());
        //渠道验证
        channelValidate.validate(orderInfo.getChannel());
        //ip验证
        ipValidate.volidate(orderInfo, "0");
        //签名验证
        validate(orderInfo);
        //重复请求
        vistVali(orderInfo);
    }

    public void validate(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", "签名校验失败");
        }
    }

    /**
     * 拼接签名信息 cpid+spid+userid+type+channel+timestamp
     *
     * @param orderInfo
     * @return
     */
    private String getSign(OrderInfo orderInfo) {
        if (orderInfo == null) {
            return "";
        }
        StringBuilder strb = new StringBuilder();
        if (orderInfo.getOrderid() != null && !"".equals(orderInfo.getOrderid())) {
            strb.append(orderInfo.getOrderid());
        }
        strb.append(orderInfo.getChannel());
        strb.append(orderInfo.getTimestamp());
        return strb.toString();
    }

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