""" routes/sales.py Dedicated modular APIRouter serving commercial sales records and catalog sales rankings. Completely decoupled from the live 500-cohort telemetry endpoint (/artists). """ import sqlite3 from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, Header, status DB_PATH = "data/hiffi_catalog.db" AUTH_SECRET = "hiffi_live_secret_key_prod_2026" sales_router = APIRouter(prefix="/sales", tags=["Commercial Sales"]) def verify_sales_auth(x_auth_secret: Optional[str] = Header(None)) -> str: """Verifies incoming X-Auth-Secret header for protected sales endpoints.""" if x_auth_secret != AUTH_SECRET: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or missing X-Auth-Secret header" ) return x_auth_secret def get_db(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row try: yield conn finally: conn.close() @sales_router.get("/summary", dependencies=[Depends(verify_sales_auth)]) def get_sales_summary(db: sqlite3.Connection = Depends(get_db)) -> Dict[str, Any]: """Returns aggregate commercial sales totals across all ingested catalog records.""" cur = db.cursor() summary_sql = """ SELECT COUNT(*) as total_catalog_artists, SUM(CASE WHEN audited_sales_units > 0 THEN 1 ELSE 0 END) as commercial_active_artists, COALESCE(SUM(audited_sales_units), 0) as total_audited_units, COALESCE(SUM(pure_album_sales), 0) as total_pure_albums, COALESCE(SUM(digital_singles_sales), 0) as total_digital_singles, COALESCE(SUM(physical_singles_sales), 0) as total_physical_singles, COALESCE(SUM(streaming_eas), 0) as total_streaming_eas, COALESCE(SUM(awards_count), 0) as total_certifications FROM commercial_sales """ row = cur.execute(summary_sql).fetchone() return dict(row) @sales_router.get("/artists", dependencies=[Depends(verify_sales_auth)]) def list_sales_artists( limit: int = Query(50, ge=1, le=500, description="Records per page"), offset: int = Query(0, ge=0, description="Offset for pagination"), search: Optional[str] = Query(None, description="Search artist by name"), provenance: Optional[str] = Query(None, description="Filter by provenance flag"), min_sales: Optional[float] = Query(None, description="Minimum audited sales units"), db: sqlite3.Connection = Depends(get_db) ) -> List[Dict[str, Any]]: """Returns paginated catalog commercial sales rankings ordered strictly by sales_rank.""" cur = db.cursor() base_sql = """ SELECT cs.sales_rank, cs.artist_id, a.artist_name, a.country_origin, a.image_url, cs.audited_sales_units, cs.pure_album_sales, cs.digital_singles_sales, cs.physical_singles_sales, cs.streaming_eas, cs.awards_count, cs.provenance_flag FROM commercial_sales cs JOIN artists a ON cs.artist_id = a.artist_id WHERE 1=1 """ params = [] if search: base_sql += " AND a.artist_name LIKE ?" params.append(f"%{search}%") if provenance: base_sql += " AND cs.provenance_flag = ?" params.append(provenance) if min_sales is not None: base_sql += " AND cs.audited_sales_units >= ?" params.append(min_sales) base_sql += " ORDER BY cs.sales_rank ASC LIMIT ? OFFSET ?" params.extend([limit, offset]) rows = cur.execute(base_sql, params).fetchall() return [dict(r) for r in rows] @sales_router.get("/artists/{artist_id}", dependencies=[Depends(verify_sales_auth)]) def get_artist_sales_dossier( artist_id: str, db: sqlite3.Connection = Depends(get_db) ) -> Dict[str, Any]: """Returns commercial sales dossier for a single catalog artist.""" cur = db.cursor() sql = """ SELECT cs.sales_rank, cs.artist_id, a.artist_name, a.country_origin, a.image_url, a.youtube_url, a.spotify_url, a.instagram_url, cs.audited_sales_units, cs.pure_album_sales, cs.digital_singles_sales, cs.physical_singles_sales, cs.streaming_eas, cs.awards_count, cs.provenance_flag FROM commercial_sales cs JOIN artists a ON cs.artist_id = a.artist_id WHERE cs.artist_id = ? """ row = cur.execute(sql, (artist_id,)).fetchone() if not row: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Commercial sales record for artist ID '{artist_id}' not found." ) return dict(row)