"""Missing locations API endpoints""" from fastapi import APIRouter, Query, HTTPException from typing import Optional from app.core.database import init_db, pool as db_pool router = APIRouter() @router.get("") async def get_missing_locations( source_kind: Optional[str] = Query(None, description="Filter by source: radarr, sonarr, lidarr"), media_type: Optional[str] = Query(None, description="Filter by media type: movie, show, music"), limit: int = Query(100, ge=1, le=1000, description="Maximum number of items to return"), offset: int = Query(0, ge=0, description="Number of items to skip") ): """ Get list of media items without country metadata. Returns paginated list of media items that don't have any country associations. """ await init_db() if db_pool is None: raise HTTPException(status_code=503, detail="Database not available") async with db_pool.connection() as conn: async with conn.cursor() as cur: # Build query where_clauses = ["mc.media_item_id IS NULL"] params = [] if source_kind: where_clauses.append("mi.source_kind = %s") params.append(source_kind) if media_type: where_clauses.append("mi.media_type = %s") params.append(media_type) where_clause = " AND ".join(where_clauses) # Get total count count_query = f""" SELECT COUNT(DISTINCT mi.id) FROM moviemap.media_item mi LEFT JOIN moviemap.media_country mc ON mi.id = mc.media_item_id WHERE {where_clause} """ await cur.execute(count_query, params) total_count = (await cur.fetchone())[0] # Get items query = f""" SELECT mi.id, mi.source_kind, mi.source_item_id, mi.title, mi.year, mi.media_type FROM moviemap.media_item mi LEFT JOIN moviemap.media_country mc ON mi.id = mc.media_item_id WHERE {where_clause} ORDER BY mi.title LIMIT %s OFFSET %s """ params.extend([limit, offset]) await cur.execute(query, params) rows = await cur.fetchall() items = [] for row in rows: items.append({ "id": str(row[0]), "source_kind": row[1], "source_item_id": row[2], "title": row[3], "year": row[4], "media_type": row[5], }) return { "total": total_count, "returned": len(items), "offset": offset, "limit": limit, "items": items }