from fastapi import APIRouter, HTTPException, Query from datetime import date, datetime, timedelta from typing import Optional from loguru import logger from backend.services.registration_analytics_service import RegistrationService from backend.models.user_registration_models import UserRegistrationResponse, UserRegistrationQuery router = APIRouter(prefix="/api/metrics", tags=["registration"]) # Initialize service registration_service = RegistrationService() @router.get("/daily-registered-users", response_model=UserRegistrationResponse) async def get_daily_registered_users( start_date: date = Query(..., description="Start date in YYYY-MM-DD format"), end_date: date = Query(..., description="End date in YYYY-MM-DD format"), product_id: str = Query("freeleaps", description="Product identifier") ): """ Get daily registered users count for a date range Returns two lists: - dates: List of dates in YYYY-MM-DD format - counts: List of daily registration counts Example: - GET /api/metrics/daily-registered-users?start_date=2024-01-01&end_date=2024-01-07 """ try: # Validate date range if start_date > end_date: raise HTTPException( status_code=400, detail="Start date must be before or equal to end date" ) # Check date range is not too large (max 1 year) if (end_date - start_date).days > 365: raise HTTPException( status_code=400, detail="Date range cannot exceed 365 days" ) logger.info(f"Querying registration data from {start_date} to {end_date} for product {product_id}") # Get data from service result = registration_service.get_daily_registered_users( start_date, end_date, product_id ) logger.info(f"Successfully retrieved data for {len(result.dates)} days") return result except HTTPException: raise except Exception as e: logger.error(f"Failed to get daily registered users: {e}") raise HTTPException( status_code=500, detail=f"Internal server error: {str(e)}" ) @router.get("/registration-summary") async def get_registration_summary( start_date: date = Query(..., description="Start date in YYYY-MM-DD format"), end_date: date = Query(..., description="End date in YYYY-MM-DD format"), product_id: str = Query("freeleaps", description="Product identifier") ): """ Get summary statistics for user registrations in a date range Returns summary statistics including: - total_registrations: Total number of registrations - average_daily: Average daily registrations - max_daily: Maximum daily registrations - min_daily: Minimum daily registrations - days_with_registrations: Number of days with registrations - total_days: Total number of days in range """ try: # Validate date range if start_date > end_date: raise HTTPException( status_code=400, detail="Start date must be before or equal to end date" ) if (end_date - start_date).days > 365: raise HTTPException( status_code=400, detail="Date range cannot exceed 365 days" ) logger.info(f"Querying registration summary from {start_date} to {end_date} for product {product_id}") # Get summary from service summary = registration_service.get_registration_summary( start_date, end_date, product_id ) return summary except HTTPException: raise except Exception as e: logger.error(f"Failed to get registration summary: {e}") raise HTTPException( status_code=500, detail=f"Internal server error: {str(e)}" ) @router.get("/recent-registered-users", response_model=UserRegistrationResponse) async def get_recent_registered_users( days: int = Query(7, ge=1, le=365, description="Number of recent days to query"), product_id: str = Query("freeleaps", description="Product identifier") ): """ Get daily registered users count for recent N days Returns registration data for the last N days from today Example: - GET /api/metrics/recent-registered-users?days=7 - GET /api/metrics/recent-registered-users?days=30&product_id=freeleaps """ try: # Calculate date range end_date = date.today() start_date = end_date - timedelta(days=days-1) logger.info(f"Querying recent {days} days registration data from {start_date} to {end_date} for product {product_id}") # Get data from service result = registration_service.get_daily_registered_users( start_date, end_date, product_id ) logger.info(f"Successfully retrieved recent {days} days data, total registrations: {result.total_registrations}") return result except Exception as e: logger.error(f"Failed to get recent registered users: {e}") raise HTTPException( status_code=500, detail=f"Internal server error: {str(e)}" ) @router.get("/registered-users-by-days", response_model=UserRegistrationResponse) async def get_registered_users_by_days( start_date: date = Query(..., description="Start date in YYYY-MM-DD format"), days: int = Query(..., ge=1, le=365, description="Number of days from start date"), product_id: str = Query("freeleaps", description="Product identifier") ): """ Get daily registered users count starting from a specific date for N days Returns registration data for N days starting from the specified start date Example: - GET /api/metrics/registered-users-by-days?start_date=2024-01-01&days=7 - GET /api/metrics/registered-users-by-days?start_date=2024-09-01&days=30&product_id=freeleaps """ try: # Calculate end date end_date = start_date + timedelta(days=days-1) logger.info(f"Querying registration data from {start_date} for {days} days (until {end_date}) for product {product_id}") # Get data from service result = registration_service.get_daily_registered_users( start_date, end_date, product_id ) logger.info(f"Successfully retrieved {days} days data from {start_date}, total registrations: {result.total_registrations}") return result except Exception as e: logger.error(f"Failed to get registered users by days: {e}") raise HTTPException( status_code=500, detail=f"Internal server error: {str(e)}" ) @router.post("/daily-registered-users", response_model=UserRegistrationResponse) async def get_daily_registered_users_post( query: UserRegistrationQuery ): """ Get daily registered users count for a date range (POST method) Same as GET method but accepts parameters in request body """ try: # Validate date range if query.start_date > query.end_date: raise HTTPException( status_code=400, detail="Start date must be before or equal to end date" ) if (query.end_date - query.start_date).days > 365: raise HTTPException( status_code=400, detail="Date range cannot exceed 365 days" ) logger.info(f"Querying registration data from {query.start_date} to {query.end_date} for product {query.product_id}") # Get data from service result = registration_service.get_daily_registered_users( query.start_date, query.end_date, query.product_id ) logger.info(f"Successfully retrieved data for {len(result.dates)} days") return result except HTTPException: raise except Exception as e: logger.error(f"Failed to get daily registered users: {e}") raise HTTPException( status_code=500, detail=f"Internal server error: {str(e)}" )