"""
Route Info API - Exports endpoint permissions for testing by analyzing FastAPI app routes
"""
from fastapi import APIRouter, Depends, HTTPException
from typing import Dict, List, Set, Optional
import inspect
import re
from pathlib import Path

router = APIRouter()

# Global reference to the FastAPI app (set in main.py)
_app = None

def set_app(app):
    """Set the FastAPI app reference"""
    global _app
    _app = app

def get_user_roles() -> Set[str]:
    """Extract user roles from the backend user model"""
    roles = set()
    
    # Try to extract roles from the user model file
    user_model_path = Path("/app/backend/app/models/user.py")
    if not user_model_path.exists():
        user_model_path = Path(__file__).parent.parent.parent / "app" / "models" / "user.py"
    
    if user_model_path.exists():
        try:
            with open(user_model_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # Look for role definitions or enum
            # Pattern: role = Column(Enum(..., values=['admin', 'creator', 'viewer']))
            enum_pattern = re.compile(r'values=\[([^\]]+)\]')
            match = enum_pattern.search(content)
            if match:
                roles_str = match.group(1)
                roles = set(role.strip().strip('"\'') for role in roles_str.split(','))
            
            # Fallback: look for common role names in the file
            if not roles:
                common_roles = ['admin', 'creator', 'viewer', 'moderator', 'subscriber']
                for role in common_roles:
                    if role in content:
                        roles.add(role)
        except Exception:
            pass
    
    # Default roles if extraction fails
    if not roles:
        roles = {'admin', 'creator', 'viewer'}
    
    return roles

def analyze_route_dependencies(route):
    """Analyze route dependencies to determine required roles"""
    required_roles = set()
    
    # Check dependencies in the route
    has_admin = False
    has_user = False
    
    if hasattr(route, 'dependencies'):
        for dep in route.dependencies:
            dep_str = str(dep)
            if 'get_current_admin_user' in dep_str:
                required_roles.add('admin')
                has_admin = True
            elif 'get_current_user' in dep_str:
                has_user = True
    
    # Check the endpoint function for role checks
    if hasattr(route, 'endpoint'):
        func = route.endpoint
        # Check function signature for role parameters
        sig = inspect.signature(func)
        for param_name, param in sig.parameters.items():
            param_str = str(param)
            if 'admin' in param_str.lower():
                required_roles.add('admin')
                has_admin = True
            if 'current_user' in param_str.lower() or 'user:' in param_str:
                has_user = True
    
    # Determine required roles based on dependencies
    if has_admin:
        required_roles.add('admin')
    elif has_user:
        # If user is authenticated but no specific admin check, add all non-admin roles
        # This means the endpoint is accessible to all authenticated users
        required_roles.update(['creator', 'viewer'])  # Add all non-admin roles
    
    return required_roles

def get_endpoint_permissions(app_override=None) -> Dict[str, Dict]:
    """Get all endpoint permissions by analyzing FastAPI app routes

    Args:
        app_override: Optional FastAPI app instance to use instead of global _app
    """
    permissions = {}

    # Use provided app or fall back to global _app
    target_app = app_override if app_override is not None else _app

    if target_app is None:
        return permissions
    
    # Get available roles from the backend
    available_roles = get_user_roles()

    for route in target_app.routes:
        # Skip non-API routes
        if not hasattr(route, 'methods') or not hasattr(route, 'path'):
            continue
        
        # Skip static files and websocket routes
        if hasattr(route, 'include_in_schema') and not route.include_in_schema:
            continue
        
        # Get methods for this route
        methods = route.methods if route.methods else ['GET']
        
        # Analyze dependencies for this route
        required_roles = analyze_route_dependencies(route)
        
        # Determine if auth is required
        requires_auth = len(required_roles) > 0
        
        # Determine accessible roles
        if requires_auth:
            accessible_roles = required_roles if required_roles else list(available_roles)
        else:
            accessible_roles = list(available_roles)  # All roles can access public endpoints
        
        # Add permissions for each method
        for method in methods:
            if method == 'HEAD':  # Skip HEAD method
                continue
            
            key = f"{method}:{route.path}"
            # Determine category based on path
            category = route.path
            if category.startswith('/api/streams'):
                if '/chat' in category:
                    category = 'api/streams/{stream_id}/chat'
                elif '/comments' in category:
                    category = 'api/streams/{stream_id}/comments'
                else:
                    category = 'api/streams'
            elif category.startswith('/api/users'):
                category = 'api/users'
            elif category.startswith('/api/tags'):
                category = 'api/tags'
            elif category.startswith('/api/auth'):
                if '/twitch' in category:
                    category = 'api/auth/twitch'
                else:
                    category = 'api/auth'
            elif category.startswith('/api/admin'):
                if '/backup' in category:
                    category = 'api/admin/backup'
                else:
                    category = 'api/admin'
            elif category == '/api/health':
                category = 'api/health'
            elif category == '/api/settings':
                category = 'api/settings'
            else:
                category = 'api'

            permissions[key] = {
                "requires_auth": requires_auth,
                "required_roles": list(required_roles),
                "accessible_roles": accessible_roles,
                "available_roles": list(available_roles),
                "path": route.path,
                "method": method,
                "category": category
            }
    
    return permissions


