"""
Rate Limiting Service - Singleton Pattern
Sử dụng SlowAPI với Memory backend
"""
from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from fastapi import Request
from slowapi import Limiter
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
from slowapi.util import get_remote_address
from fastapi.responses import JSONResponse

if TYPE_CHECKING:
    from fastapi import FastAPI

logger = logging.getLogger(__name__)


class RateLimitService:
    """
    Rate Limiting Service - Singleton Pattern
    
    Usage:
        @router.post("/chat")
        @rate_limit_service.limiter.limit("50/minute")
        async def chat(request: Request):
            ...
    """
    
    _instance: RateLimitService | None = None
    _initialized: bool = False
    
    def __new__(cls) -> RateLimitService:
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self) -> None:
        if RateLimitService._initialized:
            return
        
        # Paths không áp dụng rate limit
        self.exempt_prefixes = ["/mock", "/api/mock", "/health", "/docs", "/openapi.json", "/redoc"]
        
        # Create limiter instance (memory storage)
        self.limiter = Limiter(
            key_func=self._get_client_identifier,
            storage_uri="memory://",
        )
        
        RateLimitService._initialized = True
        logger.info("✅ RateLimitService initialized")
    
    def _get_client_identifier(self, request: Request) -> str:
        """
        Lấy client identifier cho rate limiting.
        Ưu tiên: user_id > device_id > IP
        Trả về 'exempt' cho paths không rate limit
        """
        # Check exempt paths
        path = request.url.path
        if any(path.startswith(prefix) for prefix in self.exempt_prefixes):
            return "exempt"  # SlowAPI sẽ không limit key này
        
        # 1. User đã login
        if hasattr(request.state, "user_id") and request.state.user_id:
            return f"user:{request.state.user_id}"
        
        # 2. Device ID
        if hasattr(request.state, "device_id") and request.state.device_id:
            return f"device:{request.state.device_id}"
        
        # 3. IP address
        try:
            return f"ip:{get_remote_address(request)}"
        except Exception:
            if request.client:
                return f"ip:{request.client.host}"
            return "unknown"
    
    def setup(self, app: FastAPI) -> None:
        """Setup rate limiting cho FastAPI app."""
        app.state.limiter = self.limiter
        
        # Add SlowAPI middleware
        app.add_middleware(SlowAPIMiddleware)
        
        # Exception handler
        @app.exception_handler(RateLimitExceeded)
        async def rate_limit_handler(request: Request, exc: RateLimitExceeded):
            logger.warning(f"⚠️ Rate limit exceeded: {self._get_client_identifier(request)}")
            return JSONResponse(
                status_code=429,
                content={
                    "status": "error",
                    "error_code": "RATE_LIMIT_EXCEEDED",
                    "message": "Quá số lượt cho phép. Vui lòng thử lại sau.",
                },
            )
        
        logger.info("✅ Rate limiting middleware registered")


# Singleton instance
rate_limit_service = RateLimitService()
