package com.tofly.third.filter;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.tofly.third.config.ThirdSysConfigProperties;
import com.tofly.third.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
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.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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 java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class ThirdSystemGlobalFilter implements GlobalFilter, Ordered {

    public static final String SIGN_HEADER = "X-Sign";
    public static final String APP_ID_HEADER = "X-Appid";
    public static final String TIMESTAMP_HEADER = "X-Timestamp";

    @Autowired
    private ThirdSysConfigProperties thirdSysConfigProperties;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();

        String appid = headers.getFirst(APP_ID_HEADER);
        String reqTimestamp = headers.getFirst(TIMESTAMP_HEADER);
        String sign = headers.getFirst(SIGN_HEADER);

        if (StrUtil.isEmpty(appid) || StrUtil.isEmpty(reqTimestamp) || StrUtil.isEmpty(sign)) {
            return writeErrorResponse(exchange.getResponse(), createErrorResponse("无效请求"));
        }

        long minute = DateUtil.spendMs(Long.valueOf(reqTimestamp)) / (1000 * 60);
        if (minute > 2) {
            return writeErrorResponse(exchange.getResponse(), createErrorResponse("请求过期"));
        }

        Map<String, String> appSecretMap = thirdSysConfigProperties.getAppSecretMap();
        String appSecret = appSecretMap.get(appid);

        if (MapUtil.isEmpty(appSecretMap) || StrUtil.isEmpty(appSecret)) {
            writeErrorResponse(exchange.getResponse(), createErrorResponse("非法请求"));
        }

        boolean checkSign = SignUtil.checkSign(appid, reqTimestamp, sign, appSecret);
        if (!checkSign) {
            return writeErrorResponse(exchange.getResponse(), createErrorResponse("签名错误"));
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private static Map<String, Object> createErrorResponse(String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("code", "1");
        response.put("message", message);
        response.put("result", null);
        response.put("success", false);
        response.put("timestamp", System.currentTimeMillis());
        return response;
    }

    private Mono<Void> writeErrorResponse(ServerHttpResponse response, Map<String, Object> errorResponse) {
        response.setStatusCode(HttpStatus.BAD_REQUEST);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        String jsonResponse = JSONUtil.toJsonStr(errorResponse);
        return response.writeWith(
                Mono.just(response.bufferFactory().wrap(jsonResponse.getBytes(StandardCharsets.UTF_8)))
        );
    }

}
