"""
Middleware Module - Gom Auth + Rate Limit
Singleton Pattern cho cả 2 services
"""
from __future__ import annotations

import logging
from collections.abc import Callable
from typing import TYPE_CHECKING

from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware

from common.clerk_auth import verify_clerk_jwt
from config import DISABLE_AUTH

if TYPE_CHECKING:
    from fastapi import FastAPI

logger = logging.getLogger(__name__)


# =============================================================================
# CONFIGURATION
# =============================================================================

# Public endpoints - không cần auth
PUBLIC_PATHS = {
    "/",
    "/health",
    "/docs",
    "/openapi.json",
    "/redoc",
}

# Public path prefixes
PUBLIC_PATH_PREFIXES = [
    "/static",
    "/mock",
]


# =============================================================================
# AUTH + RATE LIMIT MIDDLEWARE CLASS
# =============================================================================

# Paths that need rate limit check
RATE_LIMITED_PATHS = [
    "/api/agent/chat",
]

class CanifaAuthMiddleware(BaseHTTPMiddleware):
    """
    Authentication + Rate Limit Middleware
    
    Flow:
    1. Frontend gửi request với Authorization: Bearer <canifa_token>
    2. Middleware verify token với Canifa API → extract customer_id
    3. Check message rate limit (Guest: 10, User: 100)
    4. Attach user info vào request.state
    5. Routes lấy trực tiếp từ request.state
    """

    async def dispatch(self, request: Request, call_next: Callable):
        path = request.url.path
        method = request.method

        # Temporary bypass: skip auth/rate-limit when DISABLE_AUTH=true
        if DISABLE_AUTH:
            return await call_next(request)

        # ✅ Allow OPTIONS requests (CORS preflight)
        if method == "OPTIONS":
            return await call_next(request)

        # Skip public endpoints
        if path in PUBLIC_PATHS:
            return await call_next(request)

        # Skip public path prefixes
        if any(path.startswith(prefix) for prefix in PUBLIC_PATH_PREFIXES):
            return await call_next(request)

        # =====================================================================
        # STEP 1: AUTHENTICATION (Clerk JWT)
        # =====================================================================
        try:
            auth_header = request.headers.get("Authorization")
            device_id = request.headers.get("device_id", "")

            # ========== DEV MODE: Bypass auth ==========
            dev_user_id = request.headers.get("X-Dev-User-Id")
            if dev_user_id:
                logger.warning(f"⚠️ DEV MODE: Using X-Dev-User-Id={dev_user_id}")
                request.state.user = {"customer_id": dev_user_id}
                request.state.user_id = dev_user_id
                request.state.is_authenticated = True
                request.state.device_id = device_id or dev_user_id
                return await call_next(request)

            # --- TRƯỜNG HỢP 1: KHÔNG CÓ TOKEN -> GUEST ---
            if not auth_header or not auth_header.startswith("Bearer "):
                request.state.user = None
                request.state.user_id = None
                request.state.is_authenticated = False
                request.state.device_id = device_id
            else:
                # --- TRƯỜNG HỢP 2: CÓ TOKEN -> VERIFY CLERK JWT ---
                token = auth_header.replace("Bearer ", "")
                try:
                    payload = verify_clerk_jwt(token)
                    user_id = payload.get("sub")
                    if user_id:
                        request.state.user = payload
                        request.state.user_id = str(user_id)
                        request.state.token = token
                        request.state.is_authenticated = True
                        request.state.device_id = device_id or str(user_id)
                        logger.debug("✅ Clerk Auth Success: user_id=%s", user_id)
                    else:
                        logger.warning("⚠️ Clerk token missing sub -> Guest Mode")
                        request.state.user = None
                        request.state.user_id = None
                        request.state.is_authenticated = False
                        request.state.device_id = device_id
                except Exception as e:
                    logger.error("❌ Clerk Auth Error: %s -> Guest Mode", e)
                    request.state.user = None
                    request.state.user_id = None
                    request.state.is_authenticated = False
                    request.state.device_id = device_id

        except Exception as e:
            logger.error(f"❌ Middleware Auth Error: {e}")
            request.state.user = None
            request.state.user_id = None
            request.state.is_authenticated = False
            request.state.device_id = request.headers.get("device_id", "")

        # =====================================================================
        # STEP 2: RATE LIMIT CHECK (Chỉ cho các path cần limit)
        # =====================================================================
        if path in RATE_LIMITED_PATHS:
            try:
                from common.message_limit import message_limit_service
                from fastapi.responses import JSONResponse
                
                # Lấy identity_key làm rate limit key
                # Guest: device_id → limit 10
                # User: user_id → limit 100
                is_authenticated = request.state.is_authenticated
                if is_authenticated and request.state.user_id:
                    rate_limit_key = request.state.user_id
                else:
                    rate_limit_key = request.state.device_id
                
                if rate_limit_key:
                    can_send, limit_info = await message_limit_service.check_limit(
                        identity_key=rate_limit_key,
                        is_authenticated=is_authenticated,
                    )
                    
                    # Lưu limit_info vào request.state để route có thể dùng
                    request.state.limit_info = limit_info
                    
                    if not can_send:
                        logger.warning(
                            "⚠️ Rate Limit Exceeded: %s | used=%s/%s",
                            rate_limit_key,
                            limit_info["used"],
                            limit_info["limit"],
                        )
                        return JSONResponse(
                            status_code=429,
                            content={
                                "status": "error",
                                "error_code": "MESSAGE_LIMIT_EXCEEDED",
                                "message": limit_info["message"],
                                "require_login": limit_info["require_login"],
                                "limit_info": {
                                    "limit": limit_info["limit"],
                                    "used": limit_info["used"],
                                    "remaining": limit_info["remaining"],
                                    "reset_seconds": limit_info["reset_seconds"],
                                },
                            },
                        )
                else:
                    logger.warning(f"⚠️ No identity_key for rate limiting")
                    
            except Exception as e:
                logger.error(f"❌ Rate Limit Check Error: {e}")
                # Cho phép request tiếp tục nếu lỗi rate limit
            
        return await call_next(request)


# =============================================================================
# MIDDLEWARE MANAGER - Singleton to manage all middlewares
# =============================================================================

class MiddlewareManager:
    """
    Middleware Manager - Singleton Pattern
    Quản lý và setup tất cả middlewares cho FastAPI app
    
    Usage:
        from common.middleware import middleware_manager
        
        app = FastAPI()
        middleware_manager.setup(app, enable_auth=True, enable_rate_limit=True)
    """
    
    _instance: MiddlewareManager | None = None
    _initialized: bool = False
    
    def __new__(cls) -> MiddlewareManager:
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self) -> None:
        if MiddlewareManager._initialized:
            return
        
        self._auth_enabled = False
        self._rate_limit_enabled = False
        
        MiddlewareManager._initialized = True
        logger.info("✅ MiddlewareManager initialized")
    
    def setup(
        self,
        app: FastAPI,
        *,
        enable_auth: bool = True,
        enable_rate_limit: bool = True,
        enable_cors: bool = True,
        cors_origins: list[str] | None = None,
    ) -> None:
        """
        Setup tất cả middlewares cho FastAPI app.
        
        Args:
            app: FastAPI application
            enable_auth: Bật Canifa authentication middleware
            enable_rate_limit: Bật rate limiting
            enable_cors: Bật CORS middleware
            cors_origins: List origins cho CORS (default: ["*"])
        
        Note:
            Thứ tự middleware quan trọng! Middleware thêm sau sẽ chạy TRƯỚC.
            Order: CORS → Auth → RateLimit → SlowAPI
        """
        # 1. CORS Middleware (thêm cuối cùng để chạy đầu tiên)
        if enable_cors:
            self._setup_cors(app, cors_origins or ["*"])
        
        # 2. Auth Middleware
        if enable_auth:
            self._setup_auth(app)
        
        # 3. Rate Limit Middleware
        if enable_rate_limit:
            self._setup_rate_limit(app)
        
        logger.info(
            f"✅ Middlewares configured: "
            f"CORS={enable_cors}, Auth={enable_auth}, RateLimit={enable_rate_limit}"
        )
    
    def _setup_cors(self, app: FastAPI, origins: list[str]) -> None:
        """Setup CORS middleware."""
        from fastapi.middleware.cors import CORSMiddleware
        
        app.add_middleware(
            CORSMiddleware,
            allow_origins=origins,
            allow_credentials=True,
            allow_methods=["*"],
            allow_headers=["*"],
        )
        logger.info(f"✅ CORS middleware enabled (origins: {origins})")
    
    def _setup_auth(self, app: FastAPI) -> None:
        """Setup Canifa auth middleware."""
        app.add_middleware(CanifaAuthMiddleware)
        self._auth_enabled = True
        logger.info("✅ Canifa Auth middleware enabled")
    
    def _setup_rate_limit(self, app: FastAPI) -> None:
        """Setup rate limiting."""
        from common.rate_limit import rate_limit_service
        
        rate_limit_service.setup(app)
        self._rate_limit_enabled = True
        logger.info("✅ Rate Limit middleware enabled")
    
    @property
    def is_auth_enabled(self) -> bool:
        return self._auth_enabled
    
    @property
    def is_rate_limit_enabled(self) -> bool:
        return self._rate_limit_enabled


# =============================================================================
# SINGLETON INSTANCE
# =============================================================================

middleware_manager = MiddlewareManager()
