searchMoviesByActor method

Future<List<Movie>> searchMoviesByActor(
  1. String actorName
)

Searches for movies by actor/person name.

Implementation

Future<List<Movie>> searchMoviesByActor(String actorName) async {
  // First search for people.

  final personResults = await _client
      .getJsonList('search/person?query=${Uri.encodeComponent(actorName)}');

  if (personResults.isEmpty) return [];

  final allMovies = <Movie>[];
  final seenMovieIds = <int>{};

  // Determine if this is a specific search (contains space) or generic.

  final isSpecificSearch = actorName.contains(' ');

  // Sort people by popularity (descending) and known_for_department.

  final sortedPeople = List<Map<String, dynamic>>.from(personResults);
  sortedPeople.sort((a, b) {
    final popularityA = (a['popularity'] as num?)?.toDouble() ?? 0.0;
    final popularityB = (b['popularity'] as num?)?.toDouble() ?? 0.0;

    // Prioritise actors over other professions.

    final knownForA = a['known_for_department'] as String? ?? '';
    final knownForB = b['known_for_department'] as String? ?? '';
    final isActorA = knownForA.toLowerCase() == 'acting';
    final isActorB = knownForB.toLowerCase() == 'acting';

    if (isActorA && !isActorB) return -1;
    if (!isActorA && isActorB) return 1;

    return popularityB.compareTo(popularityA);
  });

  // For generic searches, process more people to find famous actors.
  // For specific searches, process fewer but still enough to find target.

  final maxPeopleToProcess = isSpecificSearch ? 5 : 10;
  final peopleToProcess = sortedPeople.take(maxPeopleToProcess);

  for (final person in peopleToProcess) {
    try {
      final personId = person['id'];
      final popularity = (person['popularity'] as num?)?.toDouble() ?? 0.0;

      // Skip people who are too unknown (but be more lenient for specific).

      final minPopularity = isSpecificSearch ? 0.1 : 0.5;
      if (popularity < minPopularity) {
        continue;
      }

      final movieCredits =
          await _client.getJson('person/$personId/movie_credits');
      final cast = movieCredits['cast'] as List<dynamic>? ?? [];

      for (final movieData in cast) {
        final movieId = movieData['id'] as int;

        // Avoid duplicate movies.

        if (!seenMovieIds.contains(movieId)) {
          try {
            final movie = Movie.fromJson(movieData);
            allMovies.add(movie);
            seenMovieIds.add(movieId);
          } catch (e) {
            continue;
          }
        }
      }

      // If we have a very specific search and found a highly popular
      // match, prioritise that.

      if (isSpecificSearch && popularity > 10.0) {
        break;
      }
    } catch (e) {
      continue;
    }
  }

  // Sort by popularity/rating for better results ordering.

  allMovies.sort((a, b) => b.voteAverage.compareTo(a.voteAverage));

  return allMovies;
}