@startuml


package controller <<Folder>> #lime{

    class MovieController{
    +static int maximumMovieId = 1101964//changeForConstants
    + MovieService movieService
    + ActorService actorService
    + ResponseEntity<Movie> defaultMapping()
    + ResponseEntity<List<Movie>> movieRecommendations(@PathVariable Long movieId)
    + ResponseEntity<List<Movie>> movieSimilar(@PathVariable Long movieId)
    + ResponseEntity<List<Movie>> moviesWithActors(@RequestParam Long actor1, @RequestParam(required = false) Long actor2)
    + ResponseEntity<Director> directorByMovie(@PathVariable Long movieId)
    + ResponseEntity<List<Genres>> genrelist()
    + ResponseEntity<Movie> movieByID(@PathVariable Long movieId)
    + ResponseEntity<List<Movie>> popularMovies()
    + ResponseEntity<List<Movie>> topRatedMovies()
    + ResponseEntity<Movie> latestMovie()
    + ResponseEntity<List<Actor>> actorsByMovieId(@PathVariable Long movieId)
    + ResponseEntity<List<Movie>> moviesWithinRating(@RequestParam Double rateMin, @RequestParam(required = false) Double rateMax)
    + ResponseEntity<Movie> chooseRandomMovie()
    + ResponseEntity<List<Movie>> findMoviesWithSpecificParameters(@RequestParam(defaultValue = "1900-01-01") String from_date,
                                                                            @RequestParam(required = false) String genre,
                                                                            @RequestParam(required = false) String rating,
                                                                            @RequestParam(required = false) String time_available)
    + ResponseEntity<List<Movie>> getUpcomingMovies(@RequestParam(defaultValue = "GB") String region)
    }

    class ActorController{
    + ActorService actorService
    + ResponseEntity<List<Actor>> defaultMapping()
    + ResponseEntity<Actor> actorById(@PathVariable Long actorId)
    + ResponseEntity<List<Actor>> popularActors()
    }

    class SearchController {
    +SearchService searchService
    + ResponseEntity<String> defaultMapping()
    + ResponseEntity<List<Movie>> searchMovies(@PathVariable String searchTerm)
    + ResponseEntity<List<Actor>> searchActor(@PathVariable String searchTerm)
    }

    class MovieReviewController {
    + MovieReviewService reviewService
    + ResponseEntity<List<MovieReviews>> getReviewsByMovieId(@PathVariable Long id)
    }

}


package model <<Folder>> #burlywood{

    class Actor{

  }

  class AuthorDetails {
    - String name;
    - String username;
    - String avatar_path;
    - Double rating;
  }


  class Director{
  - String job
  }

  class Genres{
  - Long id;
  - String name;
  }

  class Movie{
    - Long id;
    - String original_title;
    - String release_date;
    - String overview;
    - double vote_average;
    - boolean adult;
      }

  class MovieReviewResponse {
  - List<MovieReviews> results;
  + List<MovieReviews> getResults()
  }

   class MovieReviews {
   - String id
   - String author
   - AuthorDetails author_details
   - String content
   - double rating
   - LocalDateTime created_at
   - LocalDateTime updated_at
   - String url
   }

  class Person{
    - Long id;
    - String name;
    - String known_for_department;
    - String birthday;
    - String biography;
    }
}

package repository <<Folder>> #violet {

  interface MovieRepository {

  }
}

package service <<Folder>> #red{

     interface ActorService{
      + Actor getActor(Long actorId)
      + List<Actor> getActorsByMovieId(Long movieId)
      + List<Actor> getPopularActors()
      }



  interface MovieService{
  + Movie getMovieById(Long movieId)
  + List<Movie> getMovies(String type)
  + Movie getLatestMovie()
  + List<Genres> getGenreList()
  + List<Movie> getMovieRecommendationsSimilar(Long movieId, String recommendations)
  + List<Movie> getMoviesByActor(Long actorId)
  }
  class MovieServiceImpl{
  - String apiKey
  - String apiUrl;
  + MovieRepository movieRepository
  + Movie getMovieById(Long movieId)
  + List<Movie> getMovies(String type)
  + Movie getLatestMovie()
  + List<Genres> getGenreList()
  + List<Movie> getMovieRecommendationsSimilar(Long movieId, String type)
  + List<Movie> getMoviesByActor(Long actorId)
  - List<Movie> returnMovieListFromUrl(String url)
  }



  class ActorServiceImpl{
  - String apiKey
  - String apiUrl
  + Actor getActor(Long actorId)
  + List<Actor> getActorsByMovieId(Long movieId)
  + List<Actor> getPopularActors()
  - List<Actor> returnActorListFromUrl(String url, String type)
  }



}
Interface CrudRepository<movie,ID>{

}

class ExternalMovieAPI{

    }

package exception <<Folder>> #brown{
    class ErrorResponse{
    - LocalDateTime timestamp;
    - String message;
    __
    + errorResponse(String message)
    ..
    + String getMessage()
    + void setMessage(String message)
    + LocalDateTime getTimestamp()
    + void setTimestamp(LocalDateTime timestamp)
    }
    class MovieNotFoundException {
    + MovieNotFoundException()

    }
    class MovieReviewException {
        + MovieReviewException(String message)

        }
    class MyMovieErrorHandler {
     + handleError(ClientHttpResponse response)
    }

    class ActorNotFoundException {
    + ActorNotFoundException()
    }

    class MyPersonErrorHandler {
    + void handleError(ClientHttpResponse response)
    }

    class PersonNotFoundException {
    + PersonNotFoundException()
    }



    }
    class ApplicationExceptionHandler{
    + ResponseEntity<Object> handleMovieNotFoundException(MovieNotFoundException e)
    + ResponseEntity<Object> handlePersonNotFoundException(PersonNotFoundException e)
    + ResponseEntity<Object> handleActorNotFoundException(ActorNotFoundException e)

    }

MovieController <--> MovieServiceImpl
MovieRepository --> CrudRepository

MovieServiceImpl -- MovieService
MovieServiceImpl -- MovieRepository
MovieRepository -- Movie
MovieServiceImpl -- ExternalMovieAPI

ActorController <--> ActorServiceImpl
ActorServiceImpl -- ActorService
Actor -up-> Person
Genres -- MovieServiceImpl
Director --> Person
'exception
ActorNotFoundException --> RuntimeException
MovieNotFoundException --> RuntimeException
MyMovieErrorHandler --> DefaultResponseErrorHandler
MyPersonErrorHandler --> DefaultResponseErrorHandler
PersonNotFoundException --> RuntimeException
MovieReviewException --> RuntimeException

ApplicationExceptionHandler -- MovieNotFoundException
ApplicationExceptionHandler -- PersonNotFoundException
ApplicationExceptionHandler -- ActorNotFoundException
ApplicationExceptionHandler -- ErrorResponse


@enduml