import uuid from datetime import datetime from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from ...auth import verify_token from ...config import settings from ...outbound.postgres.database import get_db from ...outbound.postgres.repositories.translated_article_repository import TranslatedArticleRepository router = APIRouter(prefix="/articles", tags=["bff", "articles"]) class ArticleItem(BaseModel): id: str published_at: datetime source_language: str source_title: str target_language: str target_complexities: list[str] target_title: str class ArticleListResponse(BaseModel): articles: list[ArticleItem] class ArticleDetail(BaseModel): id: str published_at: datetime source_language: str source_title: str source_body: str source_body_pos: dict target_language: str target_complexities: list[str] target_title: str target_body: str target_audio_url: str | None target_body_pos: dict target_body_transcript: dict | None def _audio_url(key: str | None) -> str | None: if key is None: return None return f"{settings.api_base_url}/media/{key}" @router.get("", response_model=ArticleListResponse, status_code=200) async def list_articles( target_language: str = 'fr', db: AsyncSession = Depends(get_db), _: dict = Depends(verify_token), ) -> ArticleListResponse: articles = await TranslatedArticleRepository(db).list_complete(target_language=target_language) return ArticleListResponse( articles=[ ArticleItem( id=a.id, published_at=a.published_at, source_language=a.source_language, source_title=a.source_title, target_language=a.target_language, target_complexities=a.target_complexities, target_title=a.target_title, ) for a in articles ] ) @router.get("/{article_id}", response_model=ArticleDetail, status_code=200) async def get_article( article_id: str, db: AsyncSession = Depends(get_db), _: dict = Depends(verify_token), ) -> ArticleDetail: try: uid = uuid.UUID(article_id) except ValueError: raise HTTPException(status_code=400, detail="Invalid article ID") article = await TranslatedArticleRepository(db).get_complete_by_id(uid) if article is None: raise HTTPException(status_code=404, detail="Article not found") return ArticleDetail( id=article.id, published_at=article.published_at, source_language=article.source_language, source_title=article.source_title, source_body=article.source_body, source_body_pos=article.source_body_pos, target_language=article.target_language, target_complexities=article.target_complexities, target_title=article.target_title, target_body=article.target_body, target_audio_url=_audio_url(article.audio_url), target_body_pos=article.target_body_pos, target_body_transcript=article.target_body_transcript, )