#!/usr/bin/env python3
"""
External API clients for TMDB, OMDb, and Jellyseerr
"""
import json
import os
import time
from datetime import datetime, timezone
from typing import Dict, Any, List, Optional, Tuple
from urllib.parse import urlencode, quote
from urllib.request import Request as UrlRequest, urlopen
from urllib.error import URLError, HTTPError

from core.logging import _log


def _get_json(url: str, timeout: int = 20, headers: Dict[str, str] = None, suppress_404: bool = False) -> Optional[Dict[str, Any]]:
    """Make GET request and return JSON"""
    try:
        req = UrlRequest(url, headers=headers or {"Accept": "application/json"})
        with urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except HTTPError as e:
        # Handle specific HTTP errors more gracefully
        if suppress_404 and e.code in [400, 404]:
            _log("DEBUG", f"TVDB API: {url} - item not found (HTTP {e.code}) - this is expected")
            return None
        else:
            _log("WARNING", f"GET {url} failed: HTTP Error {e.code}: {e.reason}")
            return None
    except Exception as e:
        _log("WARNING", f"GET {url} failed: {e}")
        return None


def _parse_date_to_iso(date_str: str) -> Optional[str]:
    """Parse various date formats to ISO string"""
    if not date_str or date_str == "N/A":
        return None
    try:
        if len(date_str) == 10 and date_str[4] == "-":  # YYYY-MM-DD
            dt = datetime.fromisoformat(date_str).replace(tzinfo=timezone.utc)
        else:
            dt = datetime.fromisoformat(date_str.replace("Z", "+00:00")).astimezone(timezone.utc)
        return dt.isoformat(timespec="seconds")
    except Exception:
        return None


class TVDBClient:
    """The TV Database API client for IMDB to TVDB ID conversion"""
    
    def __init__(self, api_key: str = None):
        self.api_key = api_key or os.environ.get("TVDB_API_KEY", "")
        self.base_url = "https://api4.thetvdb.com/v4"
        self._token = None
        self._token_expires = 0
    
    def _get_token(self) -> Optional[str]:
        """Get TVDB auth token (cached)"""
        if not self.api_key:
            _log("DEBUG", "TVDB: No API key provided")
            return None
            
        if time.time() < self._token_expires and self._token:
            return self._token
            
        try:
            _log("DEBUG", f"TVDB: Authenticating with API key: {self.api_key[:8]}...")
            req = UrlRequest(
                f"{self.base_url}/login",
                data=json.dumps({"apikey": self.api_key}).encode('utf-8'),
                headers={"Content-Type": "application/json"}
            )
            with urlopen(req, timeout=10) as resp:
                data = json.loads(resp.read().decode("utf-8"))
                _log("DEBUG", f"TVDB login response: {data}")
                if data.get("status") == "success":
                    self._token = data["data"]["token"]
                    self._token_expires = time.time() + 3600  # 1 hour
                    _log("INFO", f"✅ TVDB: Authentication successful")
                    return self._token
                else:
                    _log("WARNING", f"TVDB login failed: {data}")
        except Exception as e:
            _log("WARNING", f"TVDB login failed: {e}")
        return None
    
    def imdb_to_tvdb_series_id(self, imdb_id: str) -> Optional[str]:
        """Convert IMDB ID to TVDB series ID using TVDB v4 API"""
        token = self._get_token()
        if not token:
            return None
            
        try:
            # Try the official v4 search endpoint first
            # According to docs: /search?query=imdb_id&type=series
            url = f"{self.base_url}/search?query={imdb_id}&type=series&meta=translations"
            headers = {"Authorization": f"Bearer {token}"}
            
            _log("DEBUG", f"TVDB: Searching for {imdb_id} using /search endpoint")
            data = _get_json(url, headers=headers, suppress_404=True)
            
            if data and data.get("status") == "success" and data.get("data"):
                series_list = data["data"]
                _log("DEBUG", f"TVDB search response: found {len(series_list)} results")
                
                # Look for exact IMDB match in results
                for series in series_list:
                    # Check if this series has the IMDB ID we're looking for
                    remote_ids = series.get("remote_ids", [])
                    for remote in remote_ids:
                        if (remote.get("source_name") == "IMDB" and 
                            remote.get("remote_id") == imdb_id):
                            tvdb_id = series.get("tvdb_id") or series.get("id")
                            if tvdb_id:
                                _log("INFO", f"✅ TVDB: Found series {imdb_id} → {tvdb_id}")
                                return str(tvdb_id)
                
                # If no exact match, try the first result if it looks promising
                if series_list:
                    first_result = series_list[0]
                    tvdb_id = first_result.get("tvdb_id") or first_result.get("id")
                    if tvdb_id:
                        _log("INFO", f"✅ TVDB: Found series {imdb_id} → {tvdb_id} (first result)")
                        return str(tvdb_id)
            
            # If search didn't work, try the legacy remoteid endpoint
            _log("DEBUG", f"TVDB: Trying legacy remoteid endpoint for {imdb_id}")
            url = f"{self.base_url}/search/remoteid?remoteId={imdb_id}&type=series"
            data = _get_json(url, headers=headers, suppress_404=True)
            
            if data and data.get("status") == "success" and data.get("data"):
                series_list = data["data"]
                if series_list and len(series_list) > 0:
                    tvdb_id = series_list[0].get("id")
                    if tvdb_id:
                        _log("INFO", f"✅ TVDB: Found series {imdb_id} → {tvdb_id} (legacy endpoint)")
                        return str(tvdb_id)
            
            # If we get here, the series wasn't found in TVDB
            _log("DEBUG", f"TVDB: No series found for IMDb {imdb_id} (not available in TVDB)")
            
        except Exception as e:
            _log("WARNING", f"TVDB API error for {imdb_id}: {e}")
        
        return None


class TMDBClient:
    """The Movie Database API client"""
    
    def __init__(self, api_key: str = None, primary_country: str = "US"):
        self.api_key = api_key or os.environ.get("TMDB_API_KEY", "")
        self.primary_country = primary_country.upper()
        self.enabled = bool(self.api_key)
    
    def _get(self, path: str, params: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
        """Make GET request to TMDB API"""
        if not self.enabled:
            return None
        
        params = params or {}
        params["api_key"] = self.api_key
        url = f"https://api.themoviedb.org/3{path}?{urlencode(params)}"
        return _get_json(url, timeout=20)
    
    def find_by_imdb(self, imdb_id: str) -> Optional[Dict[str, Any]]:
        """Find movie by IMDb ID"""
        result = self._get(f"/find/{quote(imdb_id)}", {"external_source": "imdb_id"})
        if result and result.get("movie_results"):
            return result["movie_results"][0]
        return None
    
    def get_movie_details(self, tmdb_id: int) -> Optional[Dict[str, Any]]:
        """Get detailed movie information"""
        return self._get(f"/movie/{tmdb_id}")
    
    def get_digital_release_date(self, imdb_id: str) -> Optional[str]:
        """Get digital release date for a movie"""
        _log("INFO", f"🔍 TMDB: Looking for digital release date for {imdb_id}")
        movie = self.find_by_imdb(imdb_id)
        if not movie:
            _log("WARNING", f"❌ TMDB: Movie not found for {imdb_id}")
            return None
        
        tmdb_id = movie.get("id")
        _log("INFO", f"✅ TMDB: Found movie ID {tmdb_id} for {imdb_id}")
        if not tmdb_id:
            return None
        
        release_dates = self._get(f"/movie/{tmdb_id}/release_dates")
        if not release_dates:
            _log("WARNING", f"❌ TMDB: No release dates data for movie {tmdb_id}")
            return None
        
        _log("INFO", f"🔍 TMDB: Got release dates data, looking for {self.primary_country} digital releases")
        
        # Debug: Show all available countries
        countries = [entry.get("iso_3166_1") for entry in release_dates.get("results", [])]
        _log("INFO", f"📍 TMDB: Available countries: {countries}")
        
        for entry in release_dates.get("results", []):
            country = entry.get("iso_3166_1", "").upper()
            if country != self.primary_country:
                continue
                
            _log("INFO", f"🎯 TMDB: Found {country} release data")
            releases = entry.get("release_dates", [])
            _log("INFO", f"🎬 TMDB: Release types available: {[r.get('type') for r in releases]}")
            
            # Collect all available releases with their types and dates
            available_releases = []
            for release in releases:
                release_type = release.get("type")
                release_date = release.get("release_date")
                _log("INFO", f"📅 TMDB: Type {release_type}, Date: {release_date}")
                
                if release_date:
                    parsed_date = _parse_date_to_iso(release_date)
                    if parsed_date:
                        available_releases.append((release_type, parsed_date))
            
            # Apply TMDB release type priority order
            tmdb_priority = self._get_tmdb_type_priority()
            for preferred_type in tmdb_priority:
                for release_type, parsed_date in available_releases:
                    if release_type == preferred_type:
                        release_type_names = {
                            1: "Premiere", 2: "Limited Theatrical", 3: "Theatrical", 
                            4: "Digital", 5: "Physical", 6: "TV Premiere"
                        }
                        type_name = release_type_names.get(release_type, f"Type {release_type}")
                        _log("INFO", f"✅ TMDB: Selected {type_name} release date: {parsed_date} (priority: {tmdb_priority})")
                        return parsed_date
        
        _log("WARNING", f"❌ TMDB: No release dates found for {imdb_id} in {self.primary_country}")
        
        # Fallback: First try English-speaking countries, then any country
        english_speaking_countries = {"GB", "CA", "AU", "NZ", "IE"}  # UK, Canada, Australia, New Zealand, Ireland
        
        # First pass: Try English-speaking countries
        _log("INFO", f"🇺🇸 TMDB: Trying English-speaking countries fallback for {imdb_id}")
        for entry in release_dates.get("results", []):
            country = entry.get("iso_3166_1", "").upper()
            if country not in english_speaking_countries:
                continue
                
            _log("INFO", f"🎯 TMDB: Checking English-speaking country {country}")
            
            releases = entry.get("release_dates", [])
            if not releases:
                continue
            
            # Collect all available releases with their types and dates
            available_releases = []
            for release in releases:
                release_type = release.get("type")
                release_date = release.get("release_date")
                
                if release_date:
                    parsed_date = _parse_date_to_iso(release_date)
                    if parsed_date:
                        available_releases.append((release_type, parsed_date))
            
            # Apply TMDB release type priority order
            tmdb_priority = self._get_tmdb_type_priority()
            for preferred_type in tmdb_priority:
                for release_type, parsed_date in available_releases:
                    if release_type == preferred_type:
                        release_type_names = {
                            1: "Premiere", 2: "Limited Theatrical", 3: "Theatrical", 
                            4: "Digital", 5: "Physical", 6: "TV Premiere"
                        }
                        type_name = release_type_names.get(release_type, f"Type {release_type}")
                        _log("INFO", f"✅ TMDB: Using English-speaking {country} {type_name} release date: {parsed_date}")
                        return parsed_date
        
        # Second pass: Try any remaining country as last resort
        _log("INFO", f"🌍 TMDB: Trying any available country as last resort for {imdb_id}")
        for entry in release_dates.get("results", []):
            country = entry.get("iso_3166_1", "").upper()
            if country in english_speaking_countries or country == self.primary_country:
                continue  # Already tried these
                
            _log("INFO", f"🎯 TMDB: Checking fallback country {country}")
            
            releases = entry.get("release_dates", [])
            if not releases:
                continue
            
            # Collect all available releases with their types and dates
            available_releases = []
            for release in releases:
                release_type = release.get("type")
                release_date = release.get("release_date")
                
                if release_date:
                    parsed_date = _parse_date_to_iso(release_date)
                    if parsed_date:
                        available_releases.append((release_type, parsed_date))
            
            # Apply TMDB release type priority order
            tmdb_priority = self._get_tmdb_type_priority()
            for preferred_type in tmdb_priority:
                for release_type, parsed_date in available_releases:
                    if release_type == preferred_type:
                        release_type_names = {
                            1: "Premiere", 2: "Limited Theatrical", 3: "Theatrical", 
                            4: "Digital", 5: "Physical", 6: "TV Premiere"
                        }
                        type_name = release_type_names.get(release_type, f"Type {release_type}")
                        _log("INFO", f"✅ TMDB: Using fallback {country} {type_name} release date: {parsed_date}")
                        return parsed_date
        
        _log("WARNING", f"❌ TMDB: No release dates found for {imdb_id} in any country")
        return None
    
    def _get_tmdb_type_priority(self) -> List[int]:
        """Get TMDB release type priority order from environment"""
        # Default priority: Digital first, then Physical, then Theatrical, then others
        default_priority = "4,5,3,2,6,1"  # digital,physical,theatrical,limited,tv,premiere
        
        priority_str = os.environ.get("TMDB_TYPE_PRIORITY", default_priority)
        try:
            # Parse comma-separated numbers
            priority_list = [int(x.strip()) for x in priority_str.split(",") if x.strip().isdigit()]
            if priority_list:
                _log("DEBUG", f"TMDB type priority: {priority_list}")
                return priority_list
            else:
                _log("WARNING", f"Invalid TMDB_TYPE_PRIORITY '{priority_str}', using default")
                return [4, 5, 3, 2, 6, 1]
        except Exception as e:
            _log("WARNING", f"Error parsing TMDB_TYPE_PRIORITY: {e}, using default")
            return [4, 5, 3, 2, 6, 1]
    
    def get_theatrical_release_date(self, imdb_id: str) -> Optional[str]:
        """Get theatrical release date for a movie"""
        movie = self.find_by_imdb(imdb_id)
        if not movie:
            return None
        
        tmdb_id = movie.get("id")
        if not tmdb_id:
            return None
        
        release_dates = self._get(f"/movie/{tmdb_id}/release_dates")
        if not release_dates:
            return None
        
        for entry in release_dates.get("results", []):
            if entry.get("iso_3166_1", "").upper() != self.primary_country:
                continue
            
            for release in entry.get("release_dates", []):
                if release.get("type") == 3 and release.get("release_date"):  # Theatrical release
                    return _parse_date_to_iso(release["release_date"])
        
        return None
    
    def get_physical_release_date(self, imdb_id: str) -> Optional[str]:
        """Get physical release date (DVD/Blu-ray) for a movie"""
        movie = self.find_by_imdb(imdb_id)
        if not movie:
            return None
        
        tmdb_id = movie.get("id")
        if not tmdb_id:
            return None
        
        release_dates = self._get(f"/movie/{tmdb_id}/release_dates")
        if not release_dates:
            return None
        
        for entry in release_dates.get("results", []):
            if entry.get("iso_3166_1", "").upper() != self.primary_country:
                continue
            
            for release in entry.get("release_dates", []):
                if release.get("type") == 5 and release.get("release_date"):  # Physical release
                    return _parse_date_to_iso(release["release_date"])
        
        return None
    
    def get_tv_season_episodes(self, tv_id: int, season_number: int) -> Dict[int, str]:
        """Get episode air dates for a TV season"""
        result = self._get(f"/tv/{tv_id}/season/{season_number}")
        episodes = {}
        
        if result:
            for episode in result.get("episodes", []):
                ep_num = episode.get("episode_number")
                air_date = episode.get("air_date")
                if isinstance(ep_num, int) and air_date:
                    episodes[ep_num] = air_date
        
        return episodes


class OMDbClient:
    """Open Movie Database API client"""
    
    def __init__(self, api_key: str = None):
        self.api_key = api_key or os.environ.get("OMDB_API_KEY", "")
        self.enabled = bool(self.api_key)
    
    def get_movie_details(self, imdb_id: str) -> Optional[Dict[str, Any]]:
        """Get movie details from OMDb"""
        if not self.enabled:
            return None
        
        params = {"i": imdb_id, "apikey": self.api_key}
        url = f"http://www.omdbapi.com/?{urlencode(params)}"
        result = _get_json(url, timeout=15)
        
        if result and result.get("Response") == "True":
            return result
        return None
    
    def get_dvd_release_date(self, imdb_id: str) -> Optional[str]:
        """Get DVD/digital release date"""
        details = self.get_movie_details(imdb_id)
        if not details:
            return None
        
        dvd_date = details.get("DVD") or details.get("Released")
        if not dvd_date or dvd_date == "N/A":
            return None
        
        # Try to parse various date formats
        for fmt in ("%d %b %Y", "%d %B %Y", "%Y-%m-%d"):
            try:
                dt = datetime.strptime(dvd_date, fmt).replace(tzinfo=timezone.utc)
                return dt.isoformat(timespec="seconds")
            except Exception:
                continue
        
        return None
    
    def get_tv_season_episodes(self, imdb_id: str, season_number: int) -> Dict[int, str]:
        """Get episode release dates for a TV season"""
        if not self.enabled:
            return {}
        
        params = {"i": imdb_id, "Season": str(season_number), "apikey": self.api_key}
        url = f"http://www.omdbapi.com/?{urlencode(params)}"
        result = _get_json(url, timeout=15)
        
        episodes = {}
        if result and result.get("Response") == "True":
            for episode in result.get("Episodes", []):
                try:
                    ep_num = int(episode.get("Episode", 0))
                    released = episode.get("Released")
                    if ep_num and released and released != "N/A":
                        episodes[ep_num] = released
                except Exception:
                    continue
        
        return episodes


class JellyseerrClient:
    """Jellyseerr API client"""
    
    def __init__(self, base_url: str = None, api_key: str = None):
        self.base_url = (base_url or os.environ.get("JELLYSEERR_URL", "")).rstrip("/")
        self.api_key = api_key or os.environ.get("JELLYSEERR_API_KEY", "")
        self.enabled = bool(self.base_url and self.api_key)
    
    def _get(self, path: str) -> Optional[Dict[str, Any]]:
        """Make GET request to Jellyseerr API"""
        if not self.enabled:
            return None
        
        url = f"{self.base_url}/api/v1{path}"
        headers = {"X-Api-Key": self.api_key, "Accept": "application/json"}
        return _get_json(url, timeout=20, headers=headers)
    
    def get_movie_details(self, tmdb_id: int) -> Optional[Dict[str, Any]]:
        """Get movie details from Jellyseerr"""
        return self._get(f"/movie/{tmdb_id}")
    
    def get_digital_release_dates(self, tmdb_id: int) -> List[str]:
        """Get digital release date candidates from Jellyseerr"""
        details = self.get_movie_details(tmdb_id)
        if not details:
            return []
        
        candidates = []
        
        # Check direct fields
        for field in ("digitalReleaseDate", "physicalReleaseDate", "vodReleaseDate"):
            value = details.get(field)
            if value:
                iso_date = _parse_date_to_iso(value)
                if iso_date:
                    candidates.append(iso_date)
        
        # Check release dates array
        for array_field in ("releaseDates", "releases", "dates"):
            release_array = details.get(array_field)
            if not isinstance(release_array, list):
                continue
            
            for release in release_array:
                if not isinstance(release, dict):
                    continue
                
                release_type = (release.get("type") or release.get("label") or "").lower()
                release_date = release.get("date") or release.get("releaseDate")
                
                if release_date and ("digital" in release_type or "vod" in release_type or "stream" in release_type):
                    iso_date = _parse_date_to_iso(release_date)
                    if iso_date:
                        candidates.append(iso_date)
        
        return candidates


class ExternalClientManager:
    """Manager for all external API clients"""
    
    def __init__(self):
        # Get country from environment, default to US
        tmdb_country = os.environ.get("TMDB_COUNTRY", "US")
        _log("INFO", f"🌍 TMDB: Initializing with country: {tmdb_country}")
        
        self.tmdb = TMDBClient(primary_country=tmdb_country)
        self.omdb = OMDbClient()
        self.jellyseerr = JellyseerrClient()
        self.tvdb = TVDBClient()
    
    def get_release_date_by_priority(self, imdb_id: str, priority_order: List[str], enable_smart_validation: bool = True) -> Optional[Tuple[str, str]]:
        """Get release date using configurable priority order with smart date validation"""
        
        # Get all possible release dates
        release_options = {}
        
        if self.tmdb.enabled:
            # Digital release
            digital_date = self.tmdb.get_digital_release_date(imdb_id)
            if digital_date:
                release_options["digital"] = (digital_date, "tmdb:digital")
            
            # Physical release
            physical_date = self.tmdb.get_physical_release_date(imdb_id)
            if physical_date:
                release_options["physical"] = (physical_date, "tmdb:physical")
            
            # Theatrical release
            theatrical_date = self.tmdb.get_theatrical_release_date(imdb_id)
            if theatrical_date:
                release_options["theatrical"] = (theatrical_date, "tmdb:theatrical")
        
        # Add OMDb options
        if self.omdb.enabled:
            omdb_date = self.omdb.get_dvd_release_date(imdb_id)
            if omdb_date and "physical" not in release_options:
                release_options["physical"] = (omdb_date, "omdb:dvd")
        
        # Add Jellyseerr digital releases
        if self.jellyseerr.enabled and self.tmdb.enabled and "digital" not in release_options:
            tmdb_movie = self.tmdb.find_by_imdb(imdb_id)
            if tmdb_movie:
                tmdb_id = tmdb_movie.get("id")
                if tmdb_id:
                    jellyseerr_dates = self.jellyseerr.get_digital_release_dates(tmdb_id)
                    if jellyseerr_dates:
                        earliest_jellyseerr = min(jellyseerr_dates)
                        release_options["digital"] = (earliest_jellyseerr, "jellyseerr:digital")
        
        # Smart date validation: Check if priority order makes sense given the actual dates
        if enable_smart_validation and len(release_options) > 1:
            validated_choice = self._validate_date_choice(release_options, priority_order)
            if validated_choice:
                return validated_choice
        
        # Return first available option according to priority (fallback behavior)
        for priority in priority_order:
            if priority in release_options:
                return release_options[priority]
        
        return None
    
    def _validate_date_choice(self, release_options: Dict[str, Tuple[str, str]], priority_order: List[str]) -> Optional[Tuple[str, str]]:
        """Validate date choice and prefer theatrical if digital/physical are unreasonably late"""
        from datetime import datetime, timezone
        import os
        
        # Get configuration for maximum gap (default: 10 years)
        max_reasonable_gap_years = int(os.environ.get("MAX_RELEASE_DATE_GAP_YEARS", "10"))
        
        # Parse all available dates
        parsed_dates = {}
        for release_type, (date_str, source) in release_options.items():
            try:
                parsed_dates[release_type] = (datetime.fromisoformat(date_str.replace('Z', '+00:00')), source)
            except Exception:
                continue
        
        if not parsed_dates or "theatrical" not in parsed_dates:
            return None  # No smart validation possible without theatrical date
        
        theatrical_date, theatrical_source = parsed_dates["theatrical"]
        
        # Check each priority option against theatrical date
        for priority in priority_order:
            if priority == "theatrical":
                continue  # Skip theatrical in this validation
            
            if priority in parsed_dates:
                priority_date, priority_source = parsed_dates[priority]
                
                # Calculate the gap in years
                gap = (priority_date - theatrical_date).days / 365.25
                
                # If the gap is too large, skip this priority and continue
                if gap > max_reasonable_gap_years:
                    print(f"[SMART VALIDATION] {priority} date {priority_date.strftime('%Y-%m-%d')} is {gap:.1f} years after theatrical {theatrical_date.strftime('%Y-%m-%d')}, preferring theatrical")
                    continue
                
                # This priority option is reasonable, use it
                return (priority_date.isoformat(timespec="seconds"), f"{priority_source} (validated)")
        
        # If all priority options are unreasonable, fall back to theatrical
        if "theatrical" in release_options:
            theatrical_date_str, theatrical_source = release_options["theatrical"]
            return (theatrical_date_str, f"{theatrical_source} (smart fallback)")
        
        return None
    
    def get_digital_release_candidates(self, imdb_id: str) -> List[Tuple[str, str]]:
        """Get digital release date candidates from all sources (legacy method)"""
        candidates = []
        
        # Try the new priority system with digital-first fallback
        result = self.get_release_date_by_priority(imdb_id, ["digital", "physical", "theatrical"])
        if result:
            candidates.append(result)
        
        return candidates
    
    def get_earliest_digital_release(self, imdb_id: str) -> Optional[Tuple[str, str]]:
        """Get the earliest digital release date (legacy method)"""
        candidates = self.get_digital_release_candidates(imdb_id)
        return candidates[0] if candidates else None
    
    def get_tvdb_series_id(self, imdb_id: str) -> Optional[str]:
        """Get TVDB series ID from IMDB ID"""
        # Check if TVDB lookups are disabled
        if os.environ.get("DISABLE_TVDB", "false").lower() in ["true", "1", "yes"]:
            _log("DEBUG", "TVDB lookups disabled via DISABLE_TVDB environment variable")
            return None
            
        if not self.tvdb.api_key:
            _log("INFO", "TVDB API key not configured, skipping TVDB ID lookup (set TVDB_API_KEY to enable)")
            return None
        
        return self.tvdb.imdb_to_tvdb_series_id(imdb_id)


if __name__ == "__main__":
    # Test the clients
    manager = ExternalClientManager()
    
    test_imdb = "tt1596343"  # Example IMDb ID
    digital_candidates = manager.get_digital_release_candidates(test_imdb)
    print(f"Digital release candidates for {test_imdb}: {digital_candidates}")
    
    earliest = manager.get_earliest_digital_release(test_imdb)
    if earliest:
        print(f"Earliest digital release: {earliest[0]} ({earliest[1]})")
    else:
        print("No digital release dates found")