const BASE = 'https://api.themoviedb.org/3'; async function get(pathname, key) { const sep = pathname.includes('?') ? '&' : '?'; const res = await fetch(`${BASE}${pathname}${sep}api_key=${encodeURIComponent(key)}`); if (!res.ok) throw new Error(`TMDB HTTP ${res.status} for ${pathname}`); return res.json(); } function search(query, key) { return get( `/search/multi?query=${encodeURIComponent(query)}&include_adult=false&language=en-US&page=1`, key ).then((r) => (r.results || []).filter((m) => m.media_type === 'movie' || m.media_type === 'tv').slice(0, 15) ); } function trending(mediaType, timeWindow, key) { const type = ['movie', 'tv', 'all'].includes(mediaType) ? mediaType : 'all'; const window_ = timeWindow === 'day' ? 'day' : 'week'; return get(`/trending/${type}/${window_}?language=en-US`, key).then((r) => (r.results || []).slice(0, 20) ); } function getSeasons(tvId, key) { return get(`/tv/${tvId}?language=en-US`, key).then((r) => (r.seasons || []).filter((s) => s.season_number > 0 && (s.episode_count || 0) > 0) ); } function getEpisodes(tvId, seasonNumber, key) { return get(`/tv/${tvId}/season/${seasonNumber}?language=en-US`, key).then((r) => (r.episodes || []).slice().sort((a, b) => a.episode_number - b.episode_number) ); } function details(type, id, key) { return get(`/${type}/${id}?language=en-US&append_to_response=images`, key); } module.exports = { search, trending, getSeasons, getEpisodes, details };