from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from sqlalchemy.sql import func from pydantic import BaseModel from database import get_db from auth import get_current_active_user from models import User, SavedSearch router = APIRouter(prefix="/searches", tags=["Saved Searches"]) class SavedSearchCreate(BaseModel): name: str query: str filters: Optional[dict] = None results_count: Optional[int] = 0 class SavedSearchUpdate(BaseModel): name: Optional[str] = None filters: Optional[dict] = None results_count: Optional[int] = None class SavedSearchResponse(BaseModel): id: int name: str query: str filters: Optional[dict] results_count: int last_used: str class Config: from_attributes = True @router.get("/", response_model=List[SavedSearchResponse]) def get_saved_searches( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get all saved searches for the current user""" searches = db.query(SavedSearch).filter( SavedSearch.user_id == current_user.id ).order_by(SavedSearch.last_used.desc()).all() return [ SavedSearchResponse( id=s.id, name=s.name, query=s.query, filters=s.filters, results_count=s.results_count, last_used=s.last_used.isoformat() if s.last_used else "" ) for s in searches ] @router.post("/", response_model=SavedSearchResponse, status_code=status.HTTP_201_CREATED) def create_saved_search( search_data: SavedSearchCreate, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Create a new saved search""" search = SavedSearch( user_id=current_user.id, name=search_data.name, query=search_data.query, filters=search_data.filters, results_count=search_data.results_count ) db.add(search) db.commit() db.refresh(search) return SavedSearchResponse( id=search.id, name=search.name, query=search.query, filters=search.filters, results_count=search.results_count, last_used=search.last_used.isoformat() if search.last_used else "" ) @router.get("/{search_id}", response_model=SavedSearchResponse) def get_saved_search( search_id: int, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get a specific saved search""" search = db.query(SavedSearch).filter( SavedSearch.id == search_id, SavedSearch.user_id == current_user.id ).first() if not search: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Saved search not found" ) return SavedSearchResponse( id=search.id, name=search.name, query=search.query, filters=search.filters, results_count=search.results_count, last_used=search.last_used.isoformat() if search.last_used else "" ) @router.put("/{search_id}", response_model=SavedSearchResponse) def update_saved_search( search_id: int, search_update: SavedSearchUpdate, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Update a saved search""" search = db.query(SavedSearch).filter( SavedSearch.id == search_id, SavedSearch.user_id == current_user.id ).first() if not search: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Saved search not found" ) update_data = search_update.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(search, field, value) db.commit() db.refresh(search) return SavedSearchResponse( id=search.id, name=search.name, query=search.query, filters=search.filters, results_count=search.results_count, last_used=search.last_used.isoformat() if search.last_used else "" ) @router.post("/{search_id}/use") def mark_search_used( search_id: int, results_count: Optional[int] = None, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Mark a saved search as used (updates last_used timestamp)""" search = db.query(SavedSearch).filter( SavedSearch.id == search_id, SavedSearch.user_id == current_user.id ).first() if not search: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Saved search not found" ) search.last_used = func.now() if results_count is not None: search.results_count = results_count db.commit() return {"message": "Search marked as used"} @router.delete("/{search_id}") def delete_saved_search( search_id: int, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Delete a saved search""" search = db.query(SavedSearch).filter( SavedSearch.id == search_id, SavedSearch.user_id == current_user.id ).first() if not search: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Saved search not found" ) db.delete(search) db.commit() return {"message": "Saved search deleted"}