from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from pydantic import BaseModel from database import get_db from auth import get_current_active_user from models import User, PriceAlert router = APIRouter(prefix="/alerts", tags=["Price Alerts"]) class AlertCreate(BaseModel): product_name: str dispensary_id: Optional[int] = None dispensary_name: Optional[str] = None target_price: float current_price: Optional[float] = None class AlertUpdate(BaseModel): target_price: Optional[float] = None is_active: Optional[bool] = None class AlertResponse(BaseModel): id: int product_name: str dispensary_id: Optional[int] dispensary_name: Optional[str] target_price: float current_price: Optional[float] is_active: bool is_triggered: bool created_at: str class Config: from_attributes = True @router.get("/", response_model=List[AlertResponse]) def get_alerts( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get all price alerts for the current user""" alerts = db.query(PriceAlert).filter( PriceAlert.user_id == current_user.id ).order_by(PriceAlert.created_at.desc()).all() return [ AlertResponse( id=a.id, product_name=a.product_name, dispensary_id=a.dispensary_id, dispensary_name=a.dispensary_name, target_price=a.target_price, current_price=a.current_price, is_active=a.is_active, is_triggered=a.is_triggered, created_at=a.created_at.isoformat() if a.created_at else "" ) for a in alerts ] @router.post("/", response_model=AlertResponse, status_code=status.HTTP_201_CREATED) def create_alert( alert_data: AlertCreate, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Create a new price alert""" alert = PriceAlert( user_id=current_user.id, product_name=alert_data.product_name, dispensary_id=alert_data.dispensary_id, dispensary_name=alert_data.dispensary_name, target_price=alert_data.target_price, current_price=alert_data.current_price, is_triggered=alert_data.current_price and alert_data.current_price <= alert_data.target_price ) db.add(alert) db.commit() db.refresh(alert) return AlertResponse( id=alert.id, product_name=alert.product_name, dispensary_id=alert.dispensary_id, dispensary_name=alert.dispensary_name, target_price=alert.target_price, current_price=alert.current_price, is_active=alert.is_active, is_triggered=alert.is_triggered, created_at=alert.created_at.isoformat() if alert.created_at else "" ) @router.get("/{alert_id}", response_model=AlertResponse) def get_alert( alert_id: int, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get a specific price alert""" alert = db.query(PriceAlert).filter( PriceAlert.id == alert_id, PriceAlert.user_id == current_user.id ).first() if not alert: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found" ) return AlertResponse( id=alert.id, product_name=alert.product_name, dispensary_id=alert.dispensary_id, dispensary_name=alert.dispensary_name, target_price=alert.target_price, current_price=alert.current_price, is_active=alert.is_active, is_triggered=alert.is_triggered, created_at=alert.created_at.isoformat() if alert.created_at else "" ) @router.put("/{alert_id}", response_model=AlertResponse) def update_alert( alert_id: int, alert_update: AlertUpdate, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Update a price alert""" alert = db.query(PriceAlert).filter( PriceAlert.id == alert_id, PriceAlert.user_id == current_user.id ).first() if not alert: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found" ) update_data = alert_update.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(alert, field, value) # Check if alert should be triggered if alert.current_price and alert.current_price <= alert.target_price: alert.is_triggered = True db.commit() db.refresh(alert) return AlertResponse( id=alert.id, product_name=alert.product_name, dispensary_id=alert.dispensary_id, dispensary_name=alert.dispensary_name, target_price=alert.target_price, current_price=alert.current_price, is_active=alert.is_active, is_triggered=alert.is_triggered, created_at=alert.created_at.isoformat() if alert.created_at else "" ) @router.patch("/{alert_id}/toggle") def toggle_alert( alert_id: int, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Toggle alert active status""" alert = db.query(PriceAlert).filter( PriceAlert.id == alert_id, PriceAlert.user_id == current_user.id ).first() if not alert: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found" ) alert.is_active = not alert.is_active db.commit() return {"message": f"Alert {'activated' if alert.is_active else 'deactivated'}"} @router.delete("/{alert_id}") def delete_alert( alert_id: int, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Delete a price alert""" alert = db.query(PriceAlert).filter( PriceAlert.id == alert_id, PriceAlert.user_id == current_user.id ).first() if not alert: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found" ) db.delete(alert) db.commit() return {"message": "Alert deleted"} @router.get("/stats/summary") def get_alert_stats( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get alert statistics for dashboard""" alerts = db.query(PriceAlert).filter( PriceAlert.user_id == current_user.id ).all() return { "total": len(alerts), "active": len([a for a in alerts if a.is_active]), "triggered": len([a for a in alerts if a.is_triggered]), }