from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import desc, func, or_, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from app.database import get_db from app.models import Bill, Member from app.schemas.schemas import BillSchema, MemberSchema, PaginatedResponse router = APIRouter() @router.get("", response_model=PaginatedResponse[MemberSchema]) async def list_members( chamber: Optional[str] = Query(None), party: Optional[str] = Query(None), state: Optional[str] = Query(None), q: Optional[str] = Query(None), page: int = Query(1, ge=1), per_page: int = Query(50, ge=1, le=250), db: AsyncSession = Depends(get_db), ): query = select(Member) if chamber: query = query.where(Member.chamber == chamber) if party: query = query.where(Member.party == party) if state: query = query.where(Member.state == state) if q: # name is stored as "Last, First" — also match "First Last" order first_last = func.concat( func.split_part(Member.name, ", ", 2), " ", func.split_part(Member.name, ", ", 1), ) query = query.where(or_( Member.name.ilike(f"%{q}%"), first_last.ilike(f"%{q}%"), )) total = await db.scalar(select(func.count()).select_from(query.subquery())) or 0 query = query.order_by(Member.last_name, Member.first_name).offset((page - 1) * per_page).limit(per_page) result = await db.execute(query) members = result.scalars().all() return PaginatedResponse( items=members, total=total, page=page, per_page=per_page, pages=max(1, (total + per_page - 1) // per_page), ) @router.get("/{bioguide_id}", response_model=MemberSchema) async def get_member(bioguide_id: str, db: AsyncSession = Depends(get_db)): member = await db.get(Member, bioguide_id) if not member: raise HTTPException(status_code=404, detail="Member not found") return member @router.get("/{bioguide_id}/bills", response_model=PaginatedResponse[BillSchema]) async def get_member_bills( bioguide_id: str, page: int = Query(1, ge=1), per_page: int = Query(20, ge=1, le=100), db: AsyncSession = Depends(get_db), ): query = select(Bill).options(selectinload(Bill.briefs), selectinload(Bill.sponsor)).where(Bill.sponsor_id == bioguide_id) total = await db.scalar(select(func.count()).select_from(query.subquery())) or 0 query = query.order_by(desc(Bill.introduced_date)).offset((page - 1) * per_page).limit(per_page) result = await db.execute(query) bills = result.scalars().all() items = [] for bill in bills: b = BillSchema.model_validate(bill) if bill.briefs: b.latest_brief = bill.briefs[0] items.append(b) return PaginatedResponse( items=items, total=total, page=page, per_page=per_page, pages=max(1, (total + per_page - 1) // per_page), )