package services import ( "context" "fmt" "strconv" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "neomovies-api/pkg/models" ) type FavoritesService struct { db *mongo.Database tmdb *TMDBService } func NewFavoritesService(db *mongo.Database, tmdb *TMDBService) *FavoritesService { return &FavoritesService{ db: db, tmdb: tmdb, } } func (s *FavoritesService) AddToFavorites(userID, mediaID, mediaType string) error { collection := s.db.Collection("favorites") // Проверяем, не добавлен ли уже в избранное filter := bson.M{ "userId": userID, "mediaId": mediaID, "mediaType": mediaType, } var existingFavorite models.Favorite err := collection.FindOne(context.Background(), filter).Decode(&existingFavorite) if err == nil { // Уже в избранном return nil } var title, posterPath string // Получаем информацию из TMDB в зависимости от типа медиа mediaIDInt, err := strconv.Atoi(mediaID) if err != nil { return fmt.Errorf("invalid media ID: %s", mediaID) } if mediaType == "movie" { movie, err := s.tmdb.GetMovie(mediaIDInt, "en-US") if err != nil { return err } title = movie.Title posterPath = movie.PosterPath } else if mediaType == "tv" { tv, err := s.tmdb.GetTVShow(mediaIDInt, "en-US") if err != nil { return err } title = tv.Name posterPath = tv.PosterPath } else { return fmt.Errorf("invalid media type: %s", mediaType) } // Формируем полный URL для постера if posterPath != "" { posterPath = fmt.Sprintf("https://image.tmdb.org/t/p/w500%s", posterPath) } favorite := models.Favorite{ UserID: userID, MediaID: mediaID, MediaType: mediaType, Title: title, PosterPath: posterPath, CreatedAt: time.Now(), } _, err = collection.InsertOne(context.Background(), favorite) return err } // AddToFavoritesWithInfo adds media to favorites with provided media information func (s *FavoritesService) AddToFavoritesWithInfo(userID, mediaID, mediaType string, mediaInfo *models.MediaInfo) error { collection := s.db.Collection("favorites") // Проверяем, не добавлен ли уже в избранное filter := bson.M{ "userId": userID, "mediaId": mediaID, "mediaType": mediaType, } var existingFavorite models.Favorite err := collection.FindOne(context.Background(), filter).Decode(&existingFavorite) if err == nil { // Уже в избранном return nil } // Формируем полный URL для постера если он есть posterPath := mediaInfo.PosterPath if posterPath != "" && posterPath[0] == '/' { posterPath = fmt.Sprintf("https://image.tmdb.org/t/p/w500%s", posterPath) } favorite := models.Favorite{ UserID: userID, MediaID: mediaID, MediaType: mediaType, Title: mediaInfo.Title, PosterPath: posterPath, CreatedAt: time.Now(), } _, err = collection.InsertOne(context.Background(), favorite) return err } func (s *FavoritesService) RemoveFromFavorites(userID, mediaID, mediaType string) error { collection := s.db.Collection("favorites") filter := bson.M{ "userId": userID, "mediaId": mediaID, "mediaType": mediaType, } _, err := collection.DeleteOne(context.Background(), filter) return err } func (s *FavoritesService) GetFavorites(userID string) ([]models.Favorite, error) { collection := s.db.Collection("favorites") filter := bson.M{ "userId": userID, } cursor, err := collection.Find(context.Background(), filter) if err != nil { return nil, err } defer cursor.Close(context.Background()) var favorites []models.Favorite err = cursor.All(context.Background(), &favorites) if err != nil { return nil, err } // Возвращаем пустой массив вместо nil если нет избранных if favorites == nil { favorites = []models.Favorite{} } return favorites, nil } func (s *FavoritesService) IsFavorite(userID, mediaID, mediaType string) (bool, error) { collection := s.db.Collection("favorites") filter := bson.M{ "userId": userID, "mediaId": mediaID, "mediaType": mediaType, } var favorite models.Favorite err := collection.FindOne(context.Background(), filter).Decode(&favorite) if err != nil { if err == mongo.ErrNoDocuments { return false, nil } return false, err } return true, nil }