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 and get info in one call
        rate_limit_info, rate_limit_exception = await limiter.check_with_info(
            identity=identity, endpoint=endpoint
        )

        if rate_limit_exception:
            # Return 429 Too Many Requests with all rate limit headers
            e = rate_limit_exception
            import time
            from fastapi import HTTPException

            reset_timestamp = int(time.time()) + e.retry_after
            headers = {
                "Retry-After": str(e.retry_after),
                "X-RateLimit-Limit": str(e.limit),
                "X-RateLimit-Remaining": "0",
                "X-RateLimit-Reset": str(reset_timestamp),
            }
            raise HTTPException(
                status_code=429,
                detail=f"Rate limit exceeded. Retry after {e.retry_after} seconds.",
                headers=headers,
            )

        # Store rate limit info in request state for potential use in response
        # Note: Dependencies run before endpoint handlers, so we can't directly modify
        # the response here. Headers would need to be added via response dependency
        # or middleware. For now, we just ensure the dependency passes.
        if rate_limit_info:
            # Store in request state in case we want to use it later
            if not hasattr(request.state, "rate_limit_info"):
                request.state.rate_limit_info = rate_limit_info

    return dependency
