package com.infoepoch.pms.dispatchassistant.common.configuration;


import com.infoepoch.pms.dispatchassistant.common.component.RedisTool;
import com.infoepoch.pms.dispatchassistant.common.constant.RedisKeys;
import com.infoepoch.pms.dispatchassistant.common.exception.NotLoginException;
import com.infoepoch.pms.dispatchassistant.common.utils.JsonUtils;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * MVC拦截全局配置
 */
@Configuration
public class MvcInterceptConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // URL格式校验拦截器
        InterceptorRegistration urlFormatInterceptor = registry.addInterceptor(getUrlFormatInterceptor());
        // 拦截所有请求
        urlFormatInterceptor.addPathPatterns("/**");

        //拦截器
        InterceptorRegistration adminInterceptor = registry.addInterceptor(getAdminInterceptor());
        //拦截api开头地址
        adminInterceptor.addPathPatterns("/**");
        // 账号登录相关请求不拦截
        adminInterceptor.excludePathPatterns("/auth/**");
        // 获取平台名称请求不拦截
        adminInterceptor.excludePathPatterns("/api/key-value-store/platform-name");
        // 访问页面相关地址不拦截
        adminInterceptor.excludePathPatterns("/pages/auth/**");
        adminInterceptor.excludePathPatterns("/healthy.html");
        adminInterceptor.excludePathPatterns("/asset/**");
        adminInterceptor.excludePathPatterns("/images/**");
        adminInterceptor.excludePathPatterns("/libs/**");
        adminInterceptor.excludePathPatterns("/scripts/**");
        adminInterceptor.excludePathPatterns("/styles/**");
    }

    @Bean
    public UrlFormatInterceptor getUrlFormatInterceptor() {
        return new UrlFormatInterceptor();
    }

    @Bean
    public AdminInterceptor getAdminInterceptor() {
        return new AdminInterceptor();
    }

    /**
     * 访问地址格式校验拦截器
     */
    private static class UrlFormatInterceptor extends HandlerInterceptorAdapter {

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String uri = request.getRequestURI();
            // 不合法的访问地址，统一跳转到首页
            if (uri.contains("..") || uri.contains(":") || uri.contains(";")) {
                throw new NotLoginException("请求地址非法");
            }
            return true;
        }
    }

    /**
     * 拦截后台访问，判断是否登录，如未登录跳转到登录页面
     */
    private static class AdminInterceptor extends HandlerInterceptorAdapter {

        @Autowired
        private RedisTool redisTool;

        @Value("${spring.application.name}")
        private String applicationName;

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws IOException, NotLoginException {
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    String cookieName = cookie.getName();
                    if (cookieName.equals(RedisKeys.SIGN)) {
                        String userStr = redisTool.get(RedisKeys.AUTHED_USER + cookie.getValue());
                        if(userStr == null) {
                            throw new NotLoginException("登录已失效，请重新登录");
                        }
                        User user = JsonUtils.jsonToObject(userStr, User.class);
                        if (user != null) {
                            // 刷新redis缓存时间
                            redisTool.expire(RedisKeys.AUTHED_USER + cookie.getValue(), 2, TimeUnit.HOURS);
                            return true;
                        }
                    }
                }
            }
            throw new NotLoginException("登录已失效，请重新登录");
        }
    }
}
