package com.sunxung.factoring.component.interceptor;


import com.sunxung.factoring.component.constance.AuthConstance;
import com.sunxung.factoring.component.exception.ServiceException;
import com.sunxung.factoring.component.properties.NotLoginUrl;
import com.sunxung.factoring.component.util.StringUtil;
import com.sunxung.factoring.component.util.ThreadLocalUtil;
import com.sunxung.factoring.entity.sys.User;
import com.sunxung.factoring.service.sys.AuthorityService;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.web.BasicErrorController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author 张超
 * @date 2021/10/19
 */
public class AuthenticationInterceptor extends
    HandlerInterceptorAdapter implements ApplicationContextAware,
    ApplicationListener<ContextRefreshedEvent> {

    private String bankendPackageName = "com.inkasso.factoring.login";

    private final String mark = "*";

    private List<String> whiteUrl;

    private AuthorityService authorityService;

    private ApplicationContext applicationContext;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest,
                             HttpServletResponse httpServletResponse, Object o) {

        if (!(o instanceof HandlerMethod)) {
            return true;
        }
        if (o instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) o;
            if (((HandlerMethod) o).getBean() instanceof BasicErrorController) {
                return true;
            }

        }
        String uri = httpServletRequest.getRequestURI();
        uri = uri.substring(1);
        if (comparePath(uri, whiteUrl)) {
            //标识请求的路径在白名单里面 可以直接通过
            return true;
        }
       // HandlerMethod hm = (HandlerMethod) o;
       // String packageName = hm.getBean().getClass().getPackage().getName();
        String token  = httpServletRequest.getHeader(AuthConstance.X_AUTH_ACCESS);
        if(StringUtil.isEmpty(token)){
            throw new ServiceException(401,"认证信息已过期，请重新登录");
        }
        User user = authorityService.getUserByToken(token);
        if(user==null){
            throw new ServiceException(401,"认证信息已过期，请重新登录");
        }
        ThreadLocalUtil.clearThreadVariable();
        ThreadLocalUtil.setUser(user);
        return true;
    }


    /*
     * 比较用户能否
     * */
    public boolean comparePath(String path, List<String> list) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        String[] paths = path.split("/");
        for (String r : list) {
            String[] urls = r.split("/");
            if (paths.length != urls.length) {
                continue;
            }
            //每一段的路径匹配
            for (int i = 0; i < paths.length; i++) {
                if (!(mark.equals(urls[i]) || paths[i].equals(urls[i]))) {
                    break;
                }
                if (i + 1 == paths.length) {
                    //校验成功
                    return true;
                }
            }
        }
        return false;
    }


    @Override
    public final void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        init();
    }

    private void init() {
        NotLoginUrl notLoginUrl = applicationContext.getBean(NotLoginUrl.class);
        if (notLoginUrl != null) {
            whiteUrl = notLoginUrl.getUrl();
        }
        authorityService = applicationContext.getBean(AuthorityService.class);
    }
}
