from fastapi import APIRouter, Depends, HTTPException, UploadFile, File from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func, delete from app.core.database import get_db from app.core.deps import get_approved_user from app.models.user import User from app.models.collection import CollectionCard from app.schemas.collection import CollectionCardOut, CollectionStatsOut, PaginatedCollection from app.services.imports import archidekt, manabox from app.services.imports.enrichment import enrich_and_upsert router = APIRouter() @router.post("/import/archidekt", status_code=201) async def import_archidekt( file: UploadFile = File(...), replace: bool = False, user: User = Depends(get_approved_user), db: AsyncSession = Depends(get_db), ): raw = await file.read() rows = archidekt.parse(raw) if replace: await db.execute(delete(CollectionCard).where(CollectionCard.owner_id == user.id)) await db.commit() imported = await enrich_and_upsert(rows, user.id, db) return {"imported": imported} @router.post("/import/manabox", status_code=201) async def import_manabox( file: UploadFile = File(...), replace: bool = False, user: User = Depends(get_approved_user), db: AsyncSession = Depends(get_db), ): raw = await file.read() rows = manabox.parse(raw) if replace: await db.execute(delete(CollectionCard).where(CollectionCard.owner_id == user.id)) await db.commit() imported = await enrich_and_upsert(rows, user.id, db) return {"imported": imported} @router.get("/", response_model=PaginatedCollection) async def list_collection( search: str = "", page: int = 1, page_size: int = 50, user: User = Depends(get_approved_user), db: AsyncSession = Depends(get_db), ): query = select(CollectionCard).where(CollectionCard.owner_id == user.id) if search: query = query.where(CollectionCard.card_name.ilike(f"%{search}%")) total_result = await db.execute( select(func.count()).select_from(query.subquery()) ) total = total_result.scalar_one() result = await db.execute( query.order_by(CollectionCard.card_name) .offset((page - 1) * page_size) .limit(page_size) ) items = result.scalars().all() return PaginatedCollection( items=items, total=total, page=page, page_size=page_size, pages=max(1, -(-total // page_size)), ) @router.get("/stats", response_model=CollectionStatsOut) async def collection_stats( user: User = Depends(get_approved_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(CollectionCard).where(CollectionCard.owner_id == user.id) ) cards = result.scalars().all() total = sum(c.quantity + c.foil_quantity for c in cards) unique = len(cards) foil = sum(c.foil_quantity for c in cards) value = None prices = [] for c in cards: if c.scryfall_data: p = c.scryfall_data.get("prices", {}).get("usd") if p: prices.append(float(p) * (c.quantity + c.foil_quantity)) if prices: value = sum(prices) return CollectionStatsOut( total_cards=total, unique_cards=unique, foil_cards=foil, estimated_value=value ) @router.delete("/", status_code=204) async def clear_collection( user: User = Depends(get_approved_user), db: AsyncSession = Depends(get_db), ): await db.execute(delete(CollectionCard).where(CollectionCard.owner_id == user.id)) await db.commit() @router.delete("/{card_id}", status_code=204) async def delete_card( card_id: int, user: User = Depends(get_approved_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(CollectionCard).where(CollectionCard.id == card_id, CollectionCard.owner_id == user.id) ) card = result.scalar_one_or_none() if not card: raise HTTPException(status_code=404, detail="Card not found") await db.delete(card) await db.commit()