package com.crm.gateway.filter;

import com.crm.gateway.constants.RoleConstants;
import com.crm.gateway.property.ConfigureProperty;
import com.crm.gateway.service.RedisService;
import com.crm.gateway.service.UserFeignService;
import com.crm.gateway.util.HttpServletRequestUtil;
import com.crm.gateway.util.InteceptorResultUtil;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.PrefixEnum;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.entity.user.BaseUserInfoEntity;
import com.google.common.base.Strings;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RequestMethod;

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

@Component
public class JwtCheckGatewayFilterFactory extends ZuulFilter {
    @Autowired
    ConfigureProperty configureProperty;

    public static final String PRE_TYPE = "pre";

    @Autowired
    private UserFeignService userFeignService;

    @Autowired
    private RedisService redisService;

    private static AntPathMatcher antPathMatcher;

    static {
        antPathMatcher = new AntPathMatcher();
    }

    // 前置过滤器
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    // 过滤顺序
    @Override
    public int filterOrder() {
        return 4;
    }

    @SneakyThrows
    @Override
    public boolean shouldFilter() {

        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        String uri = request.getRequestURI();
        //如果为OPTIONS直接返回成功
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            return true;
        }

        boolean matchs = false;
        for (String path : configureProperty.getRaleExcludePathPatterns()) {
            if (Strings.isNullOrEmpty(path)) {
                continue;
            }
            matchs = antPathMatcher.matchStart(path, uri);
            if (matchs) {
                break;
            }
        }

        return !matchs;
    }

    @SneakyThrows
    @Override
    public Object run() {
//        RequestContext requestContext = RequestContext.getCurrentContext();
//        HttpServletRequest request = requestContext.getRequest();
//        HttpServletResponse response = requestContext.getResponse();
//        boolean handle = handle(request, response);
//        if (!handle) {
//            requestContext.setSendZuulResponse(handle);
//            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
//        }
//        return null;
        return  null;
    }

    private boolean handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        String uri = httpServletRequest.getRequestURI();
        for (String path : configureProperty.getLoginExcludePathPatterns()) {
            if (Strings.isNullOrEmpty(path)) {
                continue;
            }
            if (antPathMatcher.matchStart(path, uri)) {
                return true;
            }
        }

        BaseUserInfoEntity infoEntity = HttpServletRequestUtil.getLoginInfo(httpServletRequest, redisService, true);

        if (infoEntity == null) {

            InteceptorResultUtil.returnResult(httpServletResponse, BaseResultDto.result(Constants.UNLOGIN_CODE, Constants.INVALID));
            return false;
        }
        if (PrefixEnum.PREFIX_SYSTEM.equals(infoEntity.getPrefix())) {
            return true;
        }

        String key;
        if (infoEntity.getRoleId() == null || infoEntity.getRoleId() == 0) {
            key = RoleConstants.ROLE_USER_ACTION + RoleConstants.ROLE_ADMIN;
        } else {
            key = RoleConstants.ROLE_USER_ACTION + infoEntity.getRoleId().toString();
        }
        String requestPath = httpServletRequest.getRequestURI();
        /*
         * 验证权限
         */
        if (!redisService.hasKey(key)) {
            userFeignService.getUserNodeDisplay(infoEntity.getRoleId());
        }
        List<String> actionList = redisService.getObject(key);
        if (actionList == null || actionList.size() == 0) {
            InteceptorResultUtil.returnResult(httpServletResponse, BaseResultDto.result(Constants.FAILED_CODE, Constants.NOT_PERMIT));
            return false;
        }
        for (String action : actionList) {
            if (requestPath.startsWith(action)) {
                return true;
            }
        }
        InteceptorResultUtil.returnResult(httpServletResponse, BaseResultDto.result(Constants.FAILED_CODE, Constants.NOT_PERMIT));
        return false;
    }
}
