"""
Rate limiting for API endpoints using Flask-Limiter.

Provides decorators and configuration for rate limiting HTTP requests
to prevent abuse and resource exhaustion.

Configuration:
    RATE_LIMIT_FAIL_CLOSED: Set to "true" in production to fail closed
        when rate limiter is not initialized. Default is fail-open for
        easier development setup.

    For production, also configure:
        storage_uri="redis://localhost:6379" for multi-worker support
"""

import os

from flask import g
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from loguru import logger


# Global limiter instance (initialized by app factory)
_limiter = None

# Configuration: fail-closed in production, fail-open in development
RATE_LIMIT_FAIL_CLOSED = (
    os.environ.get("RATE_LIMIT_FAIL_CLOSED", "false").lower() == "true"
)


def get_rate_limiter() -> Limiter:
    """
    Get the global rate limiter instance.

    Returns:
        Flask-Limiter instance

    Raises:
        RuntimeError: If limiter hasn't been initialized
    """
    global _limiter
    if _limiter is None:
        raise RuntimeError(
            "Rate limiter not initialized. Call init_rate_limiter(app) first."
        )
    return _limiter


def init_rate_limiter(app):
    """
    Initialize the rate limiter with the Flask app.

    This should be called once during app initialization.

    Args:
        app: Flask application instance

    Returns:
        Configured Limiter instance
    """
    global _limiter

    # Use authenticated username if available, otherwise fall back to IP
    def get_user_identifier():
        # Check if user is authenticated
        username = g.get("current_user")
        if username:
            return f"user:{username}"
        # Fall back to IP address for unauthenticated requests
        return f"ip:{get_remote_address()}"

    _limiter = Limiter(
        app=app,
        key_func=get_user_identifier,
        default_limits=[],  # No default limits - apply via decorators only
        storage_uri="memory://",  # Use in-memory storage (for development)
        # For production, consider: storage_uri="redis://localhost:6379"
        strategy="fixed-window",
        headers_enabled=True,  # Add rate limit headers to responses
    )

    logger.info("Rate limiter initialized successfully")
    return _limiter


def upload_rate_limit(f):
    """
    Decorator for rate limiting file upload endpoints.

    Limits:
    - 10 uploads per minute per user
    - 100 uploads per hour per user

    Usage:
        @research_bp.route("/api/upload/pdf", methods=["POST"])
        @login_required
        @upload_rate_limit
        def upload_pdf():
            ...

    Returns:
        Decorated function with rate limiting

    Note:
        If the rate limiter is not initialized (e.g., flask_limiter not installed),
        behavior depends on RATE_LIMIT_FAIL_CLOSED environment variable:
        - "false" (default): Pass through without rate limiting (fail-open)
        - "true": Raise RuntimeError, crashing the application (fail-closed)

        Set RATE_LIMIT_FAIL_CLOSED=true in production to ensure rate limiting
        is always active.
    """
    try:
        limiter = get_rate_limiter()
        # Use Flask-Limiter's limit decorator
        return limiter.limit("10 per minute;100 per hour")(f)
    except RuntimeError:
        # Rate limiter not initialized - this is expected if flask_limiter
        # is not installed or init_rate_limiter was not called
        if RATE_LIMIT_FAIL_CLOSED:
            logger.exception(
                f"Rate limiter not initialized for {f.__name__} and "
                "RATE_LIMIT_FAIL_CLOSED is enabled. Application will fail."
            )
            raise
        logger.warning(
            f"Rate limiting disabled for {f.__name__}: "
            "limiter not initialized. Install flask_limiter for rate limiting. "
            "Set RATE_LIMIT_FAIL_CLOSED=true to enforce rate limiting in production."
        )
        return f
    except Exception:
        # Unexpected error - log it but don't break the application
        if RATE_LIMIT_FAIL_CLOSED:
            logger.exception(
                f"Unexpected error applying rate limit to {f.__name__} and "
                "RATE_LIMIT_FAIL_CLOSED is enabled. Application will fail."
            )
            raise
        logger.exception(
            f"Unexpected error applying rate limit to {f.__name__}. "
            "Rate limiting disabled for this endpoint. "
            "Set RATE_LIMIT_FAIL_CLOSED=true to enforce rate limiting in production."
        )
        return f


# Export convenience decorator
__all__ = ["init_rate_limiter", "get_rate_limiter", "upload_rate_limit"]
