import os, requests, time
from datetime import datetime

from .logging_utils import get_ffx_logger


class TMDB_REQUEST_EXCEPTION(Exception):
    def __init__(self, statusCode, statusMessage):
        errorMessage = f"TMDB query failed with status code {statusCode}: {statusMessage}"
        super().__init__(errorMessage)

class TMDB_API_KEY_NOT_PRESENT_EXCEPTION(Exception):
    def __str__(self):
        return 'TMDB api key is not available, please set environment variable TMDB_API_KEY'

class TMDB_EXCESSIVE_USAGE_EXCEPTION(Exception):
    def __str__(self):
        return 'Rate limit was triggered too often'


class TmdbController():

    DEFAULT_LANGUAGE = 'de-DE'

    RATE_LIMIT_WAIT_SECONDS = 10
    RATE_LIMIT_RETRIES = 3

    def __init__(self, context = None):
        self.__context = context

        if context is None:
            self.__logger = get_ffx_logger()
        else:
            self.__logger = context['logger']

        self.__tmdbApiKey = os.environ.get('TMDB_API_KEY', None)
        if self.__tmdbApiKey is None:
            raise TMDB_API_KEY_NOT_PRESENT_EXCEPTION
        
        self.tmdbLanguage = TmdbController.DEFAULT_LANGUAGE


    def getTmdbRequest(self, tmdbUrl):
        retries = TmdbController.RATE_LIMIT_RETRIES
        while True:
            response = requests.get(tmdbUrl)
            if response.status_code == 429:
                if not retries:
                    raise TMDB_EXCESSIVE_USAGE_EXCEPTION()
                self.__logger.warning('TMDB Rate limit (status_code 429)')
                time.sleep(TmdbController.RATE_LIMIT_WAIT_SECONDS)
                retries -= 1
            else:
                jsonResult = response.json()
                if ('success' in jsonResult.keys()
                            and not jsonResult['success']):
                    raise TMDB_REQUEST_EXCEPTION(jsonResult['status_code'], jsonResult['status_message'])
                return jsonResult


    def queryShow(self, showId):
        """
        First level keys in the response object:
        adult bool
        backdrop_path str
        created_by []
        episode_run_time []
        first_air_date str YYYY-MM-DD
        genres []
        homepage str
        id int
        in_production bool
        languages []
        last_air_date str YYYY-MM-DD
        last_episode_to_air {}
        name str
        next_episode_to_air null
        networks []
        number_of_episodes int
        number_of_seasons int
        origin_country []
        original_language str
        original_name str
        overview str
        popularity float
        poster_path str
        production_companies []
        production_countries []
        seasons []
        spoken_languages []
        status str
        tagline str
        type str
        vote_average float
        vote_count int
        """
        
        urlParams = f"?language={self.tmdbLanguage}&api_key={self.__tmdbApiKey}"
        
        tmdbUrl = f"https://api.themoviedb.org/3/tv/{showId}{urlParams}"

        return self.getTmdbRequest(tmdbUrl)


    def getShowNameAndYear(self, showId: int):
    
        showResult = self.queryShow(int(showId))
        firstAirDate = datetime.strptime(showResult['first_air_date'], '%Y-%m-%d')

        return str(showResult['name']), int(firstAirDate.year)


    def queryEpisode(self, showId, season, episode):
        """
        First level keys in the response object:
        air_date str 'YYY-MM-DD'
        crew []
        episode_number int
        guest_stars []
        name str
        overview str
        id int
        production_code
        runtime int
        season_number int
        still_path str '/filename.jpg'
        vote_average float
        vote_count int
        """
        
        urlParams = f"?language={self.tmdbLanguage}&api_key={self.__tmdbApiKey}"
        
        tmdbUrl = f"https://api.themoviedb.org/3/tv/{showId}/season/{season}/episode/{episode}{urlParams}"

        return self.getTmdbRequest(tmdbUrl)
