""" Search routes for the sim-search API. This module defines the routes for search execution and history. """ from typing import Any, List from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from app.api.dependencies import get_current_active_user from app.db.models import User, Search from app.db.session import get_db from app.schemas.search import SearchExecute, SearchResults, SearchHistory, SearchHistoryList from app.services.search_service import SearchService router = APIRouter() search_service = SearchService() @router.post("/execute", response_model=SearchResults) async def execute_search( search_in: SearchExecute, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db), ) -> Any: """ Execute a search with the given parameters. Args: search_in: Search parameters current_user: Current authenticated user db: Database session Returns: Search results """ try: # Get the structured query from the input structured_query = search_in.structured_query.model_dump() if search_in.structured_query else {} # Print for debugging print(f"Executing search with structured_query: {structured_query}") # Call the search service search_results = await search_service.execute_search( structured_query=structured_query, # Explicitly use keyword argument search_engines=search_in.search_engines, num_results=search_in.num_results, timeout=search_in.timeout, user_id=current_user.id, db=db, ) return search_results except Exception as e: import traceback traceback.print_exc() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error executing search: {str(e)}", ) @router.get("/engines", response_model=List[str]) async def get_available_search_engines( current_user: User = Depends(get_current_active_user), ) -> Any: """ Get a list of available search engines. Args: current_user: Current authenticated user Returns: List of available search engine names """ try: engines = await search_service.get_available_search_engines() return engines except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error getting available search engines: {str(e)}", ) @router.get("/history", response_model=SearchHistoryList) async def get_search_history( skip: int = 0, limit: int = 100, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db), ) -> Any: """ Get the user's search history. Args: skip: Number of records to skip limit: Maximum number of records to return current_user: Current authenticated user db: Database session Returns: List of search history records """ searches = db.query(Search).filter(Search.user_id == current_user.id).order_by( Search.created_at.desc() ).offset(skip).limit(limit).all() total = db.query(Search).filter(Search.user_id == current_user.id).count() return {"searches": searches, "total": total} @router.get("/{search_id}", response_model=SearchResults) async def get_search_results( search_id: str, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db), ) -> Any: """ Get results for a specific search. Args: search_id: ID of the search current_user: Current authenticated user db: Database session Returns: Search results Raises: HTTPException: If the search is not found or doesn't belong to the user """ search = db.query(Search).filter( Search.id == search_id, Search.user_id == current_user.id ).first() if not search: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Search not found", ) return await search_service.get_search_results(search) @router.delete("/{search_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_search( search_id: str, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db), ) -> None: """ Delete a search from history. Args: search_id: ID of the search to delete current_user: Current authenticated user db: Database session Raises: HTTPException: If the search is not found or doesn't belong to the user """ search = db.query(Search).filter( Search.id == search_id, Search.user_id == current_user.id ).first() if not search: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Search not found", ) db.delete(search) db.commit()