2025-08-07 13:47:42 +00:00
|
|
|
package services
|
|
|
|
|
|
|
|
|
|
import (
|
2025-10-18 23:55:42 +00:00
|
|
|
"fmt"
|
2025-08-07 13:47:42 +00:00
|
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
|
|
|
|
|
|
|
|
"neomovies-api/pkg/models"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type MovieService struct {
|
2025-10-18 20:21:13 +00:00
|
|
|
tmdb *TMDBService
|
|
|
|
|
kpService *KinopoiskService
|
2025-08-07 13:47:42 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-18 20:21:13 +00:00
|
|
|
func NewMovieService(db *mongo.Database, tmdb *TMDBService, kpService *KinopoiskService) *MovieService {
|
2025-08-07 13:47:42 +00:00
|
|
|
return &MovieService{
|
2025-10-18 20:21:13 +00:00
|
|
|
tmdb: tmdb,
|
|
|
|
|
kpService: kpService,
|
2025-08-07 13:47:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) Search(query string, page int, language, region string, year int) (*models.TMDBResponse, error) {
|
2025-10-18 20:21:13 +00:00
|
|
|
if ShouldUseKinopoisk(language) && s.kpService != nil {
|
|
|
|
|
kpSearch, err := s.kpService.SearchFilms(query, page)
|
|
|
|
|
if err == nil {
|
|
|
|
|
return MapKPSearchToTMDBResponse(kpSearch), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-07 13:47:42 +00:00
|
|
|
return s.tmdb.SearchMovies(query, page, language, region, year)
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-18 23:41:53 +00:00
|
|
|
func (s *MovieService) GetByID(id int, language string, idType string) (*models.Movie, error) {
|
2025-10-19 07:40:37 +00:00
|
|
|
// Строго уважаем явный id_type, без скрытого fallback на TMDB
|
|
|
|
|
switch idType {
|
|
|
|
|
case "kp":
|
|
|
|
|
if s.kpService == nil {
|
|
|
|
|
return nil, fmt.Errorf("kinopoisk service not configured")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Сначала пробуем как Kinopoisk ID
|
|
|
|
|
if kpFilm, err := s.kpService.GetFilmByKinopoiskId(id); err == nil {
|
2025-10-19 13:51:47 +00:00
|
|
|
// Возвращаем KP-модель в TMDB-формате без подмены на TMDB объект
|
2025-10-19 07:40:37 +00:00
|
|
|
return MapKPFilmToTMDBMovie(kpFilm), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Возможно пришел TMDB ID — пробуем конвертировать TMDB -> KP
|
|
|
|
|
if kpId, convErr := TmdbIdToKPId(s.tmdb, s.kpService, id); convErr == nil {
|
|
|
|
|
if kpFilm, err := s.kpService.GetFilmByKinopoiskId(kpId); err == nil {
|
|
|
|
|
return MapKPFilmToTMDBMovie(kpFilm), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Явно указан KP, но ничего не нашли — возвращаем ошибку
|
|
|
|
|
return nil, fmt.Errorf("film not found in Kinopoisk with id %d", id)
|
|
|
|
|
|
|
|
|
|
case "tmdb":
|
|
|
|
|
return s.tmdb.GetMovie(id, language)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Если id_type не указан — старая логика по языку
|
|
|
|
|
if ShouldUseKinopoisk(language) && s.kpService != nil {
|
|
|
|
|
if kpFilm, err := s.kpService.GetFilmByKinopoiskId(id); err == nil {
|
|
|
|
|
return MapKPFilmToTMDBMovie(kpFilm), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s.tmdb.GetMovie(id, language)
|
2025-08-07 13:47:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetPopular(page int, language, region string) (*models.TMDBResponse, error) {
|
2025-10-18 20:21:13 +00:00
|
|
|
if ShouldUseKinopoisk(language) && s.kpService != nil {
|
|
|
|
|
kpTop, err := s.kpService.GetTopFilms("TOP_100_POPULAR_FILMS", page)
|
|
|
|
|
if err == nil {
|
|
|
|
|
return MapKPSearchToTMDBResponse(kpTop), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-07 13:47:42 +00:00
|
|
|
return s.tmdb.GetPopularMovies(page, language, region)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetTopRated(page int, language, region string) (*models.TMDBResponse, error) {
|
2025-10-18 20:21:13 +00:00
|
|
|
if ShouldUseKinopoisk(language) && s.kpService != nil {
|
|
|
|
|
kpTop, err := s.kpService.GetTopFilms("TOP_250_BEST_FILMS", page)
|
|
|
|
|
if err == nil {
|
|
|
|
|
return MapKPSearchToTMDBResponse(kpTop), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-07 13:47:42 +00:00
|
|
|
return s.tmdb.GetTopRatedMovies(page, language, region)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetUpcoming(page int, language, region string) (*models.TMDBResponse, error) {
|
|
|
|
|
return s.tmdb.GetUpcomingMovies(page, language, region)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetNowPlaying(page int, language, region string) (*models.TMDBResponse, error) {
|
|
|
|
|
return s.tmdb.GetNowPlayingMovies(page, language, region)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetRecommendations(id, page int, language string) (*models.TMDBResponse, error) {
|
|
|
|
|
return s.tmdb.GetMovieRecommendations(id, page, language)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetSimilar(id, page int, language string) (*models.TMDBResponse, error) {
|
|
|
|
|
return s.tmdb.GetSimilarMovies(id, page, language)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *MovieService) GetExternalIDs(id int) (*models.ExternalIDs, error) {
|
2025-10-18 22:05:51 +00:00
|
|
|
if s.kpService != nil {
|
|
|
|
|
kpFilm, err := s.kpService.GetFilmByKinopoiskId(id)
|
|
|
|
|
if err == nil && kpFilm != nil {
|
|
|
|
|
externalIDs := MapKPExternalIDsToTMDB(kpFilm)
|
|
|
|
|
externalIDs.ID = id
|
2025-10-19 12:48:11 +00:00
|
|
|
|
|
|
|
|
// Пытаемся получить TMDB ID через IMDB ID
|
|
|
|
|
if kpFilm.ImdbId != "" && s.tmdb != nil {
|
|
|
|
|
if tmdbID, tmdbErr := s.tmdb.FindTMDBIdByIMDB(kpFilm.ImdbId, "movie", "ru-RU"); tmdbErr == nil {
|
|
|
|
|
externalIDs.TMDBID = tmdbID
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-18 22:05:51 +00:00
|
|
|
return externalIDs, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-18 20:21:13 +00:00
|
|
|
tmdbIDs, err := s.tmdb.GetMovieExternalIDs(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.kpService != nil && tmdbIDs.IMDbID != "" {
|
|
|
|
|
kpFilm, err := s.kpService.GetFilmByImdbId(tmdbIDs.IMDbID)
|
|
|
|
|
if err == nil && kpFilm != nil {
|
|
|
|
|
tmdbIDs.KinopoiskID = kpFilm.KinopoiskId
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tmdbIDs, nil
|
2025-09-28 11:46:20 +00:00
|
|
|
}
|