from __future__ import annotations from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app.db.session import get_db from app.schemas import Envelope, JobCreate, JobList, JobRead, JobStatus from app.services.job_service import JobService from app.utils.response import envelope router = APIRouter(prefix="/projects/{project_id}", tags=["jobs"]) @router.post("/jobs", status_code=201, response_model=Envelope[JobRead]) def create_job( project_id: UUID, payload: JobCreate, db: Session = Depends(get_db), ): if payload.project_id != project_id: raise HTTPException(status_code=400, detail="project_id mismatch") return envelope(JobService.create_job(db, payload).model_dump()) @router.get("/jobs", response_model=Envelope[JobList]) def list_jobs( project_id: UUID, dataset_id: UUID | None = Query(default=None), limit: int = Query(default=50, ge=1, le=200), offset: int = Query(default=0, ge=0), db: Session = Depends(get_db), ): items, total = JobService.list_jobs( db, project_id=project_id, dataset_id=dataset_id, limit=limit, offset=offset, ) return envelope(JobList(items=items, total=total, limit=limit, offset=offset).model_dump()) @router.get("/jobs/{job_id}", response_model=Envelope[JobRead]) def read_job( project_id: UUID, job_id: UUID, db: Session = Depends(get_db), ): job = JobService.get_job(db, job_id) if job.project_id != project_id: raise HTTPException(status_code=404, detail="Job not found") return envelope(job.model_dump()) @router.get("/jobs/{job_id}/status", response_model=Envelope[JobStatus]) def read_job_status( project_id: UUID, job_id: UUID, db: Session = Depends(get_db), ): status_row = JobService.get_job_status(db, job_id) if status_row["project_id"] != str(project_id): raise HTTPException(status_code=404, detail="Job not found") return envelope(JobStatus(**status_row).model_dump())