#!/usr/bin/env python3
"""
Proxy trust and client IP resolution.

Safely extracts real client IP from X-Forwarded-For header only when
request originates from trusted proxy CIDRs. Prevents IP spoofing attacks.
"""
import os
import ipaddress
from fastapi import Request


# Parse trusted proxy CIDRs from environment
TRUSTED_PROXY_CIDRS = [
    cidr.strip() for cidr in
    os.getenv("FLOWTORCH_TRUSTED_PROXIES", "").split(",")
    if cidr.strip()
]

try:
    TRUSTED_NETWORKS = [ipaddress.ip_network(c) for c in TRUSTED_PROXY_CIDRS]
except ValueError as e:
    # Invalid CIDR in config - fail loudly
    raise RuntimeError(f"Invalid CIDR in FLOWTORCH_TRUSTED_PROXIES: {e}")


def get_client_ip(request: Request) -> str:
    """
    Resolve client IP address with proxy trust semantics.

    If request comes from trusted proxy CIDR, extract first IP from
    X-Forwarded-For header (leftmost = original client).

    Otherwise, use direct connection IP (request.client.host).

    Args:
        request: FastAPI Request object

    Returns:
        Client IP address as string
    """
    if not request.client or not request.client.host:
        return "unknown"

    # Check if source IP is in trusted proxy range
    try:
        src_ip = ipaddress.ip_address(request.client.host)
    except ValueError:
        # Invalid source IP - fall back to direct host
        return request.client.host

    # If source is trusted proxy, extract from X-Forwarded-For
    if any(src_ip in net for net in TRUSTED_NETWORKS):
        xff = request.headers.get("x-forwarded-for", "").split(",")[0].strip()
        if xff:
            try:
                # Validate XFF is a valid IP before trusting it
                ipaddress.ip_address(xff)
                return xff
            except ValueError:
                # Invalid XFF value - fall back to direct
                pass

    # Default: use direct connection IP
    return request.client.host
