from typing import Callable, Optional

from fastapi import Depends, Request

from rate_limiter.config import RateLimiterConfig
from rate_limiter.core.identity import IdentityResolver, get_identity_resolver
from rate_limiter.core.limiter import RateLimiter
from rate_limiter.core.rules import RateLimitRule
from rate_limiter.exceptions import RateLimitExceeded


def rate_limit_dep(
    rule_str: str,
    key: str = "ip",
    config: Optional[RateLimiterConfig] = None,
    identity_resolver: Optional[IdentityResolver] = None,
) -> Callable:
    """
    Create a FastAPI dependency for rate limiting.

    Args:
        rule_str: Rate limit rule string (e.g., "10/minute")
        key: Identity key type ("ip", "user_id", "api_key")
        config: Optional rate limiter configuration
        identity_resolver: Optional custom identity resolver

    Returns:
        Dependency function

    Example:
        router = APIRouter(
            dependencies=[Depends(rate_limit_dep("10/minute", key="ip"))]
        )
    """
    rule = RateLimitRule.from_string(rule_str, key=key)
    limiter_config = config or RateLimiterConfig.from_env()
    limiter = RateLimiter(config=limiter_config, rules=[rule])
    resolver = identity_resolver or get_identity_resolver(
        key, trust_proxy=limiter_config.trust_proxy_headers
    )

    async def dependency(request: Request) -> None:
        """Rate limit dependency."""
        # Resolve identity
        identity = await resolver.resolve(request)

        # Get endpoint path
        endpoint = request.url.path if hasattr(request, "url") else ""

        # Check rate limit
        try:
            await limiter.check(identity=identity, endpoint=endpoint)
        except RateLimitExceeded as e:
            from fastapi import HTTPException

            raise HTTPException(
                status_code=429,
                detail=f"Rate limit exceeded. Retry after {e.retry_after} seconds.",
                headers={"Retry-After": str(e.retry_after)},
            )

    return dependency
