from abc import abstractmethod
from typing import Any, Dict, List, Tuple

from evalscope.perf.query_parameters import QueryParameters

class ApiPluginBase:
    def __init__(self, model_path: str) -> None:
        self.model_path = model_path
        
    @abstractmethod
    def build_request(self, messages: List[Dict], param: QueryParameters)->Dict:
        """Build a api request body.

        Args:
            messages (List[Dict]): The messages generated by dataset.
            param (QueryParameters): The query parameters.

        Raises:
            NotImplementedError: Not implemented.

        Returns:
            Dict: The api request body.
        """
        raise NotImplementedError
    
    @abstractmethod
    def parse_responses(self, 
                        responses: List, 
                        request: Any=None,
                        **kwargs:Any) -> Tuple[int, int]:
        """Parser responses and return number of request and response tokens.

        Args:
            responses (List[bytes]): List of http response body, for stream output,
                there are multiple responses, each is bytes, for general only one. 
            request (Any): The request body.

        Returns:
            Tuple: (Number of prompt_tokens and number of completion_tokens).
        """
        raise NotImplementedError  

    @staticmethod
    def replace_values(input_json: Any, model: str, prompt: str):
        if isinstance(input_json, dict):  
            for key, value in input_json.items():
                if isinstance(value, str):
                    input_json[key] = value.replace("%m", model).replace("%p", prompt)
                else:                    
                    ApiPluginBase.replace_values(value, model, prompt)  
        elif isinstance(input_json, list): 
            for idx, item in enumerate(input_json):
                if isinstance(item, str):
                    input_json[idx] = item.replace("%m", model).replace("%p", prompt)
                else:
                    ApiPluginBase.replace_values(item, model, prompt)
        elif isinstance(input_json, str):
            input_json = input_json.replace("%m", model).replace("%p", prompt)
        else:
            pass