""" Admin API routes for configuration and management. """ from fastapi import APIRouter, HTTPException, Request from ..models import HealthResponse, ErrorResponse from indexer.mapping_generator import get_tenant_index_name router = APIRouter(prefix="/admin", tags=["admin"]) @router.get("/health", response_model=HealthResponse) async def health_check(): """ Health check endpoint. Returns service status and Elasticsearch connectivity. """ try: from ..app import get_es_client, get_config es_client = get_es_client() config = get_config() # Check ES connectivity es_status = "connected" if es_client.ping() else "disconnected" return HealthResponse( status="healthy" if es_status == "connected" else "unhealthy", elasticsearch=es_status ) except Exception as e: return HealthResponse( status="unhealthy", elasticsearch="error" ) @router.get("/config") async def get_configuration(): """ Get the effective application configuration (sanitized). """ try: from ..app import get_config return get_config().sanitized_dict() except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/config/meta") async def get_configuration_meta(): """Get configuration metadata for observability.""" try: from ..app import get_config config = get_config() return { "environment": config.runtime.environment, "config_hash": config.metadata.config_hash, "loaded_files": list(config.metadata.loaded_files), "deprecated_keys": list(config.metadata.deprecated_keys), } except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/stats") async def get_index_stats(http_request: Request): """ Get index statistics. """ try: from urllib.parse import parse_qs from ..app import get_es_client es_client = get_es_client() tenant_id = http_request.headers.get("X-Tenant-ID") if not tenant_id: query_string = http_request.url.query if query_string: params = parse_qs(query_string) tenant_id = params.get("tenant_id", [None])[0] if not tenant_id: raise HTTPException( status_code=400, detail="tenant_id is required. Provide it via header 'X-Tenant-ID' or query parameter 'tenant_id'", ) index_name = get_tenant_index_name(tenant_id) if not es_client.client.indices.exists(index=index_name): raise HTTPException( status_code=404, detail=f"Tenant index not found: {index_name}", ) # Get document count doc_count = es_client.client.count(index=index_name).get("count", 0) # Get index size (if available) try: stats = es_client.client.indices.stats(index=index_name) size_in_bytes = stats["indices"][index_name]["total"]["store"]["size_in_bytes"] size_mb = size_in_bytes / (1024 * 1024) except Exception: size_mb = None return { "tenant_id": str(tenant_id), "index_name": index_name, "document_count": doc_count, "size_mb": round(size_mb, 2) if size_mb else None } except Exception as e: raise HTTPException(status_code=500, detail=str(e))