import uuid from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from api.database import get_session from api.models.managed_repo import ManagedRepo from api.models.repo_goal import RepoGoal, RepoGoalStatus from api.schemas.repo_goal import RepoGoalCreate, RepoGoalRead, RepoGoalUpdate router = APIRouter(prefix="/repo-goals", tags=["repo-goals"]) async def _resolve_repo(repo_slug: str, session: AsyncSession) -> ManagedRepo: result = await session.execute(select(ManagedRepo).where(ManagedRepo.slug == repo_slug)) repo = result.scalar_one_or_none() if repo is None: raise HTTPException(status_code=404, detail=f"Repo '{repo_slug}' not found") return repo @router.get("/", response_model=list[RepoGoalRead]) async def list_repo_goals( repo_slug: str | None = None, domain_goal_id: uuid.UUID | None = None, status: str | None = None, session: AsyncSession = Depends(get_session), ) -> list[RepoGoal]: q = select(RepoGoal) if repo_slug: repo = await _resolve_repo(repo_slug, session) q = q.where(RepoGoal.repo_id == repo.id) if domain_goal_id: q = q.where(RepoGoal.domain_goal_id == domain_goal_id) if status: q = q.where(RepoGoal.status == status) q = q.order_by(RepoGoal.priority.asc(), RepoGoal.created_at.asc()) result = await session.execute(q) return list(result.scalars().all()) @router.post("/", response_model=RepoGoalRead, status_code=status.HTTP_201_CREATED) async def create_repo_goal( body: RepoGoalCreate, session: AsyncSession = Depends(get_session), ) -> RepoGoal: goal = RepoGoal(**body.model_dump()) session.add(goal) await session.commit() await session.refresh(goal) return goal @router.get("/{goal_id}", response_model=RepoGoalRead) async def get_repo_goal( goal_id: uuid.UUID, session: AsyncSession = Depends(get_session), ) -> RepoGoal: goal = await session.get(RepoGoal, goal_id) if goal is None: raise HTTPException(status_code=404, detail="Repo goal not found") return goal @router.patch("/{goal_id}", response_model=RepoGoalRead) async def update_repo_goal( goal_id: uuid.UUID, body: RepoGoalUpdate, session: AsyncSession = Depends(get_session), ) -> RepoGoal: goal = await session.get(RepoGoal, goal_id) if goal is None: raise HTTPException(status_code=404, detail="Repo goal not found") for field, value in body.model_dump(exclude_unset=True).items(): setattr(goal, field, value) await session.commit() await session.refresh(goal) return goal