from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from starlette.responses import PlainTextResponse from api.database import get_session from api.schemas.recently_on_scope import ( RecentlyOnScopeGenerate, RecentlyOnScopeGeneratedReport, RecentlyOnScopeHourlyGenerate, RecentlyOnScopeHourlyRun, RecentlyOnScopeReportMetadata, ) from api.services.markitect_templates import MarkitectRenderError, MarkitectUnavailable from api.services.recently_on_scope import ( generate_report, generate_hourly_reports, list_reports, read_report, resolve_window, ) router = APIRouter(prefix="/domains/{slug}/recently-on-scope", tags=["recently-on-scope"]) hourly_router = APIRouter(prefix="/recently-on-scope", tags=["recently-on-scope"]) @hourly_router.post("/hourly", response_model=RecentlyOnScopeHourlyRun, status_code=status.HTTP_201_CREATED) async def generate_hourly_recently_on_scope( body: RecentlyOnScopeHourlyGenerate, session: AsyncSession = Depends(get_session), ) -> RecentlyOnScopeHourlyRun: try: window = resolve_window(body.range, body.since, body.until) return await generate_hourly_reports( session, window, active_only=body.active_only, include_attention=body.include_attention, ) except ValueError as exc: raise HTTPException(status_code=422, detail=str(exc)) from exc @router.post("/", response_model=RecentlyOnScopeGeneratedReport, status_code=status.HTTP_201_CREATED) async def generate_recently_on_scope( slug: str, body: RecentlyOnScopeGenerate, session: AsyncSession = Depends(get_session), ) -> RecentlyOnScopeGeneratedReport: try: window = resolve_window(body.range, body.since, body.until) metadata, markdown = await generate_report(session, slug, window) except ValueError as exc: raise HTTPException(status_code=422, detail=str(exc)) from exc except MarkitectUnavailable as exc: raise HTTPException(status_code=503, detail=str(exc)) from exc except MarkitectRenderError as exc: raise HTTPException(status_code=500, detail=str(exc)) from exc return RecentlyOnScopeGeneratedReport(**metadata.model_dump(), markdown=markdown) @router.get("/", response_model=list[RecentlyOnScopeReportMetadata]) async def list_recently_on_scope(slug: str) -> list[RecentlyOnScopeReportMetadata]: return list_reports(slug) @router.get("/{report_id}", response_class=PlainTextResponse) async def get_recently_on_scope_report(slug: str, report_id: str) -> PlainTextResponse: try: markdown = read_report(slug, report_id) except FileNotFoundError as exc: raise HTTPException(status_code=404, detail="Report not found") from exc return PlainTextResponse(markdown, media_type="text/markdown")