"""
Module for defining the base class of EDG models.

This file contains the abstract base class `EDGBaseModel`, which serves as a foundation for implementing various 
machine learning models. The class defines key methods that must be implemented by any derived model class 
to handle requests, send HTTP requests, and interact with APIs.

Classes
-------
EDGBaseModel(ABC)
    Abstract base class for EDG models, providing a standard structure for derived model implementations.

Methods
-------
__init__(api_key: str = None, base_url: str = None, model_name: str = None)
    Initializes the base model with API key, base URL, and model name.

execute_request(system_prompt: str, user_prompt: str, **kwargs) -> str
    Abstract method to process user input and generate model responses.
    Must be implemented by derived classes.

send_request(request: Dict[str, Any]) -> Dict[str, Any]
    Abstract method to send HTTP requests and handle server interactions.
    Must be implemented by derived classes.
"""

import requests
from abc import ABC, abstractmethod
from typing import Any, Dict

from edg4llm.utils.logger import custom_logger

logger = custom_logger('baseModel')


class EDGBaseModel(ABC):
    """
    Abstract base class for EDG models.

    This class defines the blueprint for machine learning model implementations. Derived classes must 
    implement methods to process user prompts, interact with APIs, and handle HTTP requests.

    Attributes
    ----------
    api_key : str
        The API key required for authenticating requests.
    
    base_url : str
        The base URL of the model API endpoint.
    
    model_name : str
        The name of the model, used to differentiate between various models.
    """

    def __init__(self, api_key: str = None, base_url: str = None, model_name: str = None):
        """
        Initializes the base model with API key, base URL, and model name.

        Parameters
        ----------
        api_key : str, optional
            The API key for authenticating requests. Default is None.

        base_url : str, optional
            The base URL of the model API endpoint. Default is None.

        model_name : str, optional
            The name of the model, used for identifying different models. Default is None.
        """
        self.api_key = api_key
        self.base_url = base_url
        self.model_name = model_name

    @abstractmethod
    def execute_request(self, system_prompt: str, user_prompt: str, **kwargs) -> str:
        """
        Abstract method to process and execute a request.

        This method must be implemented by derived classes. It processes user input and generates 
        responses based on a system prompt and additional parameters.

        Parameters
        ----------
        system_prompt : str
            The system-level instruction or prompt defining the role or behavior of the model.

        user_prompt : str
            The user's input or query for the model.

        kwargs : dict
            Additional parameters for processing the request.

        Returns
        -------
        str
            The response generated by the model.

        Notes
        -----
        - Derived classes should implement this method to handle the specific logic for generating responses.
        """
        pass

    @abstractmethod
    def send_request(self, request: Dict[str, Any]) -> Dict[str, Any]:
        """
        Abstract method to send HTTP requests.

        This method must be implemented by derived classes to handle API interactions and perform 
        error handling for HTTP requests.

        Parameters
        ----------
        request : dict
            A dictionary containing all necessary information for the HTTP request.

        Returns
        -------
        dict
            The server's response as a dictionary.

        Notes
        -----
        - Derived classes should implement this method to handle API-specific logic and error handling.
        """
        pass
