"""API routes for fraud detection.""" import logging from typing import Dict, List from fastapi import APIRouter, HTTPException, status from src.schemas.fraud import ( FraudAnalysisRequest, FraudAnalysisResponse, TransactionSummary, ) from src.services.fraud_analyzer import FraudAnalyzer logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/v1", tags=["fraud"]) # Initialize services (in production, use dependency injection) fraud_analyzer = FraudAnalyzer() @router.get("/health", summary="Health check") async def health_check() -> Dict[str, str]: """Health check endpoint.""" return {"status": "healthy", "service": "fraud-detection-api"} @router.post( "/analyze", response_model=FraudAnalysisResponse, status_code=status.HTTP_200_OK, summary="Analyze transaction for fraud", ) async def analyze_transaction(request: FraudAnalysisRequest) -> FraudAnalysisResponse: """Analyze a transaction for fraud indicators. Args: request: Fraud analysis request. Returns: Fraud analysis response with detailed assessment. """ try: if not request.transaction_id and not request.transaction_data: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Either transaction_id or transaction_data must be provided", ) result = fraud_analyzer.analyze_transaction( transaction_id=request.transaction_id, transaction_data=request.transaction_data.dict() if request.transaction_data else None, use_rag=request.use_rag, ) return FraudAnalysisResponse(**result) except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e), ) except Exception as e: logger.error(f"Error analyzing transaction: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Internal server error: {str(e)}", ) @router.get( "/summary", response_model=TransactionSummary, summary="Get transaction summary", ) async def get_summary() -> TransactionSummary: """Get summary statistics of the fraud dataset. Returns: Transaction summary with statistics. """ try: summary = fraud_analyzer.data_processor.get_transaction_summary() return TransactionSummary(**summary) except Exception as e: logger.error(f"Error getting summary: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Internal server error: {str(e)}", ) @router.post( "/batch-analyze", response_model=List[FraudAnalysisResponse], summary="Batch analyze multiple transactions", ) async def batch_analyze( transaction_ids: List[int], use_rag: bool = True, ) -> List[FraudAnalysisResponse]: """Analyze multiple transactions in batch. Args: transaction_ids: List of transaction IDs to analyze. use_rag: Whether to use RAG for context. Returns: List of fraud analysis responses. """ try: if not transaction_ids: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="At least one transaction_id must be provided", ) results = fraud_analyzer.batch_analyze(transaction_ids, use_rag=use_rag) return [FraudAnalysisResponse(**result) for result in results] except Exception as e: logger.error(f"Error in batch analysis: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Internal server error: {str(e)}", )