package ink.wgink.gateway.filter.web;

import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.handler.log.RequestLogHandler;
import ink.wgink.gateway.pojo.log.RequestLog;
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.WebSession;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: WebFluxConfig
 * @Description:
 * @Author: wanggeng
 * @Date: 2021/4/14 2:42 下午
 * @Version: 1.0
 */
@Component
public class WebFluxFilter implements WebFilter {

    /**
     * 校验的路径
     */
    private List<PathPattern> unPassPatterns = Arrays.asList(new PathPattern[]{
            new PathPatternParser().parse(ISystemConst.ADMIN_ROUTER_PREFIX + "/**")
    });

    /**
     * 不校验的路径
     */
    private List<PathPattern> passPathPatterns = Arrays.asList(new PathPattern[]{
            new PathPatternParser().parse(ISystemConst.ADMIN_ROUTER_PREFIX + "/assets/**"),
            new PathPatternParser().parse(ISystemConst.ADMIN_ROUTER_PREFIX + "/api/sign/**"),
            new PathPatternParser().parse(ISystemConst.PAGE_LOGIN),
    });

    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
        ServerHttpResponse serverHttpResponse = serverWebExchange.getResponse();
        HttpHeaders headers = serverHttpResponse.getHeaders();
        // 校验登录的路径，管理使用
        if (this.isUnPass(serverWebExchange)) {
            // 直接放行的路径
            if (this.isPass(serverWebExchange)) {
                return webFilterChain.filter(serverWebExchange);
            }
            return serverWebExchange.getSession().flatMap(webSession -> {
                if (this.isLogin(webSession)) {
                    return webFilterChain.filter(serverWebExchange);
                }
                serverHttpResponse.setStatusCode(HttpStatus.FOUND);
                headers.setLocation(URI.create(ISystemConst.PAGE_LOGIN));
                return serverHttpResponse.setComplete();
            });
        }
        // 其它情况，一律放行
        return webFilterChain.filter(serverWebExchange);
    }

    /**
     * 是否不校验登录
     *
     * @param serverWebExchange
     * @return
     */
    private boolean isPass(ServerWebExchange serverWebExchange) {
        return passPathPatterns.stream().anyMatch(pathPattern -> pathPattern.matches(serverWebExchange.getRequest().getPath()));
    }

    /**
     * 是否校验登录
     *
     * @param serverWebExchange
     * @return
     */
    private boolean isUnPass(ServerWebExchange serverWebExchange) {
        return unPassPatterns.stream().anyMatch(pathPattern -> pathPattern.matches(serverWebExchange.getRequest().getPath()));
    }

    /**
     * 是否登录
     *
     * @param webSession
     * @return
     */
    private boolean isLogin(WebSession webSession) {
        return webSession.getAttributes().get(ISystemConst.SESSION_USER) != null;
    }

}
