"""This module defines the /summary route for the Flask application.""" import importlib from venv import logger import re from fastapi import APIRouter, HTTPException, Path from fastapi.responses import JSONResponse from controllers.summary import get_summary_data # pylint: disable=import-error from models.database import knowledge_base # pylint: disable=import-error router = APIRouter(prefix="/summary", tags=["summary"]) @router.get("/{email}") async def get_user_document_stats( email: str = Path(..., description="User's email address") ) -> JSONResponse: """ Get document statistics for a specific user. This endpoint counts the number of unique emails and files uploaded by the user. It groups documents by metadata.id to ensure unique document counting (not chunks). Args: email (str): The user's email address Returns: JSONResponse: A JSON response containing document counts: { "email": "user@example.com", "emails": 5, "files": 12, "total_documents": 17 } Raises: HTTPException: 400 for invalid email, 500 for database errors """ try: email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' if not email or not re.match(email_pattern, email): raise HTTPException( status_code=400, detail="Invalid email format. Must be a valid email address." ) # Get document counts from database result = knowledge_base.get_doc_count(email) # Add email to response result["email"] = email return JSONResponse(content=result, status_code=200) except ValueError as e: logger.error("Validation error for user %s: %s", email, str(e)) raise HTTPException(status_code=400, detail=str(e)) # pylint: disable=raise-missing-from except Exception as e: # pylint: disable=broad-exception-caught logger.error("Database error for user %s: %s", email, str(e)) raise HTTPException( # pylint: disable=raise-missing-from status_code=500, detail="Internal server error while retrieving document statistics." ) @router.get('') async def get_summary() -> JSONResponse: """ Generate a summary dashboard with content flow and entity analysis data. This endpoint provides a complete summary overview, including: - Content Flow Tracker: Article counts by source and category - Entity Analysis: Top entities by type with mentions All data is returned together, divided into three time periods: today, week, and month. Returns: JSONResponse: A JSON response containing the complete summary dashboard data: { "content": {"today": {...}, "week": {...}, "month": {...}}, "entity": {"today": {...}, "week": {...}, "month": {...}} } """ try: summary_data = get_summary_data() return JSONResponse(content=summary_data) except Exception as e: #pylint: disable=broad-except return JSONResponse(content={"error": str(e)}, status_code=500) @router.get("/{module}/{chart_id}") def get_summary_chart(module: str, chart_id: str) -> JSONResponse: """ Handles GET requests to the summary route with a specific module and chart ID. Args: module (str): The module identifier (content or entity). chart_id (str): The chart identifier (today, weekly, monthly). Returns: tuple: The result of the chart's process function and HTTP status code 200. Raises: ImportError: If the specified chart module cannot be imported. AttributeError: If the imported module does not have a 'process' function. Endpoint: GET // """ try: result = importlib.import_module(f"controllers.summary.{module}.{chart_id}").process() return JSONResponse(content=result) except ImportError as e: return JSONResponse(content={"error": str(e)}, status_code=404) except AttributeError as e: return JSONResponse(content={"error": str(e)}, status_code=500) @router.get("/{module}") async def get_summary_module(module: str) -> JSONResponse: """ Handles GET requests to the summary route for a specific module. Triggers the process for each chart under this module concurrently. Args: module (str): The module identifier (content or entity). Returns: dict: {"module": module, "charts": [chart1, chart2, ...]} """ try: result = importlib.import_module("controllers.summary").process(module) return JSONResponse(content=result) except ImportError as e: return JSONResponse(content={"error": str(e)}, status_code=404) except Exception as e: #pylint: disable=broad-except return JSONResponse(content={"error": str(e)}, status_code=500) # @router.get("/{email}") # async def get_user_document_stats( # email: str = Path(..., description="User's email address") # ) -> JSONResponse: # """ # Get document statistics for a specific user. # This endpoint counts the number of unique emails and files uploaded by the user. # It groups documents by metadata.id to ensure unique document counting (not chunks). # Args: # email (str): The user's email address # Returns: # JSONResponse: A JSON response containing document counts: # { # "email": "user@example.com", # "emails": 5, # "files": 12, # "total_documents": 17 # } # Raises: # HTTPException: 400 for invalid email, 500 for database errors # """ # try: # email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' # if not email or not re.match(email_pattern, email): # raise HTTPException( # status_code=400, # detail="Invalid email format. Must be a valid email address." # ) # # Get document counts from database # result = knowledge_base.get_doc_count(email) # # Add email to response # result["email"] = email # return JSONResponse(content=result, status_code=200) # except ValueError as e: # logger.error("Validation error for user %s: %s", email, str(e)) # raise HTTPException(status_code=400, detail=str(e)) # pylint: disable=raise-missing-from # except Exception as e: # pylint: disable=broad-exception-caught # logger.error("Database error for user %s: %s", email, str(e)) # raise HTTPException( # pylint: disable=raise-missing-from # status_code=500, # detail="Internal server error while retrieving document statistics." # )