from __future__ import annotations from fastapi import APIRouter, Depends, Request from sqlalchemy.orm import Session from app.api.guest_scope import assert_guest_project_scope from app.core.errors import AppError from app.db.session import get_db from app.models import Dataset from app.schemas import Envelope, JobRead from app.schemas.analysis import ChangeDetectionRequest from app.services.change_detection_service import ChangeDetectionService from app.services.job_service import JobService from app.utils.response import envelope router = APIRouter(prefix="/analysis", tags=["analysis"]) @router.post("/change-detection", response_model=Envelope[JobRead]) def run_change_detection( payload: ChangeDetectionRequest, request: Request, db: Session = Depends(get_db), ) -> dict: source_dataset = db.get(Dataset, payload.source_dataset_id) if not source_dataset: raise AppError(code="DATASET_NOT_FOUND", message="Source dataset not found", status_code=404) assert_guest_project_scope(request, source_dataset.project_id) ChangeDetectionService._get_project_vector_dataset(db, payload.source_dataset_id, source_dataset.project_id, "Source") ChangeDetectionService._get_project_vector_dataset(db, payload.target_dataset_id, source_dataset.project_id, "Target") job = JobService.run_sync_job( db=db, project_id=source_dataset.project_id, job_type="analysis.change-detection", parameters=payload.model_dump(mode="json"), input_dataset_id=payload.source_dataset_id, operation=lambda: ChangeDetectionService.compare_vector_datasets( db=db, project_id=source_dataset.project_id, source_dataset_id=payload.source_dataset_id, target_dataset_id=payload.target_dataset_id, iou_threshold=payload.iou_threshold, modified_threshold=payload.modified_threshold, include_unchanged=payload.include_unchanged, bbox=payload.bbox.model_dump() if payload.bbox is not None else None, area_id=payload.area_id, preview_limit=payload.preview_limit, ).model_dump(mode="json"), ) return envelope(job)