"""
Simple authentication middleware for NFOGuard web interface
Provides basic HTTP auth and session management for web interface protection
"""
import secrets
import hashlib
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from fastapi import HTTPException, status, Request, Response
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.middleware.base import BaseHTTPMiddleware


class AuthSession:
    """Simple session management for web interface"""
    
    def __init__(self, timeout_seconds: int = 3600):
        self.sessions: Dict[str, Dict[str, Any]] = {}
        self.timeout_seconds = timeout_seconds
    
    def create_session(self, username: str) -> str:
        """Create a new session and return session token"""
        session_token = secrets.token_urlsafe(32)
        self.sessions[session_token] = {
            "username": username,
            "created_at": datetime.utcnow(),
            "last_activity": datetime.utcnow()
        }
        return session_token
    
    def validate_session(self, session_token: str) -> bool:
        """Validate session token and update last activity"""
        if not session_token or session_token not in self.sessions:
            return False
        
        session = self.sessions[session_token]
        now = datetime.utcnow()
        
        # Check if session expired
        if (now - session["last_activity"]).seconds > self.timeout_seconds:
            del self.sessions[session_token]
            return False
        
        # Update last activity
        session["last_activity"] = now
        return True
    
    def get_session_user(self, session_token: str) -> Optional[str]:
        """Get username from valid session"""
        if self.validate_session(session_token):
            return self.sessions[session_token]["username"]
        return None
    
    def delete_session(self, session_token: str) -> None:
        """Delete a session (logout)"""
        if session_token in self.sessions:
            del self.sessions[session_token]
    
    def cleanup_expired_sessions(self) -> None:
        """Remove expired sessions"""
        now = datetime.utcnow()
        expired_tokens = []
        
        for token, session in self.sessions.items():
            if (now - session["last_activity"]).seconds > self.timeout_seconds:
                expired_tokens.append(token)
        
        for token in expired_tokens:
            del self.sessions[token]


class SimpleAuthMiddleware(BaseHTTPMiddleware):
    """Simple authentication middleware for web interface routes"""
    
    def __init__(self, app, config):
        super().__init__(app)
        self.config = config
        self.session_manager = AuthSession(config.web_auth_session_timeout)
        self.security = HTTPBasic()
        
        # Routes that require authentication (web interface)
        self.protected_routes = [
            "/",  # Main web interface
            "/static/",  # Static files (CSS, JS)
            "/api/movies",  # Web API endpoints
            "/api/series",
            "/api/episodes",
            "/api/dashboard"
        ]
        
        # Routes that are always public (webhooks, health checks, API endpoints)
        self.public_routes = [
            "/webhook/",
            "/health",
            "/ping",
            "/api/v1/health",
            "/api/v1/metrics",
            "/database/",  # Database management endpoints (API access)
            "/manual/",    # Manual scan endpoints (API access)
            "/debug/",     # Debug endpoints (API access)
            "/test/",      # Test endpoints (API access)
            "/bulk/"       # Bulk operation endpoints (API access)
        ]
    
    async def dispatch(self, request: Request, call_next):
        """Process request through authentication middleware"""
        
        # Skip authentication if disabled
        if not self.config.web_auth_enabled:
            return await call_next(request)
        
        # Check if route requires authentication
        path = request.url.path
        needs_auth = any(path.startswith(route) for route in self.protected_routes)
        is_public = any(path.startswith(route) for route in self.public_routes)
        
        if is_public or not needs_auth:
            return await call_next(request)
        
        # Check for existing session
        session_token = request.cookies.get("nfoguard_session")
        if session_token and self.session_manager.validate_session(session_token):
            # Valid session, proceed
            return await call_next(request)
        
        # Check for HTTP Basic Auth
        auth_header = request.headers.get("authorization")
        if auth_header and auth_header.startswith("Basic "):
            credentials = self._parse_basic_auth(auth_header)
            if credentials and self._validate_credentials(credentials.username, credentials.password):
                # Create session for successful login
                session_token = self.session_manager.create_session(credentials.username)
                response = await call_next(request)
                response.set_cookie(
                    key="nfoguard_session", 
                    value=session_token,
                    max_age=self.config.web_auth_session_timeout,
                    httponly=True,
                    secure=False  # Set to True if using HTTPS
                )
                return response
        
        # Authentication required
        return self._auth_required_response()
    
    def _parse_basic_auth(self, auth_header: str) -> Optional[HTTPBasicCredentials]:
        """Parse HTTP Basic Auth header"""
        try:
            import base64
            encoded_credentials = auth_header.split(" ")[1]
            decoded_credentials = base64.b64decode(encoded_credentials).decode('utf-8')
            username, password = decoded_credentials.split(":", 1)
            return HTTPBasicCredentials(username=username, password=password)
        except Exception:
            return None
    
    def _validate_credentials(self, username: str, password: str) -> bool:
        """Validate username and password"""
        return (username == self.config.web_auth_username and 
                password == self.config.web_auth_password)
    
    def _auth_required_response(self) -> Response:
        """Return 401 response with WWW-Authenticate header"""
        return Response(
            content="Authentication required",
            status_code=status.HTTP_401_UNAUTHORIZED,
            headers={"WWW-Authenticate": "Basic realm=\"NFOGuard Web Interface\""}
        )


def create_auth_dependencies(config) -> Dict[str, Any]:
    """Create authentication-related dependencies for dependency injection"""
    session_manager = AuthSession(config.web_auth_session_timeout)
    
    return {
        "session_manager": session_manager,
        "auth_enabled": config.web_auth_enabled,
        "auth_config": {
            "username": config.web_auth_username,
            "timeout": config.web_auth_session_timeout
        }
    }