from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from sqlalchemy.orm import selectinload from app.database import get_db from app.models import AdminUser, Household, Commune from app.schemas import AdminLogin, CitizenVerify, Token, AdminUserCreate, AdminUserOut from app.services.auth_service import ( verify_password, create_admin_token, create_citizen_token, hash_password, require_super_admin, ) router = APIRouter() @router.post("/admin/login", response_model=Token) async def admin_login(data: AdminLogin, db: AsyncSession = Depends(get_db)): result = await db.execute( select(AdminUser) .options(selectinload(AdminUser.communes)) .where(AdminUser.email == data.email) ) admin = result.scalar_one_or_none() if not admin or not verify_password(data.password, admin.hashed_password): raise HTTPException(status_code=401, detail="Identifiants invalides") # For commune_admin, include their first commune slug commune_slug = None if admin.communes: commune_slug = admin.communes[0].slug return Token( access_token=create_admin_token(admin), role=admin.role, commune_slug=commune_slug, ) @router.post("/citizen/verify", response_model=Token) async def citizen_verify(data: CitizenVerify, db: AsyncSession = Depends(get_db)): result = await db.execute( select(Household) .join(Commune) .where(Commune.slug == data.commune_slug, Household.auth_code == data.auth_code) ) household = result.scalar_one_or_none() if not household: raise HTTPException(status_code=401, detail="Code invalide ou commune introuvable") return Token( access_token=create_citizen_token(household, data.commune_slug), role="citizen", commune_slug=data.commune_slug, ) @router.post("/admin/create", response_model=AdminUserOut) async def create_admin( data: AdminUserCreate, db: AsyncSession = Depends(get_db), current: AdminUser = Depends(require_super_admin), ): existing = await db.execute(select(AdminUser).where(AdminUser.email == data.email)) if existing.scalar_one_or_none(): raise HTTPException(status_code=400, detail="Email déjà utilisé") admin = AdminUser( email=data.email, hashed_password=hash_password(data.password), full_name=data.full_name, role=data.role, ) if data.commune_slugs: for slug in data.commune_slugs: result = await db.execute(select(Commune).where(Commune.slug == slug)) commune = result.scalar_one_or_none() if commune: admin.communes.append(commune) db.add(admin) await db.commit() await db.refresh(admin) return admin