from fastapi import APIRouter, BackgroundTasks, Depends, Form, Request from fastapi.responses import RedirectResponse from fastapi.templating import Jinja2Templates from sqlalchemy import select from app.db import get_db from app.models import GenreCandidate, GenreRun from app.security.deps import require_auth from app.services import genre_review_service router = APIRouter(prefix="/genres", tags=["genres"]) templates = Jinja2Templates(directory="app/templates") @router.get("") async def genres_index(request: Request, user: dict = Depends(require_auth), db=Depends(get_db)): latest_run = db.execute(select(GenreRun).order_by(GenreRun.id.desc())).scalars().first() candidates = [] if latest_run is not None: candidates = list( db.execute( select(GenreCandidate).where(GenreCandidate.genre_run_id == latest_run.id) ).scalars() ) return templates.TemplateResponse( request, "genres/index.html", {"latest_run": latest_run, "candidates": candidates} ) @router.post("/scan") async def scan(background: BackgroundTasks, user: dict = Depends(require_auth)): # Always force=True: matches the weekly scheduled run's own behavior # (see genre_review_service.run's docstring), so a preview accurately # shows what "Fix genres now" would actually do. Runs in the background; # the last-run table below fills in when it finishes. background.add_task(genre_review_service.run, apply=False, force=True, triggered_by="manual") return RedirectResponse(url="/genres?started=1", status_code=303) @router.post("/apply") async def apply(background: BackgroundTasks, user: dict = Depends(require_auth)): background.add_task(genre_review_service.run, apply=True, force=True, triggered_by="manual") return RedirectResponse(url="/genres?started=1", status_code=303) @router.post("/lock") async def lock( artist: str = Form(...), genre: str = Form(...), user: dict = Depends(require_auth), ): changed_by = user.get("email") or user.get("sub", "unknown") await genre_review_service.lock_artist_genre(artist, genre, changed_by) return RedirectResponse(url="/genres", status_code=303)