package com.cnd3b.common.restful;

import com.cnd3b.utility.Encryption;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.cnd3b.common.D3BReturnObject_Err;
import com.cnd3b.common.data.Row;
import com.cnd3b.common.data.Rows;
import com.cnd3b.common.data.SQLFactory;
import com.cnd3b.common.data.db.DBConnect;
import com.cnd3b.common.data.db.DataPool;
import com.cnd3b.common.parameter.ErrModel;
import com.cnd3b.common.parameter.parameter;
import com.cnd3b.restcontroller.system.system.uploadExcelData;
import com.cnd3b.utility.Sms;
import com.cnd3b.utility.sysmsg;
import com.cnd3b.utility.wechatpay.apppay.POJO.APPQueryOrderRequest;
import com.cnd3b.utility.wechatpay.apppay.POJO.AppWechatOrder;
import com.cnd3b.utility.wechatpay.apppay.apppay;
import com.cnd3b.utility.wechatpay.jsapipay.POJO.JSQueryOrderRequest;
import com.cnd3b.utility.wechatpay.jsapipay.POJO.JSWechatOrder;
import com.cnd3b.utility.wechatpay.jsapipay.jsapipay;
import com.cnd3b.utility.wechatpay.nativepay.nativepay;
import org.dom4j.dom.DOMElement;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Random;

@Path("webclientrest")
public class WebClientRest {

    private static String[] nocheckphonenumber = {"17357363127", "13805731234"};

    @POST
    public String method(@Context HttpServletRequest request, String RequestContent) {
//        if (parameter.isdebug()) {
//            SQLiteJDBC db = new SQLiteJDBC();
//            db.InsertLogMsg("请求内容", RequestContent, "info");
//        }
        /**
         * 验证请求正文是否为规范的SONObject格式
         */
        JSONObject requestcontent = null;
        try {
            requestcontent = JSONObject.parseObject(RequestContent);
        } catch (Exception e) {
            return ErrModel.request_BasicJsonFormat().toString();
        }
        /**
         * 验证请求正文中是否包含必填的键值
         */
        String[] mustkeys = {"classname", "method", "content"};
        for (String mustkey : mustkeys) {
            if (!requestcontent.containsKey(mustkey)) {
                return ErrModel.request_ContainsMustKey(mustkey).toString();
            }
        }
        /**
         * 验证请求正文中的content是否为规范的SONObject格式
         */
        JSONObject content = new JSONObject();
        try {
            content = requestcontent.getJSONObject("content");
        } catch (Exception e) {
            return ErrModel.request_ContentJsonFormat().toString();
        }

        /**
         * 验证正文中的token是否有效
         */
        String accesstoken = "";
        String className = requestcontent.getString("classname");

        if (className.startsWith("agentclient") || className.startsWith("agentwebclient") ||
                className.startsWith("salerclient") || className.startsWith("salerwebclient")
                || className.startsWith("webclient") || className.startsWith("wechatclient")) {
            className = "enterprise." + className;
        }
        if (!className.contains("publicmethod")) {
            if (!requestcontent.containsKey("accesstoken")) {
                return ErrModel.token_Validate().toString();
            }
            accesstoken = requestcontent.getString("accesstoken");
            /**
             * 盘点当前账号是否存在有效的token
             */
            if (!parameter.tokenlist.containsKey(accesstoken) && !istokeninuserlist(accesstoken)) {
                //如果缓存中不存在，则在账号列表中进行查询，查到结果后，将tokne存入缓存
                return ErrModel.token_Validate().toString();
            }
            parameter.requesttime.put(accesstoken, Calendar.getInstance().getTime());
        }

        String methodName = requestcontent.getString("method");
        if (content.isEmpty()) {
            content = new JSONObject();
        }
        content.put("$classname", className);
        content.put("$method", methodName);
        content.put("$accesstoken", accesstoken);
        content.put("$requestHost", request.getScheme() + "://" + request.getHeader("Host"));

        String key = className + "." + methodName;
        String result;
        Object obj = null;
        try {
            boolean getdatafromdbanyway = content.containsKey("getdatafromdbanyway")
                    && content.getBoolean("getdatafromdbanyway");
            content.remove("getdatafromdbanyway");
            Object data = null;
            if (!getdatafromdbanyway) {
                data = DataPool.get(content.toString());
            }
            if (data != null) {
                result = data.toString();
                saveCallMethodMsg(key, false, 0L);
            } else {
                long starttimes = Calendar.getInstance().getTimeInMillis();
                /**
                 * 执行请求方法
                 */
                Class clz = Class.forName("com.cnd3b.restcontroller." + className);
                Constructor cla = clz.getDeclaredConstructor(JSONObject.class);
                obj = cla.newInstance(content);
                Method method = obj.getClass().getDeclaredMethod(methodName);
                result = (String) method.invoke(obj);
                long endtimes = Calendar.getInstance().getTimeInMillis();
                saveCallMethodMsg(key, true, endtimes - starttimes);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            result = ErrModel.request_GetClass("找不到指定的类" + className).toString();
        } catch (InstantiationException e) {
            e.printStackTrace();
            result = ErrModel.request_GetClass("类" + className + "实例化异常").toString();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            result = ErrModel.request_GetClass("类" + className + "安全权限异常，可能该类为非public类").toString();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            result = ErrModel.request_GetClass("找不到指定的类" + className + "的" + methodName + "方法").toString();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            result = ErrModel.request_GetClass("类" + className + "的" + methodName + "方法参数不合法").toString();
        } catch (InvocationTargetException e) {
            Throwable targetException = e.getTargetException();
            D3BReturnObject_Err d3BReturnObject_err = new D3BReturnObject_Err();
            d3BReturnObject_err.setErrMsg(targetException.getMessage());
            result = d3BReturnObject_err.toString();
        } catch (Exception e) {
            e.printStackTrace();
            result = ErrModel.request_GetClass("发生未知异常" + e.getMessage()).toString();
        } finally {
            if (obj != null) {
                try {
                    obj.getClass().getMethod("p2ServerSystemPaoSetClose").invoke(obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }


    public boolean istokeninuserlist(String accesstoken) {
        DBConnect dbConnect = new DBConnect();
        SQLFactory factory = new SQLFactory(this, "持久化账号列表查询");
        factory.addParameter("accesstoken", accesstoken);
        Rows rows = dbConnect.runSqlQuery(factory.getSQL());
        if (rows.isEmpty()) {
            return false;
        } else {
            for (Row row : rows) {
                long userid = row.getLong("userid");
                String token = row.getString("token");
                row.put("logintime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
                parameter.userIdList.put(userid, row);
                parameter.tokenlist.put(token, userid);
            }
            return true;
        }
    }

    /**
     * 记录请求数
     *
     * @param key
     * @param fromdb
     * @param time
     */
    private void saveCallMethodMsg(String key, boolean fromdb, long time) {
        long callmethodTimes = parameter.callmethodTimes.containsKey(key) ? parameter.callmethodTimes.get(key) : 0L;

        //更新请求总数
        parameter.callmethodTimes.put(key, callmethodTimes + 1L);

        //最新请求时间
        parameter.lastcallmethodtime.put(key, Calendar.getInstance().getTime());

        //从缓存获取的次数
        long callmethod_fromcacheTimes = parameter.callmethod_fromcacheTimes.containsKey(key) ? parameter.callmethod_fromcacheTimes.get(key) : 0L;
        if (!fromdb) {
            /**
             * 方法请求从缓存获取次数
             */
            parameter.callmethod_fromcacheTimes.put(key, callmethod_fromcacheTimes + 1L);
        } else {
            /**
             * 方法请求查询最新耗时
             */
            parameter.callmethodLastTimeLong.put(key, time);


            long totaltimes = callmethodTimes - callmethod_fromcacheTimes;

            /**
             * 方法请求查询平均时间
             */
            long callmethodTimeLong = parameter.callmethodTimeLong.containsKey(key) ? parameter.callmethodTimeLong.get(key) : 0L;

            parameter.callmethodTimeLong.put(key, (callmethodTimeLong * totaltimes + time) / (totaltimes + 1));
        }
    }

    /**
     * 获取短信登陆验证码
     *
     * @param RequestContent
     * @return
     */
    @Path("getpassword")
    @POST
    public String getPassWord(@Context HttpServletRequest request, String RequestContent) {
        /**
         * 验证请求正文是否为规范的SONObject格式
         */
        JSONObject requestcontent = null;
        try {
            requestcontent = JSONObject.parseObject(RequestContent);
        } catch (Exception e) {
            return ErrModel.request_BasicJsonFormat().toString();
        }
        /**
         * 验证请求正文中是否包含必填的键值
         */
        String[] mustkeys = {"phonenumber"};
        for (String mustkey : mustkeys) {
            if (!requestcontent.containsKey(mustkey)) {
                return ErrModel.request_ContainsMustKey(mustkey).toString();
            }
        }
        String phonenumber = requestcontent.getString("phonenumber");
        String client = "";
        if (requestcontent.containsKey("client")) {
            client = requestcontent.getString("client");
        }

        DBConnect dbConnect = new DBConnect();
        if (dbConnect.runSqlQuery("select *from tenterprise_users where fphonenumber='" + phonenumber + "'").isEmpty()) {
            JSONObject object = new JSONObject();
            object.put("code", 0);
            object.put("msg", "当前手机号未注册！");
            return object.toString();
        }
        if ("enterpriseweb".equalsIgnoreCase(client)) {
            SQLFactory sqlFactory = new SQLFactory(this, "企业账号权限组查询");
            sqlFactory.addParameter("fphonenumber", phonenumber);
            if (dbConnect.runSqlQuery(sqlFactory.getSQL()).isEmpty()) {
                JSONObject object = new JSONObject();
                object.put("code", 0);
                object.put("msg", "当前手机号没有有效的管理员账号！");
                return object.toString();
            }
        }
        String password = createPassWord();
        parameter.phonenumber_password.put(phonenumber, password);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, 5);
        parameter.phonenumber_date.put(phonenumber, calendar.getTime());

        if (parameter.isdebug()) {
            JSONObject object = new JSONObject();
            object.put("code", 1);
            object.put("msg", "手机验证码为：" + password);
            return object.toString();
        } else {
            JSONObject object = new JSONObject();
            Sms sms = new Sms();
            sms.sendOutMsg(phonenumber, password);
            object.put("code", 1);
            object.put("msg", "手机验证码已发送，请注意查收！");
            return object.toString();
        }
    }

    /**
     * 创建验证码
     *
     * @return
     */
    public String createPassWord() {
        String allChar = "1234567890";
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            sb.append(allChar.charAt(random.nextInt(allChar.length())));
        }
        if (parameter.phonenumber_password.containsValue(sb.toString())) {
            return createPassWord();
        } else {
            return sb.toString();
        }
    }

    @Path("login")
    @POST
    public String login(String RequestContent) {
        /**
         * 验证请求正文是否为规范的SONObject格式
         */
        JSONObject requestcontent = null;
        try {
            requestcontent = JSONObject.parseObject(RequestContent);
        } catch (Exception e) {
            return ErrModel.request_BasicJsonFormat().toString();
        }
        /**
         * 验证请求正文中是否包含必填的键值
         */
        String[] mustkeys = {"phonenumber", "password"};
        for (String mustkey : mustkeys) {
            if (!requestcontent.containsKey(mustkey)) {
                return ErrModel.request_ContainsMustKey(mustkey).toString();
            }
        }
        String phonenumber = requestcontent.getString("phonenumber");
        String password = requestcontent.getString("password");

        int resultcode;
        DBConnect connect = new DBConnect();
        if (!parameter.phonenumber_password.containsKey(phonenumber)) {
            resultcode = 1;//没有获取验证码
        } else if (parameter.phonenumber_date.get(phonenumber).before(Calendar.getInstance().getTime())) {
            resultcode = 2;//验证码已失效
        } else {
            //系统验证码
            String syspassword = parameter.phonenumber_password.get(phonenumber);
            if (password.equals(new Encryption().Encode_MD5(syspassword))) {
                resultcode = 0;//验证码正确
            } else {
                resultcode = 3;//验证码错误
            }
        }

        if (resultcode == 0 || Arrays.asList(nocheckphonenumber).contains(phonenumber)) {
            SQLFactory factory = new SQLFactory(this, "手机账号列表查询");
            factory.addParameter("fphonenumber", phonenumber);
            Rows rows = connect.runSqlQuery(factory.getSQL());

            ArrayList<String> tokensaveList = new ArrayList<>();
            for (Row row : rows) {
                long userid = row.getLong("userid");
                String usertoken = new Encryption().Encode_MD5(phonenumber + password + userid + Calendar.getInstance().getTimeInMillis());
                row.put("token", usertoken);
                row.put("logintime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
                parameter.userIdList.put(userid, row);
                parameter.tokenlist.put(usertoken, userid);

                tokensaveList.add("update tenterprise_users set accesstoken='" + usertoken + "' where tenterprise_userid=" + userid);
            }
            if (!tokensaveList.isEmpty()) {
                /**
                 * 账号登录态持久化
                 */
                connect.runSqlUpdate(tokensaveList);
            }

            JSONObject object = new JSONObject();
            object.put("code", 1);
            object.put("msg", "成功");
            object.put("webclienturl", "https://cnd3b.com/dsb1/#/");
            object.put("servicehotline", "13095738000");
            object.put("account_list", rows.toJsonArray());

            //登录成功，将验证码失效掉；
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, -5);
            parameter.phonenumber_date.put(phonenumber, calendar.getTime());
            return object.toString();
        } else {
            String msg = "";
            if (resultcode == 1) {
                msg = "请先获取所填手机号验证码！";
            } else if (resultcode == 2) {
                msg = "验证码已失效，请重新获取！";
            } else if (resultcode == 3) {
                msg = "无效的验证码！";
            }
            JSONObject object = new JSONObject();
            object.put("code", 0);
            object.put("msg", msg);
            return object.toString();
        }
    }

    @Path("loginbyaccount")
    @POST
    public String loginbyaccount(String RequestContent) {
        /**
         * 验证请求正文是否为规范的SONObject格式
         */
        JSONObject requestcontent = null;
        try {
            requestcontent = JSONObject.parseObject(RequestContent);
        } catch (Exception e) {
            return ErrModel.request_BasicJsonFormat().toString();
        }
        /**
         * 验证请求正文中是否包含必填的键值
         */
        String[] mustkeys = {"accountno", "password"};
        for (String mustkey : mustkeys) {
            if (!requestcontent.containsKey(mustkey)) {
                return ErrModel.request_ContainsMustKey(mustkey).toString();
            }
        }
        String accountno = requestcontent.getString("accountno");
        String password = requestcontent.getString("password");//md5加密


        boolean result = true;

        DBConnect connect = new DBConnect();

        Rows usersrows = connect.runSqlQuery("select t1.* from tenterprise_users t1 inner join tenterprise t2 on t1.siteid=t2.siteid  where t2.floginmode in(2,3) and convert(varchar(100),t1.faccountno)='" + accountno + "'");
        if (usersrows.isEmpty()) {
            result = false;
        } else {
            //系统验证码
            String syspassword = usersrows.get(0).getString("fpassword");
            result = password.equals(syspassword);
        }
        if (result) {
            SQLFactory factory = new SQLFactory(this, "账号列表查询");
            factory.addParameter("faccountno", accountno);
            Rows rows = connect.runSqlQuery(factory.getSQL());

            if (rows.isEmpty()) {
                JSONObject object = new JSONObject();
                object.put("code", 0);
                object.put("msg", "没有包含此账号的企业或经销商！");
                return object.toString();
            }
            ArrayList<String> tokensaveList = new ArrayList<>();
            for (Row row : rows) {
                long userid = row.getLong("userid");
                String usertoken = new Encryption().Encode_MD5(accountno + password + userid + Calendar.getInstance().getTimeInMillis());
                row.put("token", usertoken);
                row.put("logintime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
                parameter.userIdList.put(userid, row);
                parameter.tokenlist.put(usertoken, userid);
                tokensaveList.add("update tenterprise_users set accesstoken='" + usertoken + "' where tenterprise_userid=" + userid);
            }
            if (!tokensaveList.isEmpty()) {
                /**
                 * 账号登录态持久化
                 */
                connect.runSqlUpdate(tokensaveList);
            }
            JSONObject object = new JSONObject();
            object.put("code", 1);
            object.put("msg", "成功");
            object.put("webclienturl", "https://cnd3b.com/dsb1/#/");
            object.put("servicehotline", "13095738000");
            object.put("account_list", rows.toJsonArray());
            return object.toString();
        } else {
            JSONObject object = new JSONObject();
            object.put("code", 0);
            object.put("msg", "用户名或密码错误");
            return object.toString();
        }
    }

    @Path("logout")
    @POST
    public String logout(String RequestContent) {
        /**
         * 验证请求正文是否为规范的SONObject格式
         */
        JSONObject requestcontent = null;
        try {
            requestcontent = JSONObject.parseObject(RequestContent);
        } catch (Exception e) {
            return ErrModel.request_BasicJsonFormat().toString();
        }
        /**
         * 验证请求正文中是否包含必填的键值
         */
        String[] mustkeys = {"accesstoken"};
        for (String mustkey : mustkeys) {
            if (!requestcontent.containsKey(mustkey)) {
                return ErrModel.request_ContainsMustKey(mustkey).toString();
            }
        }
        /**
         * 验证正文中的token是否有效
         */
        String accesstoken = requestcontent.getString("accesstoken");
        parameter.tokenlist.remove(accesstoken);
        new DBConnect().runSqlUpdate("update tenterprise_users set accesstoken=null where accesstoken='" + accesstoken + "'");
        JSONObject object = new JSONObject();
        object.put("status", "ok");
        return object.toString();
    }


    /**
     * 数据导入
     *
     * @param uploadfileInputStream
     * @param uploadfile
     * @param userid
     * @param accesstoken
     * @param ftype
     * @return
     */
    @Path("uploadexcel")
    @POST
    @Consumes({"multipart/form-data"})
    @Produces({"application/json"})
    public String upLoadDoc(@FormDataParam("uploadfile") InputStream uploadfileInputStream,
                            @FormDataParam("uploadfile") FormDataContentDisposition uploadfile,
                            @FormDataParam("userid") String userid,
                            @FormDataParam("accesstoken") String accesstoken, @FormDataParam("ftype") String ftype) {
        /**
         * 验证正文中的token是否有效
         */
        if (!parameter.tokenlist.containsKey(accesstoken)) {
            return ErrModel.token_Validate().toString();
        }
        JSONObject content = new JSONObject();
        content.put("userid", userid);
        uploadExcelData uploadExcelData = new uploadExcelData(content);
        return uploadExcelData.upLoadExcel(uploadfileInputStream, uploadfile, ftype);
    }

    /**
     * 微信支付回调接口
     *
     * @param RequestContent
     * @return
     */
    @POST
    @Path("wechatpay/returnorderstateapp")
    public String wechatpayapp(String RequestContent) {

        APPQueryOrderRequest queryOrderRequest = new APPQueryOrderRequest();
        AppWechatOrder order = queryOrderRequest.getWechatOrder(RequestContent);
        apppay apppay = new apppay();
        boolean success = apppay.updateLocalOrder(order);
        DOMElement request = new DOMElement("xml");
        request.addElement("return_code").addText(success ? "SUCCESS" : "FAIL");
        request.addElement("return_msg").addText(success ? "OK" : "校验失败");
        return request.asXML();
    }

    /**
     * 微信网页支付回调接口
     *
     * @param RequestContent
     * @return
     */
    @POST
    @Path("wechatpay/returnorderstatenative")
    public String wechatpaynative(String RequestContent) {
        nativepay nativepay = new nativepay();
        JSONObject returnobject = JSONObject.parseObject(RequestContent);
        boolean success = nativepay.updateLocalOrder_callback(returnobject);
        JSONObject request = new JSONObject();
        request.put("code", success ? "SUCCESS" : "FAIL");
        request.put("message", success ? "成功" : "校验失败");
        return request.toString();
    }

    /**
     * 微信网页支付回调接口
     *
     * @param RequestContent
     * @return
     */
    @POST
    @Path("wechatpay/returnorderstatejs")
    public String wechatpayjs(String RequestContent) {

        JSQueryOrderRequest queryOrderRequest = new JSQueryOrderRequest();
        JSWechatOrder order = queryOrderRequest.getWechatOrder(RequestContent);
        jsapipay jsapipay = new jsapipay();
        boolean success = jsapipay.updateLocalOrder(order);
        DOMElement request = new DOMElement("xml");
        request.addElement("return_code").addText(success ? "SUCCESS" : "FAIL");
        request.addElement("return_msg").addText(success ? "OK" : "校验失败");
        return request.asXML();
    }

    @Path("sysmsg")
    @GET
    @Produces(MediaType.TEXT_HTML)
    @Consumes(MediaType.TEXT_HTML)
    public String sysmsg() throws JSONException {
        return new sysmsg().getCustMsg();
    }
}
