from fastapi import APIRouter, Depends, HTTPException, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from pydantic import BaseModel from ..database import get_db from ..models import Set, Card, User from ..auth import require_admin router = APIRouter() async def require_admin_html(request: Request) -> User: """Admin check from cookie-based auth (HTML pages).""" user = request.state.user if not user or user.role != "admin": raise HTTPException(status_code=401, detail="Admin login required") return user templates = Jinja2Templates(directory="app/templates") class SetForm(BaseModel): code: str name: str release_date: str | None = None description: str | None = None class CardForm(BaseModel): number: str name: str type: str | None = None rarity: str | None = None hp: int | None = None stage: str | None = None description: str | None = None image_url: str | None = None # --- Admin pages --- @router.get("/admin", response_class=HTMLResponse) async def admin_dashboard(request: Request, user: User = Depends(require_admin_html)): return templates.TemplateResponse("admin/dashboard.html", {"request": request, "user": user}) @router.get("/admin/sets", response_class=HTMLResponse) async def admin_sets(request: Request, user: User = Depends(require_admin_html)): return templates.TemplateResponse("admin/sets.html", {"request": request, "user": user}) @router.get("/admin/cards/{set_code}", response_class=HTMLResponse) async def admin_cards(request: Request, set_code: str, user: User = Depends(require_admin_html)): return templates.TemplateResponse("admin/cards.html", {"request": request, "user": user, "set_code": set_code}) # --- CRUD: Sets --- @router.post("/api/admin/sets") async def create_set( data: SetForm, db: AsyncSession = Depends(get_db), _: User = Depends(require_admin), ): exists = await db.execute(select(Set).where(Set.code == data.code.upper())) if exists.scalar_one_or_none(): raise HTTPException(status_code=400, detail=f"Set '{data.code.upper()}' findes allerede") s = Set(code=data.code.upper(), name=data.name, release_date=data.release_date, description=data.description) db.add(s) await db.commit() await db.refresh(s) return {"ok": True, "id": s.id, "code": s.code} @router.get("/api/admin/sets") async def list_sets_admin( db: AsyncSession = Depends(get_db), _: User = Depends(require_admin), ): result = await db.execute(select(Set).order_by(Set.code)) sets = result.scalars().all() return [{"id": s.id, "code": s.code, "name": s.name, "release_date": s.release_date or ""} for s in sets] @router.delete("/api/admin/sets/{set_id}") async def delete_set( set_id: int, db: AsyncSession = Depends(get_db), _: User = Depends(require_admin), ): s = await db.get(Set, set_id) if not s: raise HTTPException(status_code=404, detail="Set ikke fundet") await db.delete(s) await db.commit() return {"ok": True} # --- CRUD: Cards --- @router.post("/api/admin/sets/{set_code}/cards") async def create_card( set_code: str, data: CardForm, db: AsyncSession = Depends(get_db), _: User = Depends(require_admin), ): result = await db.execute(select(Set).where(Set.code == set_code.upper())) s = result.scalar_one_or_none() if not s: raise HTTPException(status_code=404, detail=f"Set '{set_code.upper()}' ikke fundet") card = Card( set_id=s.id, number=data.number, name=data.name, type=data.type, rarity=data.rarity, hp=data.hp, stage=data.stage, description=data.description, image_url=data.image_url, ) db.add(card) await db.commit() await db.refresh(card) return {"ok": True, "id": card.id, "full_code": card.full_code} @router.get("/api/admin/sets/{set_code}/cards") async def list_cards_admin( set_code: str, db: AsyncSession = Depends(get_db), _: User = Depends(require_admin), ): result = await db.execute(select(Set).where(Set.code == set_code.upper())) s = result.scalar_one_or_none() if not s: raise HTTPException(status_code=404, detail="Set ikke fundet") return [ {"id": c.id, "number": c.number, "name": c.name, "type": c.type or "", "rarity": c.rarity or "", "hp": c.hp, "full_code": c.full_code} for c in s.cards ] @router.delete("/api/admin/cards/{card_id}") async def delete_card( card_id: int, db: AsyncSession = Depends(get_db), _: User = Depends(require_admin), ): card = await db.get(Card, card_id) if not card: raise HTTPException(status_code=404, detail="Kort ikke fundet") await db.delete(card) await db.commit() return {"ok": True}