---
name: TMDB Enrichment Service (Parallel Pattern)
description: "Parallel TMDB metadata enrichment — credits, images, videos, recommendations with request deduplication."
version: 1.0.0
---

# TMDB Enrichment Service — Parallel Pattern

## Problem
NexStream's `TmdbRepository` only did external ID resolution and image URLs. NuvioTV's `TmdbMetadataService` does parallel enrichment (credits, images, videos, recommendations) with `async/awaitAll` and request deduplication.

## Solution
Created `TmdbMetadataService` that mirrors NuvioTV's pattern:

### Key Features
1. **Parallel sub-fetches:** details + credits + videos + images all fetched via `async`
2. **Request deduplication:** `CompletableDeferred` map prevents duplicate in-flight requests
3. **In-memory caching:** `ConcurrentHashMap` with cache keys like `"tmdbId:contentType:language"`
4. **Episode-level enrichment:** per-season episode data with caching
5. **Append-to-response:** uses TMDB's `append_to_response` parameter for single-call enrichment

### API Methods Added to TmdbApi.kt
- `getMovieCredits()` / `getTvCredits()` — credits endpoint
- `getMovieImages()` / `getTvImages()` — images endpoint
- `getPersonDetail()` — person detail endpoint
- `getSeasonDetail()` — season/episodes endpoint
- `getMovieDetailWithAppend()` — movie with credits+videos+images+external_ids
- `getTvDetailWithAppend()` — TV with credits+videos+images+external_ids

### Response Data Classes Added
- `TmdbCreditsResponse`, `TmdbCastItem`, `TmdbCrewItem`
- `TmdbImagesResponse`, `TmdbImageItem`
- `TmdbPersonResponse`, `TmdbKnownForItem`
- `TmdbSeasonResponse`, `TmdbEpisodeItem`
- `TmdbMovieDetailWithAppend`, `TmdbTvDetailWithAppend`
- `TmdbCompany`, `TmdbPersonBrief`

### Enrichment Data Classes (in TmdbMetadataService.kt)
- `TmdbEnrichment` — full enrichment result
- `TmdbDetails` — movie/TV details
- `TmdbEpisodeEnrichment` — single episode data
- `TmdbImages` — image collections
- `TmdbCastMember` — cast member
- `TmdbPersonDetail`, `TmdbKnownFor` — person data

## Pitfalls
- **TmdbVideo has `id: String`** — must pass `id = it.id` when constructing
- **Map key type mismatch:** episode cache uses `Map<Pair<Int, Int>, TmdbEpisodeEnrichment>` but `associate { ep.seasonNumber to ep }` creates `Map<Int, TmdbEpisodeItem>` — use `.mapKeys { (key, _) -> seasonNumber to key }` to fix
- **`return` in lambda:** `withContext` lambdas don't allow bare `return` — use `return@withContext`
- **`TmdbSimilarResult` already exists** in TmdbApi.kt with `id: Int` — don't redefine it

## Files Modified
- `TmdbApi.kt` — 10 new API methods + 15 new data classes
- NEW: `TmdbMetadataService.kt` — parallel enrichment service
