import abc
import json
import requests
from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional

class BaseLLM(abc.ABC):
    """ Classe abstraite pour les LLM """
    
    def __init__(self, modele: str):
        self.modele: str = modele
        self.prompt_system:str = ""
        self.params: Dict[str, Any] = {
            "temperature": 0.8,
            "top_p": 0.9,
            "top_k": 40,
            "max_tokens": 1000,
            "presence_penalty": 0,
            "frequency_penalty": 0,
            "stop": None
        }
        
        self.dureeTraitement: timedelta = timedelta()
        self.reponseErreur: bool = False
        
        self.heureDepart: Optional[datetime] = None
        self.heureFin: Optional[datetime] = None
        
    @abc.abstractmethod
    def urlBase(self) -> str:
        pass
    
    @abc.abstractmethod
    def cleAPI(self) -> str:
        pass
    
    @abc.abstractmethod
    def urlFonction(self) -> str:
        pass
    
    @abc.abstractmethod
    def _preparer_contenu(self, question: str) -> Dict[str, Any]:
        pass
    
    @abc.abstractmethod
    def _traiter_reponse(self, reponse: requests.Response) -> str:
        pass
    
    def interroger(self, question: str) -> str:
        url = self.urlBase() + self.urlFonction()
        headers = {"Content-Type": "application/json"}
        
        if self.cleAPI():
            headers["Authorization"] = f"Bearer {self.cleAPI()}"
            
        contenu = self._preparer_contenu(question)
        
        self.heureDepart = datetime.now()
        
        try:
            response = requests.post(url=url, headers=headers, json=contenu, timeout=120)
            self.heureFin = datetime.now()
            self.dureeTraitement = self.heureFin - self.heureDepart
            
            if response.status_code in [200, 201]:
                self.reponseErreur = False
                reponse = self._traiter_reponse(response)
                return reponse
            else:
                self.reponseErreur = True
                return response.text
            
        except Exception as e:
            self.heureFin = datetime.now()
            self.dureeTraitement = self.heureFin - self.heureDepart
            self.reponseErreur = True
            return str(e)
        
    def configurer(self, **kwargs):# méthode pour configurer les paramètres
        self.params.update(kwargs)
    
    