from fastapi import APIRouter, Depends, HTTPException from sqlmodel import Session, select from typing import List from database import get_session from models import User, Vertical, UserVerticalPreference from auth import get_current_user from pydantic import BaseModel from datetime import datetime router = APIRouter(prefix="/verticals", tags=["verticals"]) class VerticalRead(BaseModel): id: int name: str slug: str description: str | None = None class UserVerticalPreferenceRead(BaseModel): vertical_id: int vertical: VerticalRead display_mode: str priority: int notify_on_show: bool class UserVerticalPreferenceCreate(BaseModel): vertical_id: int display_mode: str = "primary" # primary, secondary, attribution_only, hidden priority: int = 0 notify_on_show: bool = True class UserVerticalPreferenceUpdate(BaseModel): display_mode: str | None = None priority: int | None = None notify_on_show: bool | None = None class BulkVerticalPreferencesCreate(BaseModel): """For onboarding - set multiple band preferences at once""" vertical_ids: List[int] display_mode: str = "primary" # --- Public endpoints --- @router.get("/", response_model=List[VerticalRead]) def list_verticals(session: Session = Depends(get_session)): """List all available verticals (bands)""" verticals = session.exec(select(Vertical)).all() return verticals @router.get("/{slug}", response_model=VerticalRead) def get_vertical(slug: str, session: Session = Depends(get_session)): """Get a specific vertical by slug""" vertical = session.exec(select(Vertical).where(Vertical.slug == slug)).first() if not vertical: raise HTTPException(status_code=404, detail="Vertical not found") return vertical # --- User preference endpoints --- @router.get("/preferences/me", response_model=List[UserVerticalPreferenceRead]) def get_my_vertical_preferences( session: Session = Depends(get_session), current_user: User = Depends(get_current_user) ): """Get current user's band preferences""" prefs = session.exec( select(UserVerticalPreference) .where(UserVerticalPreference.user_id == current_user.id) .order_by(UserVerticalPreference.priority) ).all() # Enrich with vertical data result = [] for pref in prefs: vertical = session.get(Vertical, pref.vertical_id) if vertical: result.append({ "vertical_id": pref.vertical_id, "vertical": vertical, "display_mode": pref.display_mode, "priority": pref.priority, "notify_on_show": pref.notify_on_show }) return result @router.post("/preferences", response_model=UserVerticalPreferenceRead) def add_vertical_preference( pref: UserVerticalPreferenceCreate, session: Session = Depends(get_session), current_user: User = Depends(get_current_user) ): """Add a band to user's preferences""" # Check vertical exists vertical = session.get(Vertical, pref.vertical_id) if not vertical: raise HTTPException(status_code=404, detail="Vertical not found") # Check if already exists existing = session.exec( select(UserVerticalPreference) .where(UserVerticalPreference.user_id == current_user.id) .where(UserVerticalPreference.vertical_id == pref.vertical_id) ).first() if existing: raise HTTPException(status_code=400, detail="Preference already exists") db_pref = UserVerticalPreference( user_id=current_user.id, vertical_id=pref.vertical_id, display_mode=pref.display_mode, priority=pref.priority, notify_on_show=pref.notify_on_show ) session.add(db_pref) session.commit() session.refresh(db_pref) return { "vertical_id": db_pref.vertical_id, "vertical": vertical, "display_mode": db_pref.display_mode, "priority": db_pref.priority, "notify_on_show": db_pref.notify_on_show } @router.post("/preferences/bulk", response_model=List[UserVerticalPreferenceRead]) def set_vertical_preferences_bulk( data: BulkVerticalPreferencesCreate, session: Session = Depends(get_session), current_user: User = Depends(get_current_user) ): """Set multiple band preferences at once (for onboarding)""" result = [] for idx, vid in enumerate(data.vertical_ids): vertical = session.get(Vertical, vid) if not vertical: continue # Upsert existing = session.exec( select(UserVerticalPreference) .where(UserVerticalPreference.user_id == current_user.id) .where(UserVerticalPreference.vertical_id == vid) ).first() if existing: existing.display_mode = data.display_mode existing.priority = idx session.add(existing) pref = existing else: pref = UserVerticalPreference( user_id=current_user.id, vertical_id=vid, display_mode=data.display_mode, priority=idx, notify_on_show=True ) session.add(pref) result.append({ "vertical_id": vid, "vertical": vertical, "display_mode": data.display_mode, "priority": idx, "notify_on_show": True }) session.commit() return result @router.put("/preferences/{vertical_id}", response_model=UserVerticalPreferenceRead) def update_vertical_preference( vertical_id: int, data: UserVerticalPreferenceUpdate, session: Session = Depends(get_session), current_user: User = Depends(get_current_user) ): """Update a specific band preference""" pref = session.exec( select(UserVerticalPreference) .where(UserVerticalPreference.user_id == current_user.id) .where(UserVerticalPreference.vertical_id == vertical_id) ).first() if not pref: raise HTTPException(status_code=404, detail="Preference not found") vertical = session.get(Vertical, vertical_id) update_data = data.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(pref, key, value) session.add(pref) session.commit() session.refresh(pref) return { "vertical_id": pref.vertical_id, "vertical": vertical, "display_mode": pref.display_mode, "priority": pref.priority, "notify_on_show": pref.notify_on_show } @router.delete("/preferences/{vertical_id}") def delete_vertical_preference( vertical_id: int, session: Session = Depends(get_session), current_user: User = Depends(get_current_user) ): """Remove a band from user's preferences""" pref = session.exec( select(UserVerticalPreference) .where(UserVerticalPreference.user_id == current_user.id) .where(UserVerticalPreference.vertical_id == vertical_id) ).first() if not pref: raise HTTPException(status_code=404, detail="Preference not found") session.delete(pref) session.commit() return {"ok": True}