package com.house365.common;

import com.house365.common.util.RestTemplateBean;
import com.house365.config.HgsProp;
import com.house365.web.wechat.ProjectController;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.house365.common.constant.UrlConst.getCodeURL;

/**
 * Description 微信token拦截器
 * <p>
 * Created by 365 on 2017/3/21 0021.
 */
public class WeChatInterceptor implements HandlerInterceptor {

    private static final String PREFIX = "HGS_";
    private final HgsProp hgsProp;
    private final RedisTemplate redisTemplate;
    private Logger logger = LoggerFactory.getLogger(WeChatInterceptor.class);
    //初始化微信所有菜单下的链接，供权限判断使用
    private Map<String, Set<String>> permissions = init();

    //注入hgsProp配置文件Bean
    public WeChatInterceptor(HgsProp hgsProp, RedisTemplate redisTemplate) {
        this.hgsProp = hgsProp;
        this.redisTemplate = redisTemplate;
    }

    public boolean hasKey(final String key) {
        return (Boolean) redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] serialKey = redisTemplate.getStringSerializer().serialize(key);
                return connection.exists(serialKey);
            }
        });
    }

    public String getKey(final String key) {
        logger.info("************do redis key*************:"+key);
        return (String) redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] serialKey = redisTemplate.getStringSerializer().serialize(key);
                if (connection.exists(serialKey)) {
                    byte[] val = connection.get(serialKey);
                    return redisTemplate.getStringSerializer().deserialize(val);
                }
                return null;
            }
        });
    }

    public void deleteKey(final String key) {
        redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] serialKey = redisTemplate.getStringSerializer().serialize(key);
                connection.del(serialKey);
                return null;
            }
        });
    }

    @Override
    public boolean preHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler
    ) throws Exception {
        try {
            if (request.getServletPath().contains("error")) {
                return true;
            }

            //清除用户登录Cookie
//            Cookie cleanCookie = new Cookie("phone", null);
//            cleanCookie.setDomain(hgsProp.getDomain());
//            cleanCookie.setPath("/");
//            cleanCookie.setMaxAge(0);
//            response.addCookie(cleanCookie);
//
//            if (!hasKey("HGS_weChat:userInfo:isValid:15358183725")) {
//                redisTemplate.execute(new RedisCallback<Object>() {
//                    @Override
//                    public Object doInRedis(RedisConnection connection) throws DataAccessException {
//                        byte[] serialKey = redisTemplate.getStringSerializer().serialize("HGS_weChat:userInfo:isValid:15358183725");
//                        connection.del(serialKey);
//                        connection.set(serialKey, redisTemplate.getStringSerializer().serialize("1"));
//                        return null;
//                    }
//                });
//            }

//            Cookie phoneCookie = new Cookie("phone", "15358183725");
//            phoneCookie.setDomain(hgsProp.getDomain());
//            phoneCookie.setPath("/");
//            phoneCookie.setMaxAge(86400);
//            response.addCookie(phoneCookie);

            logger.info(">>>WeChatInterceptor>>>>>>>在请求处理之前进行调用（Controller方法调用之前）");
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                logger.info("==========cookies222 ::"+cookies+"********cookies.length*********"+cookies.length);
                String phone = "";
                String cookieKey = "";
                boolean needReGetUser = true;
                //Cookie里的手机号是否能找到会员
                for (int i = 0; i < cookies.length; i++) {
                    Cookie cookie = cookies[i];
                    logger.error("==========cookie  333*****"+cookie.getName() +" ########cookie.getValue()#########  "+cookie.getValue());
                    if (cookie.getName().equals("phone") && StringUtils.isNoneBlank(cookie.getValue())) {
                        logger.info("===========has phone Cookie:" + cookie.getValue());
                        phone = cookie.getValue();
                    }
                }

                JSONArray userRoles = new JSONArray();
                //如果cookie中有手机号
                if (StringUtils.isNotBlank(phone)) {
                    cookieKey = PREFIX + "weChat:userInfo:isValid:" + phone;
                    logger.info("====>>cookieKey>>:======" + cookieKey);
                }
                //根据手机号在redis中校验用户手机号是否已经被修改 1:有效；
                logger.info("====>>needReGetUser>>======hasKey:" + hasKey(cookieKey) + "===key:" + getKey(cookieKey));
                if (StringUtils.isNotBlank(cookieKey) && hasKey(cookieKey) && getKey(cookieKey).equals("1")) {
                    needReGetUser = false;
                }
                logger.info("====>>needReGetUser======" + needReGetUser);
                if (needReGetUser) {
                    logger.info("==========step 2");
                    String getCodeURL = getCodeURL(request.getRequestURI());
                    logger.info("===============getCodeURL:" + getCodeURL);
                    response.sendRedirect(getCodeURL);
                    return false;// 只有返回true才会继续向下执行，返回false取消当前请求
                }

                String userRolesKey = "HGS_weChat:userRoles:" + phone;
                if (hasKey(userRolesKey)) {
                    logger.info("====>>hasKey userRolesKey======");
                    userRoles = JSONArray.fromObject(URLDecoder.decode(getKey(userRolesKey)));
                }
                logger.info("====>>userRoles======" + userRoles);

                if (userRoles.size() == 0) {
                    //获取用户权限列表
                    List<NameValuePair> params = new ArrayList<>();
                    params.add(new BasicNameValuePair("serviceCode", "Wechat"));
                    params.add(new BasicNameValuePair("serviceName", "getUserRoles"));
                    params.add(new BasicNameValuePair("phone", phone));
                    String userRolesResult = RestTemplateBean.doGet(hgsProp.getHgsUrl(), params);
                    logger.info("===========userRolesResult1111:" + userRolesResult);

                    JSONObject data = JSONObject.fromObject(userRolesResult).getJSONObject("data");
                    if (data != null && data.containsKey("list")) {
                        JSONArray userRolesArray = data.getJSONArray("list");
                        for (int eachUserRole = 0, userRoleLength = userRolesArray.size(); eachUserRole < userRoleLength; eachUserRole++) {
                            JSONObject userRole = userRolesArray.getJSONObject(eachUserRole);
                            if (userRole != null) {
                                userRoles.add(userRole.getString("resource"));
                            }
                        }
                        logger.info("====encoder roles====>>" + userRoles.toString());

                        redisTemplate.opsForValue().set(userRolesKey, URLEncoder.encode(userRoles.toString(), "UTF-8"), 86400, TimeUnit.SECONDS);
                    } else {
                        response.sendRedirect("/error/403");
                        return false;
                    }
                }

                userRoles.add("http://" + hgsProp.getDomain() + "/function/function");
                logger.info("===========userRoles:" + userRoles);

                //获取用户操作权限列表
                List<NameValuePair> params = new ArrayList<>();
                params.add(new BasicNameValuePair("serviceCode", "Wechat"));
                params.add(new BasicNameValuePair("serviceName", "getUserFunctionRoles"));
                params.add(new BasicNameValuePair("phone", phone));
                String functionRolesResult = RestTemplateBean.doGet(hgsProp.getHgsUrl(), params);
                logger.info("===========userRolesResult:" + functionRolesResult);
                JSONObject data = JSONObject.fromObject(functionRolesResult).getJSONObject("data");
                permissions.put("/function/function", new HashSet<>());
                if (data != null && data.containsKey("list")) {
                    Set<String> functions = permissions.get("/function/function");
                    JSONArray functionRolesArray = data.getJSONArray("list");
                    for (int eachFunctionRole = 0, functionRoleLength = functionRolesArray.size(); eachFunctionRole < functionRoleLength; eachFunctionRole++) {
                        JSONObject functionRole = functionRolesArray.getJSONObject(eachFunctionRole);
                        if (functionRole != null) {
                            functions.add(functionRole.getString("resource"));
                        }
                    }
                }

                //判断当前请求URL是否在 链接列表中
                String servletPath = request.getServletPath();
                logger.info("===========servletPath:" + servletPath);
                String orderPath = "";
                boolean findPath = false;
                for (Map.Entry order : permissions.entrySet()) {
                    Set<String> childrenOrders = (Set<String>) order.getValue();
                    logger.info("===========childrenOrders:" + childrenOrders);
                    for (String entry : childrenOrders) {
                        if (servletPath.contains(entry)) {
                            orderPath = (String) order.getKey();
                            logger.info("===========orderPath2222:" + orderPath);
                            findPath = true;
                            break;
                        }
                    }
                    if (findPath) {
                        break;
                    }
                }
                logger.info("===========findPath:" + findPath);
                //判断当前链接所在的菜单，是否有权限
                boolean hasAuth = false;
                if (findPath) {
                    for (Object userRoleObject : userRoles) {
                        String userRole = (String) userRoleObject;
                        if (userRole.contains(orderPath)) {
                            hasAuth = true;
                        }
                    }
                }
                logger.info("===========hasAuth:" + hasAuth);
                if (!hasAuth) {
                    response.sendRedirect("/error/403");
                    return false;
                } else {
                    return true;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            response.sendRedirect("/error/403");
            return false;
        }
        logger.info("==========step 2");
        String getCodeURL = getCodeURL(request.getRequestURI());
        logger.info("===============getCodeURL:" + getCodeURL);
        response.sendRedirect(getCodeURL);
        return false;// 只有返回true才会继续向下执行，返回false取消当前请求
    }

    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView
    ) throws Exception {
        logger.info(">>>WeChatInterceptor>>>>>>>请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）");
    }

    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex
    ) throws Exception {
        logger.info(">>>WeChatInterceptor>>>>>>>在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）");
    }


    private Map<String, Set<String>> init() {
        Map<String, Set<String>> permissions = new HashMap<>();

        Set<String> sea = new HashSet<>();
        sea.add("/customer/sea");
        sea.add("/customer/bindManager");
        sea.add("/customer/customerCell");
        sea.add("/customer/seal");
        sea.add("/customer/search");
        sea.add("/customer/querySea");
        sea.add("/customer/deleteFormOcean");
        sea.add("/customer/checkCustomerPhoneByCustomerIds");
        permissions.put("/customer/sea", sea);


        Set<String> callclient = new HashSet<>();
        callclient.add("/customer/callclient");
        callclient.add("/customer/hotlinequery");
        callclient.add("/customer/hotline");
        callclient.add("/customer/addvisit");
        callclient.add("/customer/deletehotlinecustomer");
        permissions.put("/customer/callclient", callclient);

        Set<String> my = new HashSet<>();
        my.add("/user/evaluateUser");
        permissions.put("/user/evaluateUser", my);

        Set<String> evaluationSet = new HashSet<>();
        evaluationSet.add("/customer/evaluation");
        evaluationSet.add("/customer/review");
        evaluationSet.add("/customer/delEvaluation");
        permissions.put("customer/evaluation", evaluationSet);



        Set<String> mysave = new HashSet<>();
        mysave.add("/user/getShareUrl");
        permissions.put("/user/getShareUrl", mysave);

        Set<String> addcustomer = new HashSet<>();
        addcustomer.add("/customer/addcustomer");
        addcustomer.add("/customer/myCustomersUser");
        addcustomer.add("/customer/myCustomerList");
        addcustomer.add("/customer/saveBindProject");
        addcustomer.add("/customer/editCustomerLabel");
        addcustomer.add("/customer/checkcustomer");
        addcustomer.add("/customer/addSalesReport");
        permissions.put("/customer/addcustomer", addcustomer);

        Set<String> rushcustomer = new HashSet<>();
        rushcustomer.add("/customer/rushcustomerlist");
        rushcustomer.add("/customer/getrushcustomerlist");
        rushcustomer.add("/customer/rushcustomer");
        permissions.put("/customer/rushcustomerlist", rushcustomer);

        Set<String> myCustomers = new HashSet<>();
        myCustomers.add("/customer/myCustomers");
        myCustomers.add("/customer/myCustomerSearch");
        myCustomers.add("/customer/myCustomersUser");
        myCustomers.add("/customer/myCustomerList");
        myCustomers.add("/customer/editCustomerLabel");
        myCustomers.add("/customer/saveCustomerLabel");
        myCustomers.add("/customer/saveBindProject");
        addcustomer.add("/customer/customerdetail");
        addcustomer.add("/customer/toUpdateCustomer");
        myCustomers.add("/customer/myWaitCallCustomer");
        myCustomers.add("/customer/myWaitCallCustomerCell");
        myCustomers.add("/customer/waitCustomerDetail");
        myCustomers.add("/customer/abandonCustomer");
        myCustomers.add("/project/waitaddvisit");

        addcustomer.add("/customer/modifytextarea");
        addcustomer.add("/customer/getBindProject");
        addcustomer.add("/customer/starToggle");
        addcustomer.add("/customer/abandonHotlineCustomer");
        addcustomer.add("/project/getmyprojects");
        addcustomer.add("/project/getprojectdetail");

        addcustomer.add("/project/getprojectdynamiclist");//项目动态
        addcustomer.add("/project/getprojectdynamiccell");
        addcustomer.add("/project/adddynamic");//添加项目动态
        addcustomer.add("/project/savedynamic");//项目动态
        addcustomer.add("/project/deldynamic");//添加项目动态
        addcustomer.add("/project/adddynamicpic");//项目动态
        addcustomer.add("/project/savePicInfo2Attachment");//添加项目动态

        addcustomer.add("/project/distribution");
        addcustomer.add("/project/customers");
        addcustomer.add("/project/getcustomers");
        addcustomer.add("/project/projectcustomers");
        addcustomer.add("/project/getprojectcustomers");
        addcustomer.add("/project/customerproject");
        addcustomer.add("/project/customerdetail");
        addcustomer.add("/project/visitrecord");
        addcustomer.add("/project/getvisitrecords");
        addcustomer.add("/customer/editCustomerLabel");
//        addcustomer.add("/project/addcustomerstatus");
//        addcustomer.add("/project/addvisit");
        addcustomer.add("/project/addSection");
        addcustomer.add("/project/addattachment");
        addcustomer.add("/project/modifytextarea");

        addcustomer.add("/project/reportcustomer");
        addcustomer.add("/project/modifyremark");
        addcustomer.add("/project/statuschangelogs");
        addcustomer.add("/project/getstatuschangelogs");
        addcustomer.add("/project/visitlogdetails");
        addcustomer.add("/project/changerecordedstatus");
        permissions.put("/customer/myCustomers", myCustomers);

        Set<String> myprojects = new HashSet<>();
        myprojects.add("/project/myprojects");
        myprojects.add("/project/getmyprojects");
        myprojects.add("/project/getprojectdetail");

        myprojects.add("/project/getprojectdynamiclist");
        myprojects.add("/project/getprojectdynamiccell");
        myprojects.add("/project/adddynamic");//添加项目动态
        myprojects.add("/project/savedynamic");//项目动态
        myprojects.add("/project/deldynamic");//添加项目动态
        myprojects.add("/project/adddynamicpic");//项目动态
        myprojects.add("/project/savePicInfo2Attachment");//添加项目动态

        myprojects.add("/project/distribution");
        myprojects.add("/project/customers");
        myprojects.add("/project/getcustomers");
        myprojects.add("/project/projectcustomers");
        myprojects.add("/project/getprojectcustomers");
        myprojects.add("/project/customerproject");
        myprojects.add("/project/customerdetail");
        myprojects.add("/project/visitrecord");
        myprojects.add("/project/getvisitrecords");
//        myprojects.add("/project/addcustomerstatus");
        myprojects.add("/project/getCRMURL");

        myprojects.add("/project/testupload");
//        myprojects.add("/project/addvisit");
        myprojects.add("/project/addSection");
        myprojects.add("/project/addattachment");
        myprojects.add("/project/modifytextarea");

        myprojects.add("/project/reportcustomer");
        myprojects.add("/project/modifyremark");
        myprojects.add("/project/statuschangelogs");
        myprojects.add("/project/getstatuschangelogs");
        myprojects.add("/project/visitlogdetails");
        myprojects.add("/project/changerecordedstatus");
        myprojects.add("/project/judgeCustomer");
        permissions.put("/project/myprojects", myprojects);

        Set<String> usercenter = new HashSet<>();
        usercenter.add("/customer/usercenter");
        usercenter.add("/customer/saveUserInfo");
        usercenter.add("/customer/editUserInfo");
        permissions.put("/customer/usercenter", usercenter);

        Set<String> notice = new HashSet<>();
        notice.add("/customer/notice");
        notice.add("/customer/noticeCell");
        notice.add("/customer/noticeDetail");
        permissions.put("/customer/notice", notice);

        Set<String> report = new HashSet<>();
        //客户报备
        report.add("/project/toCustomerReport");
        report.add("/project/customerReport");
        permissions.put("/project/toCustomerReport", report);

        Set<String> function = new HashSet<>();
        permissions.put("/function/function", function);
        return permissions;
    }
}
