package org.gateway.filter;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.maxkey.persistence.redis.RedisConnection;
import org.maxkey.persistence.redis.RedisConnectionFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 认证和记录日志
 */
@Component
public class AuthAndLogFilter implements GlobalFilter, Ordered
{

    private final Logger logger = LoggerFactory.getLogger(AuthAndLogFilter.class);

    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        //获取token
        String address = exchange.getRequest().getPath().toString();
        //registration/registeron

        if (address.contains("thirdLogin/login") // 登录
                || address.contains("thirdLogin/getUserInfo") // 获取用户
                || address.contains("registration/registeron") // 注册
                || address.contains("logon/oauth20/authorize/dingtalk") // 钉钉登录
                || address.contains("logon/oauth20/scanqrcode/dingtalk") // 钉钉登录
                || address.contains("logon/oauth20/callback/dingtalk")
                || address.contains("api/v3/share")
                || address.contains("api/v3/configurations")
                || address.contains("image/display")
                || address.contains("/share/record/"))

        {
            return chain.filter(exchange.mutate().build());
        }
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        System.out.println("Authorization is : " + token);
        ServerHttpResponse resp = exchange.getResponse();
        if (StringUtils.isBlank(token))
        {
            //没有token
            return denyAccess(exchange, "token不存在");

        }
        // redis 连接
        RedisConnection redisConnection = redisConnectionFactory.getConnection();
        String userInfo = (String) redisConnection.get(token);
        redisConnection.close();
        System.out.println(userInfo);
        if (StringUtils.isEmpty(userInfo))
        {
            return denyAccess(exchange, "token认证错误");
        }
        System.out.println("token is : " + userInfo.toString());
        ServerHttpRequest newRequest = exchange.getRequest().mutate()
                .header("userinfo", userInfo)
                .build();
        return chain.filter(exchange.mutate().request(newRequest).build());
    }

    /**
     * 拦截并返回自定义的json字符串
     */
    private Mono<Void> denyAccess(ServerWebExchange exchange, String message)
    {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.OK);
        //这里在返回头添加编码，否则中文会乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] bytes = JSON.toJSONBytes(message, SerializerFeature.WriteMapNullValue);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(buffer));
    }

    /**
     * 失败返回message提示用户
     *
     * @param exchange
     * @param url
     * @return
     */

    private Mono<Void> fallBack(String url, ServerWebExchange exchange)
    {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.SEE_OTHER);
        response.getHeaders().set(HttpHeaders.LOCATION, url);
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder()
    {
        logger.trace(" -20");
        return -20;
    }
}
