from fastapi import APIRouter, Depends, HTTPException, Query, status from typing import Optional from app.core.auth import get_current_active_user, User from app.core.database import get_database from app.services.keyword_service import KeywordService from app.schemas.keyword import ( KeywordCreate, KeywordUpdate, KeywordResponse, KeywordListResponse, KeywordStats ) router = APIRouter() def get_keyword_service(db=Depends(get_database)) -> KeywordService: """Dependency to get keyword service""" return KeywordService(db) @router.get("/", response_model=KeywordListResponse) async def get_keywords( category: Optional[str] = Query(None, description="Filter by category"), status: Optional[str] = Query(None, description="Filter by status (active/inactive)"), search: Optional[str] = Query(None, description="Search in keyword text"), page: int = Query(1, ge=1, description="Page number"), page_size: int = Query(50, ge=1, le=100, description="Items per page"), sort_by: str = Query("created_at", description="Field to sort by"), sort_order: int = Query(-1, ge=-1, le=1, description="1 for ascending, -1 for descending"), current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Get all keywords with filtering, pagination, and sorting""" keywords, total = await keyword_service.get_keywords( category=category, status=status, search=search, page=page, page_size=page_size, sort_by=sort_by, sort_order=sort_order ) # Convert to response models keyword_responses = [ KeywordResponse( _id=str(kw.id), keyword=kw.keyword, category=kw.category, status=kw.status, pipeline_type=kw.pipeline_type, priority=kw.priority, metadata=kw.metadata, created_at=kw.created_at, updated_at=kw.updated_at, created_by=kw.created_by ) for kw in keywords ] return KeywordListResponse( keywords=keyword_responses, total=total, page=page, page_size=page_size ) @router.get("/{keyword_id}", response_model=KeywordResponse) async def get_keyword( keyword_id: str, current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Get a keyword by ID""" keyword = await keyword_service.get_keyword_by_id(keyword_id) if not keyword: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Keyword with ID {keyword_id} not found" ) return KeywordResponse( _id=str(keyword.id), keyword=keyword.keyword, category=keyword.category, status=keyword.status, pipeline_type=keyword.pipeline_type, priority=keyword.priority, metadata=keyword.metadata, created_at=keyword.created_at, updated_at=keyword.updated_at, created_by=keyword.created_by ) @router.post("/", response_model=KeywordResponse, status_code=status.HTTP_201_CREATED) async def create_keyword( keyword_data: KeywordCreate, current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Create new keyword""" keyword = await keyword_service.create_keyword( keyword_data=keyword_data, created_by=current_user.username ) return KeywordResponse( _id=str(keyword.id), keyword=keyword.keyword, category=keyword.category, status=keyword.status, pipeline_type=keyword.pipeline_type, priority=keyword.priority, metadata=keyword.metadata, created_at=keyword.created_at, updated_at=keyword.updated_at, created_by=keyword.created_by ) @router.put("/{keyword_id}", response_model=KeywordResponse) async def update_keyword( keyword_id: str, keyword_data: KeywordUpdate, current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Update keyword""" keyword = await keyword_service.update_keyword(keyword_id, keyword_data) if not keyword: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Keyword with ID {keyword_id} not found" ) return KeywordResponse( _id=str(keyword.id), keyword=keyword.keyword, category=keyword.category, status=keyword.status, pipeline_type=keyword.pipeline_type, priority=keyword.priority, metadata=keyword.metadata, created_at=keyword.created_at, updated_at=keyword.updated_at, created_by=keyword.created_by ) @router.delete("/{keyword_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_keyword( keyword_id: str, current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Delete keyword""" success = await keyword_service.delete_keyword(keyword_id) if not success: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Keyword with ID {keyword_id} not found" ) return None @router.post("/{keyword_id}/toggle", response_model=KeywordResponse) async def toggle_keyword_status( keyword_id: str, current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Toggle keyword status between active and inactive""" keyword = await keyword_service.toggle_keyword_status(keyword_id) if not keyword: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Keyword with ID {keyword_id} not found" ) return KeywordResponse( _id=str(keyword.id), keyword=keyword.keyword, category=keyword.category, status=keyword.status, pipeline_type=keyword.pipeline_type, priority=keyword.priority, metadata=keyword.metadata, created_at=keyword.created_at, updated_at=keyword.updated_at, created_by=keyword.created_by ) @router.get("/{keyword_id}/stats", response_model=KeywordStats) async def get_keyword_stats( keyword_id: str, current_user: User = Depends(get_current_active_user), keyword_service: KeywordService = Depends(get_keyword_service) ): """Get statistics for a keyword""" stats = await keyword_service.get_keyword_stats(keyword_id) if not stats: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Keyword with ID {keyword_id} not found" ) return stats