# shared/utils/http.py

# Third Party
from fastapi import APIRouter

def list_router_endpoints(router: APIRouter) -> list[str]:
    """
    List all endpoints for a given router in the format "METHOD PATH".

    Deduplicates endpoints to account for /path and /path/ variants.
    If both variants exist, combines them as "METHOD /path + /".
    Example:
    ``` python
    [
        "GET    /api/v1/models + /",
        "POST   /api/v1/models",
        "GET    /api/v1/models/details + /",
    ]
    ```
    """
    # Track endpoints by (method, normalized_path) -> set of path variants
    endpoint_variants = {}
    
    for route in router.routes:
        if hasattr(route, 'path') and hasattr(route, 'methods'):
            methods = getattr(route, 'methods', set())
            original_path = route.path
            
            # Normalize path: remove trailing slash except for root "/"
            if original_path == '/' or original_path == '':
                normalized_path = router.prefix
                is_trailing_slash = (original_path == '/')
            else:
                path_without_slash = original_path.rstrip('/')
                # Check if path already includes the router prefix (for included routers)
                # FastAPI may store full paths for routes from included routers
                # If route.path already starts with router.prefix, use it as-is to avoid duplication
                if router.prefix and path_without_slash.startswith(router.prefix):
                    normalized_path = path_without_slash
                elif router.prefix:
                    # Ensure we don't double-add the prefix if path already starts with it
                    # Handle case where prefix might be part of a longer path
                    normalized_path = f"{router.prefix}{path_without_slash}"
                else:
                    # No prefix, use path as-is
                    normalized_path = path_without_slash
                is_trailing_slash = original_path.endswith('/')
            
            for method in methods:
                key = (method, normalized_path)
                if key not in endpoint_variants:
                    endpoint_variants[key] = set()
                
                # Track if this route has a trailing slash variant
                if is_trailing_slash:
                    endpoint_variants[key].add('trailing_slash')
                else:
                    endpoint_variants[key].add('no_trailing_slash')
    
    # Build the final list with aligned formatting
    result = []
    # Find the longest method name for alignment
    max_method_length = max(len(method) for (method, _), _ in endpoint_variants.items()) if endpoint_variants else 0
    
    for (method, normalized_path), variants in endpoint_variants.items():
        display_path = normalized_path if normalized_path else router.prefix
        
        # Pad method name to align paths
        padded_method = method.ljust(max_method_length)
        
        # If both variants exist, show "METHOD /path + /"
        if 'trailing_slash' in variants and 'no_trailing_slash' in variants:
            result.append(f"{padded_method} {display_path} + /")
        else:
            result.append(f"{padded_method} {display_path}")
    
    return sorted(result)