""" Signin Log query router. All endpoints require JWT authentication and enforce resource ownership. """ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from shared.models import get_db, Account, SigninLog, User from shared.response import success_response from api_service.app.dependencies import get_current_user from api_service.app.schemas.signin_log import SigninLogResponse, PaginatedResponse router = APIRouter(prefix="/api/v1/accounts", tags=["signin-logs"]) async def _verify_account_ownership( account_id: str, user: User, db: AsyncSession, ) -> Account: """Verify that the account belongs to the current user.""" result = await db.execute(select(Account).where(Account.id == account_id)) account = result.scalar_one_or_none() if account is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Account not found") if account.user_id != user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Access denied") return account @router.get("/{account_id}/signin-logs") async def get_signin_logs( account_id: str, page: int = Query(1, ge=1, description="Page number (starts from 1)"), size: int = Query(20, ge=1, le=100, description="Page size (max 100)"), status_filter: Optional[str] = Query(None, alias="status", description="Filter by status"), user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """ Query signin logs for a specific account with pagination and status filtering. Returns logs sorted by signed_at in descending order (newest first). """ # Verify account ownership await _verify_account_ownership(account_id, user, db) # Build base query query = select(SigninLog).where(SigninLog.account_id == account_id) # Apply status filter if provided if status_filter: query = query.where(SigninLog.status == status_filter) # Get total count count_query = select(func.count()).select_from(query.subquery()) total_result = await db.execute(count_query) total = total_result.scalar() # Apply ordering and pagination query = query.order_by(SigninLog.signed_at.desc()) offset = (page - 1) * size query = query.offset(offset).limit(size) # Execute query result = await db.execute(query) logs = result.scalars().all() # Calculate total pages total_pages = (total + size - 1) // size if total > 0 else 0 # Build response paginated = PaginatedResponse( items=[SigninLogResponse.model_validate(log) for log in logs], total=total, page=page, size=size, total_pages=total_pages, ) return success_response(paginated.model_dump(mode="json"), "Signin logs retrieved")