""" Watchlist API Endpoints """ from typing import List, Optional from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.core.database import get_db from app.models.watchlist import Watchlist from app.models.stock import Stock from app.schemas.watchlist import WatchlistResponse, WatchlistCreate, WatchlistUpdate router = APIRouter() @router.get("/", response_model=List[WatchlistResponse]) async def list_watchlist( db: AsyncSession = Depends(get_db), priority: Optional[int] = Query(None, ge=1, le=3, description="Filter by priority"), ): """Get all items in watchlist.""" query = select(Watchlist).where(Watchlist.is_active == True) if priority: query = query.where(Watchlist.priority == priority) query = query.order_by(Watchlist.priority) result = await db.execute(query) return result.scalars().all() @router.post("/", response_model=WatchlistResponse) async def add_to_watchlist( item: WatchlistCreate, db: AsyncSession = Depends(get_db), ): """Add a stock to the watchlist.""" # Find the stock stock_query = select(Stock).where(Stock.symbol == item.symbol.upper()) stock_result = await db.execute(stock_query) stock = stock_result.scalar_one_or_none() if not stock: raise HTTPException(status_code=404, detail=f"Stock {item.symbol} not found") # Check if already in watchlist existing = await db.execute( select(Watchlist).where(Watchlist.stock_id == stock.id) ) if existing.scalar_one_or_none(): raise HTTPException( status_code=400, detail=f"Stock {item.symbol} is already in watchlist" ) watchlist_item = Watchlist( stock_id=stock.id, panic_alert_threshold=item.panic_alert_threshold, price_alert_low=item.price_alert_low, price_alert_high=item.price_alert_high, priority=item.priority, notes=item.notes, ) db.add(watchlist_item) await db.commit() await db.refresh(watchlist_item) return watchlist_item @router.put("/{watchlist_id}", response_model=WatchlistResponse) async def update_watchlist_item( watchlist_id: UUID, update: WatchlistUpdate, db: AsyncSession = Depends(get_db), ): """Update a watchlist item.""" query = select(Watchlist).where(Watchlist.id == watchlist_id) result = await db.execute(query) item = result.scalar_one_or_none() if not item: raise HTTPException(status_code=404, detail="Watchlist item not found") update_data = update.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(item, key, value) await db.commit() await db.refresh(item) return item @router.delete("/{watchlist_id}") async def remove_from_watchlist( watchlist_id: UUID, db: AsyncSession = Depends(get_db), ): """Remove a stock from the watchlist.""" query = select(Watchlist).where(Watchlist.id == watchlist_id) result = await db.execute(query) item = result.scalar_one_or_none() if not item: raise HTTPException(status_code=404, detail="Watchlist item not found") await db.delete(item) await db.commit() return {"message": "Removed from watchlist"} @router.delete("/symbol/{symbol}") async def remove_symbol_from_watchlist( symbol: str, db: AsyncSession = Depends(get_db), ): """Remove a stock from watchlist by symbol.""" # Find the stock stock_query = select(Stock).where(Stock.symbol == symbol.upper()) stock_result = await db.execute(stock_query) stock = stock_result.scalar_one_or_none() if not stock: raise HTTPException(status_code=404, detail=f"Stock {symbol} not found") # Find and remove watchlist item watchlist_query = select(Watchlist).where(Watchlist.stock_id == stock.id) watchlist_result = await db.execute(watchlist_query) item = watchlist_result.scalar_one_or_none() if not item: raise HTTPException( status_code=404, detail=f"Stock {symbol} is not in watchlist" ) await db.delete(item) await db.commit() return {"message": f"Removed {symbol} from watchlist"}