"""JSON-based movie repository implementation.""" from typing import List, Optional, Dict, Any import logging from domain.movies.repositories import MovieRepository from domain.movies.entities import Movie from domain.shared.value_objects import ImdbId from ..memory import Memory logger = logging.getLogger(__name__) class JsonMovieRepository(MovieRepository): """ JSON-based implementation of MovieRepository. Stores movies in the memory.json file. """ def __init__(self, memory: Memory): """ Initialize repository. Args: memory: Memory instance for persistence """ self.memory = memory def save(self, movie: Movie) -> None: """Save a movie to the repository.""" movies = self._load_all() # Remove existing movie with same IMDb ID movies = [m for m in movies if m.get('imdb_id') != str(movie.imdb_id)] # Add new movie movies.append(self._to_dict(movie)) # Save to memory self.memory.set('movies', movies) logger.debug(f"Saved movie: {movie.imdb_id}") def find_by_imdb_id(self, imdb_id: ImdbId) -> Optional[Movie]: """Find a movie by its IMDb ID.""" movies = self._load_all() for movie_dict in movies: if movie_dict.get('imdb_id') == str(imdb_id): return self._from_dict(movie_dict) return None def find_all(self) -> List[Movie]: """Get all movies in the repository.""" movies_dict = self._load_all() return [self._from_dict(m) for m in movies_dict] def delete(self, imdb_id: ImdbId) -> bool: """Delete a movie from the repository.""" movies = self._load_all() initial_count = len(movies) # Filter out the movie movies = [m for m in movies if m.get('imdb_id') != str(imdb_id)] if len(movies) < initial_count: self.memory.set('movies', movies) logger.debug(f"Deleted movie: {imdb_id}") return True return False def exists(self, imdb_id: ImdbId) -> bool: """Check if a movie exists in the repository.""" return self.find_by_imdb_id(imdb_id) is not None def _load_all(self) -> List[Dict[str, Any]]: """Load all movies from memory.""" return self.memory.get('movies', []) def _to_dict(self, movie: Movie) -> Dict[str, Any]: """Convert Movie entity to dict for storage.""" return { 'imdb_id': str(movie.imdb_id), 'title': movie.title.value, 'release_year': movie.release_year.value if movie.release_year else None, 'quality': movie.quality.value, 'file_path': str(movie.file_path) if movie.file_path else None, 'file_size': movie.file_size.bytes if movie.file_size else None, 'tmdb_id': movie.tmdb_id, 'overview': movie.overview, 'poster_path': movie.poster_path, 'vote_average': movie.vote_average, 'added_at': movie.added_at.isoformat(), } def _from_dict(self, data: Dict[str, Any]) -> Movie: """Convert dict from storage to Movie entity.""" from domain.movies.value_objects import MovieTitle, ReleaseYear, Quality from domain.shared.value_objects import FilePath, FileSize from datetime import datetime return Movie( imdb_id=ImdbId(data['imdb_id']), title=MovieTitle(data['title']), release_year=ReleaseYear(data['release_year']) if data.get('release_year') else None, quality=Quality(data.get('quality', 'unknown')), file_path=FilePath(data['file_path']) if data.get('file_path') else None, file_size=FileSize(data['file_size']) if data.get('file_size') else None, tmdb_id=data.get('tmdb_id'), overview=data.get('overview'), poster_path=data.get('poster_path'), vote_average=data.get('vote_average'), added_at=datetime.fromisoformat(data['added_at']) if data.get('added_at') else datetime.now(), )