import re
from typing import List

from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.llms import OpenAI

from load_model import call_palm
from calling_apis import google_api_key, openai_api_key

def keywords_generator(topic : str,num_keywords=10, language='En', creativity='Original', model_name='Google Palm 2') -> str:
    
    '''
    Description: 
    
        Generates a list of short-tail keywords for a given topic using a large language model (LLM).
    '''
    
    '''
    Parameters:
    
        topic (str): Required Parameter -> The topic for which to generate keywords.
        num_keywords (int): Optional Parameter -> The number of keywords to generate. Default Value is 10
        language (str): Opitonal Parameter -> The language of the model.
        creativity (str): Optional Parameter -> Controling the randomness of the model. Default value is Original
        model_name (str): Optional Parameter -> select the LLM model. Default Value is Google Palm 2
        
    '''
    
    '''
    Returns:
        Keywords (str): A Text of list of keywords numbered with roman numerals for the given topic -> str datatype.
    '''
    temp = 0

    if creativity == 'Original':
        temp = 0
    elif creativity == 'Balanced':
        temp = 0.25
    elif creativity == 'Creative':
        temp = 0.5
    elif creativity == 'Spirited':
        temp = 0.75
    elif creativity == 'Visionary':
        temp = 1


    if model_name == 'Google Palm 2':
        llm = call_palm(google_api_key, temperature=temp)

    elif model_name == 'GPT-3.5':
        llm = OpenAI(model_name='gpt-3.5-turbo', openai_api_key=openai_api_key, temperature=temp)

    elif model_name == 'GPT-4':
        llm = OpenAI(model_name='gpt-4', openai_api_key=openai_api_key, temperature=temp)


    if language == 'En':

        keywords_prompt = f"Generate {num_keywords} SEO keywords related to '{topic}'."

        keywords_promptTemp = PromptTemplate(
        input_variables=["text_input"],
        template="You are a professional content creator and SEO Keywords Generator:\n\n{text_input}\n\nKeywords (number them with roman numerals):")

    elif language == 'Ar':

        keywords_prompt = f"قم بإنشاء {num_keywords} كلمة أساسية SEO متعلقة بـ '{topic}'."

        keywords_promptTemp = PromptTemplate(
            input_variables=["text_input"],
            template="أنت منشئ محتوى محترف ومولد كلمات أساسية SEO:\n\n{text_input}\n\nالكلمات الأساسية (قم بترقيمها بالأرقام الرومانية):")

    keywords_extraction_chain = LLMChain(llm=llm, prompt=keywords_promptTemp)
    keywords = keywords_extraction_chain.run(keywords_prompt)

    return keywords


def keywords_generator_long_tail(topic : str, num_keywords=10, language='En', creativity='Original', model_name='Google Palm 2') -> str:
    
    '''
    Description: 
    
        Generates a list of long-tail keywords for a given topic using a large language model (LLM).
    '''
    
    '''
    Parameters:
    
        topic (str): Required Parameter -> The topic for which to generate keywords.
        num_keywords (int): Optional Parameter -> The number of keywords to generate. Default Value is 10
        language (str): Opitonal Parameter -> The language of the model.
        creativity (str): Optional Parameter -> Controling the randomness of the model. Default value is Original
        model_name (str): Optional Parameter -> select the LLM model. Default Value is Google Palm 2
        
    '''
    
    '''
    Returns:
        Keywords (str): A Text of list of keywords numbered with roman numerals for the given topic -> str datatype.
    '''
    
    temp = 0

    if creativity == 'Original':
        temp = 0
    elif creativity == 'Balanced':
        temp = 0.25
    elif creativity == 'Creative':
        temp = 0.5
    elif creativity == 'Spirited':
        temp = 0.75
    elif creativity == 'Visionary':
        temp = 1


    if model_name == 'Google Palm 2':
        llm = call_palm(google_api_key, temperature=temp)

    elif model_name == 'GPT-3.5':
        llm = OpenAI(model_name='gpt-3.5-turbo', openai_api_key=openai_api_key, temperature=temp)

    elif model_name == 'GPT-4':
        llm = OpenAI(model_name='gpt-4', openai_api_key=openai_api_key, temperature=temp)

    if language == 'En':
        
        keywords_prompt = f"Generate {num_keywords} long-tail SEO keywords related to '{topic}'."

        keywords_promptTemp = PromptTemplate(
        input_variables=["text_input"],
        template="You are a professional content creator and SEO Keywords Generator:\n\n{text_input}\n\nKeywords (number them with roman numerals):")
    
    elif language == 'Ar':
        
        keywords_prompt = f"قم بإنشاء {num_keywords} كلمة أساسية SEO طويلة الذيل متعلقة بـ '{topic}'."

        keywords_promptTemp = PromptTemplate(
        input_variables=["text_input"],
        template="أنت منشئ محتوى محترف ومولد كلمات أساسية SEO:\n\n{text_input}\n\nالكلمات الأساسية (قم بترقيمها بالأرقام الرومانية):")

    keywords_extraction_chain = LLMChain(llm=llm, prompt=keywords_promptTemp)
    keywords = keywords_extraction_chain.run(keywords_prompt)

    return keywords

def filter_keywords(keywords : str) -> List[str]:
    '''
    Description: 
    
        Filters keywords to extract the keywords that numbered with roman numerals using regx
    '''
    
    '''
    Parameters:

        keywords (str): Required Parameter -> A Text of keywords Numbered with roman numerals to filter.
    '''
    
    '''
    Returns:
    
        filtered_keywords(list): A filtered list of keywords.
    '''
    
    pattern = r'\b[IVXLCDM]+\.\s*(.*?)(?:\n|$)'
    filtered_keywords = re.findall(pattern, keywords)
    
    return filtered_keywords


def process_keywords(list_keywords : List[str]) -> str:
    
    '''
    Description: 
        Formats a list of keywords into a comma-separated string.
    '''
    
    '''
    Parameters:

        list_keywords (list):Required Parameters -> A list of keywords to format.    
    '''
    
    '''
    Returns:
    
        formatted_keywords (str): A comma-separated string of keywords.
    '''
    formatted_keywords = ", ".join(list_keywords)
    return formatted_keywords