package com.sw.mes.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.sw.mes.gateway.config.GatewaySwaggerProvider;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class CheckAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> {

    private static final Log logger = LogFactory.getLog(CheckAuthGatewayFilterFactory.class);

    private static final String AUTHORIZE_TOKEN = "token";
    /**
     * 后门token
     */
    private static final String TOKEN_ADMIN = "token_admin";
    /**
     * eap系统token
     */
    private static final String EAP_SYSTEM_TOKEN = "eap_system_admin";
    /**
     * MCS 系统token
     */
    private static final String MCS_SYSTEM_TOKEN = "df3a11d2-d94d-4661-a972-6c314b0f9658";
    /**
     * FLS 系统token
     */
    private static final String FLS_SYSTEM_TOKEN = "ace064c9-55d2-409f-90ca-f721f7826cc1";
    /**
     * wms token
     */
    private static final String WMSSERVER_TOKEN = "0218FB67E4DEF20B8EE0B2262B45C0B0";
    /**
     * 令牌前缀
     */
    public static final String TOKEN_PREFIX = "BearerJk ";

    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    RedisProperties redisProperties;

    public CheckAuthGatewayFilterFactory() {
        super(Config.class);
        logger.info("Loaded GatewayFilterFactory [CheckAuth]");
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }

    @Override
    public GatewayFilter apply(CheckAuthGatewayFilterFactory.Config config) {
        return (exchange, chain) -> {

//            logger.info("Loaded GatewayFilterFactory [CheckAuth] -->> apply -->>");

            if (!config.isEnabled()) {
                return chain.filter(exchange);
            }
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (StringUtils.endsWithIgnoreCase(path, GatewaySwaggerProvider.API_URI)) {
                return chain.filter(exchange);
            }
            HttpHeaders headers = request.getHeaders();
            String token = headers.getFirst(AUTHORIZE_TOKEN);
            if (token == null) {
                token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
            }
            List<String> tokens = new ArrayList<>();
            tokens.add(TOKEN_ADMIN);
            tokens.add(EAP_SYSTEM_TOKEN);
            tokens.add(MCS_SYSTEM_TOKEN);
            tokens.add(WMSSERVER_TOKEN);
            tokens.add(FLS_SYSTEM_TOKEN);
            if (tokens.contains(token)) {
                return chain.filter(exchange);
            }
            if (StringUtils.isBlank(token)) {
                JSONObject message = new JSONObject();
                message.put("status", 201);
                message.put("code", 402);
                message.put("message", "登录信息为空！");
                return handleException(exchange, message);
            }
            Object authToken = null;
            try {
                authToken = redisTemplate.opsForValue().get(TOKEN_PREFIX + token);
            } catch (Exception e) {
            }
            if (authToken == null) {
                JSONObject message = new JSONObject();
                message.put("status", 201);
                message.put("code", 401);
                message.put("message", "登录信息已过期");
                return handleException(exchange, message);
            }
            return chain.filter(exchange);
        };
    }

    private Mono<Void> handleException(ServerWebExchange exchange, JSONObject message) {
        ServerHttpResponse response = exchange.getResponse();
        byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        response.setStatusCode(HttpStatus.OK);
        // 指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }

    public static class Config {
        // 控制是否开启认证
        private boolean enabled;

        public Config() {
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }

}
