"""Play history repository — adapter over ``AsyncSession``.""" import datetime as dt import uuid from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.domain.entities.history import PlayHistoryEntry from app.infrastructure.db.models.play_history import PlayHistoryModel def _to_entity(row: PlayHistoryModel) -> PlayHistoryEntry: return PlayHistoryEntry( id=row.id, user_id=row.user_id, track_id=row.track_id, played_at=row.played_at, play_duration_seconds=row.play_duration_seconds, completed=row.completed, ) class SqlAlchemyHistoryRepository: def __init__(self, session: AsyncSession) -> None: self._session = session async def add( self, *, user_id: uuid.UUID, track_id: uuid.UUID, played_at: dt.datetime, play_duration_seconds: int | None, completed: bool, ) -> PlayHistoryEntry: row = PlayHistoryModel( user_id=user_id, track_id=track_id, played_at=played_at, play_duration_seconds=play_duration_seconds, completed=completed, ) self._session.add(row) await self._session.flush() await self._session.refresh(row) return _to_entity(row) async def list(self, *, user_id: uuid.UUID, limit: int, offset: int) -> list[PlayHistoryEntry]: rows = ( ( await self._session.execute( select(PlayHistoryModel) .where(PlayHistoryModel.user_id == user_id) .order_by(PlayHistoryModel.played_at.desc()) .limit(limit) .offset(offset) ) ) .scalars() .all() ) return [_to_entity(r) for r in rows] async def count(self, *, user_id: uuid.UUID) -> int: return ( await self._session.execute( select(func.count()) .select_from(PlayHistoryModel) .where(PlayHistoryModel.user_id == user_id) ) ).scalar_one()