package cn.novalon.gym.manage.sys.util;

import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.reactive.function.server.ServerRequest;
import java.net.InetSocketAddress;
import java.util.Optional;

/**
 * IP地址工具类
 * 用于从ServerRequest或ServerHttpRequest中获取客户端真实IP地址
 * 支持代理服务器场景(X-Forwarded-For, X-Real-IP)
 * 
 * @author 张翔
 * @date 2026-04-03
 */
public class IpUtils {
    
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST_IP = "127.0.0.1";
    private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
    
    /**
     * 从ServerRequest中获取客户端真实IP地址
     * 支持代理服务器场景,优先级: X-Forwarded-For > X-Real-IP > RemoteAddress
     * 
     * @param request ServerRequest对象
     * @return 客户端IP地址,获取失败返回"unknown"
     */
    public static String getClientIp(ServerRequest request) {
        if (request == null) {
            return UNKNOWN;
        }

        String ip = getXForwardedForIp(request);
        if (isValidIp(ip)) {
            return ip;
        }

        ip = getXRealIp(request);
        if (isValidIp(ip)) {
            return ip;
        }

        ip = getRemoteAddress(request);
        if (isValidIp(ip)) {
            return ip;
        }

        return UNKNOWN;
    }

    /**
     * 从ServerHttpRequest中获取客户端真实IP地址
     * 支持代理服务器场景,优先级: X-Forwarded-For > X-Real-IP > RemoteAddress
     * 
     * @param request ServerHttpRequest对象
     * @return 客户端IP地址,获取失败返回"unknown"
     */
    public static String getClientIp(ServerHttpRequest request) {
        if (request == null) {
            return UNKNOWN;
        }

        String ip = getXForwardedForIp(request);
        if (isValidIp(ip)) {
            return ip;
        }

        ip = getXRealIp(request);
        if (isValidIp(ip)) {
            return ip;
        }

        ip = getRemoteAddress(request);
        if (isValidIp(ip)) {
            return ip;
        }

        return UNKNOWN;
    }

    /**
     * 从X-Forwarded-For头获取IP地址
     * X-Forwarded-For格式: client, proxy1, proxy2
     * 取第一个非unknown的有效IP
     */
    private static String getXForwardedForIp(ServerRequest request) {
        String ip = request.headers().firstHeader("X-Forwarded-For");
        if (ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            }
            return ip;
        }
        return null;
    }

    /**
     * 从X-Real-IP头获取IP地址
     */
    private static String getXRealIp(ServerRequest request) {
        String ip = request.headers().firstHeader("X-Real-IP");
        if (ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
            return ip;
        }
        return null;
    }

    /**
     * 从RemoteAddress获取IP地址
     * 将IPv6本地地址转换为IPv4格式
     */
    private static String getRemoteAddress(ServerRequest request) {
        Optional<InetSocketAddress> remoteAddress = request.remoteAddress();
        if (remoteAddress.isPresent()) {
            String ip = remoteAddress.get().getAddress().getHostAddress();
            if (LOCALHOST_IPV6.equals(ip)) {
                ip = LOCALHOST_IP;
            }
            return ip;
        }
        return null;
    }

    /**
     * 验证IP地址是否有效
     */
    private static boolean isValidIp(String ip) {
        return ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip);
    }

    /**
     * 从X-Forwarded-For头获取IP地址(ServerHttpRequest版本)
     * X-Forwarded-For格式: client, proxy1, proxy2
     * 取第一个非unknown的有效IP
     */
    private static String getXForwardedForIp(ServerHttpRequest request) {
        String ip = request.getHeaders().getFirst("X-Forwarded-For");
        if (ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            }
            return ip;
        }
        return null;
    }

    /**
     * 从X-Real-IP头获取IP地址(ServerHttpRequest版本)
     */
    private static String getXRealIp(ServerHttpRequest request) {
        String ip = request.getHeaders().getFirst("X-Real-IP");
        if (ip != null && ip.length() > 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
            return ip;
        }
        return null;
    }

    /**
     * 从RemoteAddress获取IP地址(ServerHttpRequest版本)
     * 将IPv6本地地址转换为IPv4格式
     */
    private static String getRemoteAddress(ServerHttpRequest request) {
        InetSocketAddress remoteAddress = request.getRemoteAddress();
        if (remoteAddress != null) {
            String ip = remoteAddress.getAddress().getHostAddress();
            if (LOCALHOST_IPV6.equals(ip)) {
                ip = LOCALHOST_IP;
            }
            return ip;
        }
        return null;
    }
}
