import requests
import traceback
from pathlib import Path
from requests.exceptions import ConnectionError as RequestsConnectionError, Timeout, RequestException
from urllib3.exceptions import NewConnectionError, MaxRetryError

from shared.utils import Logger, TokenManager, ConfigManager

# =============== News Service ===============
class NewsService():
    def __init__(self):
        # Logger 
        self.logger = Logger.create_logger(logger_name = "News Service", log_file_name = "validator_app")
        
        # Class Instances
        self.tokenManager = TokenManager()
        self.configManager = ConfigManager()
        
        # In memory
        self._newsDevelopment: list[dict[str, str]] = []
        self._newsPublic: list[dict[str, str]] = []
        
    # ========== News ==========
    def get_all_news(self, production: bool) -> None:
        try:
            tokens: dict[str, str] = self.tokenManager.read_tokens()
            
            if production == True:
                self._newsPublic.clear()
                
                newsRequestUrl: str = self.configManager.get_value(
                    section = "PROVIDER", key = self.configManager.get_value(section = "SERVICES", key = "production")) + self.configManager.get_value(section = "METADATA", key = "news") + "1"
                
                newsResponse = self.request(url = newsRequestUrl, tokens = tokens)
                if type(newsResponse) == str:
                    return []
                
                newsList: list[dict[str, str]] = newsResponse.json()
                newsList.sort(key=lambda x: x["id"], reverse=True)
                for news in newsList:
                    yyyy, mm, dd = news["date"].split('-')
                    formattedDate = f"{dd}/{mm}/{yyyy}"
                    
                    newsData = {
                        "Title" : news["title_ro"],
                        "ReleaseDate" : formattedDate,
                        "Description" : news["description_ro"]
                    }
                    if newsData not in self._newsPublic:
                        self._newsPublic.append(newsData)
                
                
            else:
                self._newsDevelopment.clear()
                newsRequestUrl: str = self.configManager.get_value(
                    section = "PROVIDER", key = self.configManager.get_value(section = "SERVICES", key = "development")) + self.configManager.get_value(section = "METADATA", key = "news") + "2"

                newsResponse = self.request(url = newsRequestUrl, tokens = tokens)
                if type(newsResponse) == str:
                    return []
                
                newsList: list[dict[str, str]] = newsResponse.json()
                for news in newsList:
                    yyyy, mm, dd = news["date"].split('-')
                    formattedDate = f"{dd}/{mm}/{yyyy}"
                    
                    newsData = {
                        "Title" : news["title_ro"],
                        "ReleaseDate" : formattedDate,
                        "Description" : news["description_ro"]
                    }
                    if newsData not in self._newsDevelopment:
                        self._newsDevelopment.append(newsData)
                    
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.get_all_news.__name__}] "
                f"Failed to get all the validation kits. \n{traceBack}")
    # ==========================
    
    # ========== Request ==========
    def request(self, url: str, tokens: dict[str, str]) -> requests.Response | str:
        """Request data based on url and tokens."""
        try:
            response = requests.get(
                url = url,
                headers = {'Authorization': f'JWT {tokens["access"]}'},
                timeout = 60
            )
            
            if response.status_code != 200:
                return "Error"
            
            return response
        
        except NewConnectionError as e:
            # This catches DNS failures, refused connections, etc.
            self.logger.error(f"[{self.__class__.__name__}.{self.request.__name__}] No internet connection or host unreachable: {e}")
            return "ConnectionError"
        
        except MaxRetryError as e:
            # This catches DNS failures, refused connections, etc.
            self.logger.error(f"[{self.__class__.__name__}.{self.request.__name__}] No internet connection or host unreachable: {e}")
            return "ConnectionError"
        
        except RequestsConnectionError as e:
            # This catches DNS failures, refused connections, etc.
            self.logger.error(f"[{self.__class__.__name__}.{self.request.__name__}] No internet connection or host unreachable: {e}")
            return "ConnectionError"
        
        except ConnectionError as e:
            # This catches DNS failures, refused connections, etc.
            self.logger.error(f"[{self.__class__.__name__}.{self.request.__name__}] No internet connection or host unreachable: {e}")
            return "ConnectionError"
            
        except Timeout as e:
            self.logger.error(f"[{self.__class__.__name__}.{self.request.__name__}] Request timed out: {e}")
            return "ConnectionError"
            
        except RequestException as e:
            # Catches all other requests-related errors
            self.logger.error(f"[{self.__class__.__name__}.{self.request.__name__}] Request failed: {e}")
            return "ConnectionError"
            
        except Exception as e:
            self.logger.error(f"[Class '{self.__class__.__name__}' - Function '{self.request.__name__}'] An error has occurred: {e}")
            return "Error"
    # =============================
# ============================================