import os
import time

import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

def safe_mkdir(path):
    if not os.path.exists(path):
        os.mkdir(path)

def call_openai_chat(messages, model="gpt-4", temperature=0.0, max_tokens_in_use=2048):
    """
    Sends a request with a chat conversation to OpenAI's chat API and returns a response.

    Parameters:
        messages (list)
            A list of dictionaries containing the messages to send to the chatbot.
        model (str)
            The model to use for the chatbot. Default is "gpt-3.5-turbo".
        temperature (float)
            The temperature to use for the chatbot. Defaults to 0. Note that a temperature
            of 0 does not guarantee the same response (https://platform.openai.com/docs/models/gpt-3-5).
    
    Returns:
        response (Optional[dict])
            The response from OpenAI's chat API, if any.
    """
    num_attempts = 0
    while num_attempts < 10:
        try:
            response = openai.ChatCompletion.create(
                model=model,
                messages=messages,
                temperature=temperature,
                max_tokens=max_tokens_in_use
            )
            return response['choices'][0]['message']['content'].strip(), response['usage']
        except openai.error.AuthenticationError as e:
            print(e)
            return None
        except openai.error.RateLimitError as e:
            print(e)
            print("Sleeping for 10 seconds...")
            time.sleep(10)
            num_attempts += 1
        except openai.error.ServiceUnavailableError as e:
            print(e)
            print("Sleeping for 10 seconds...")
            time.sleep(10)
            num_attempts += 1
        except openai.error.InvalidRequestError as e:
            print(e)
            print(f"Trying with max-token={max_tokens_in_use} to max-token={max_tokens_in_use - 100}")
            max_tokens_in_use -= 100
        except Exception as e:
            print(e)
            print("other bugs, try again in 5 seconds...")
            time.sleep(5)


def merge_dicts(dicts):
    return {
        k : v 
        for d in dicts
        for k, v in d.items()
    }

def exec_safe(code_str, gvars=None, lvars=None):
    banned_phrases = ['import', '__']
    for phrase in banned_phrases:
        assert phrase not in code_str
  
    if gvars is None:
        gvars = {}
    if lvars is None:
        lvars = {}
    empty_fn = lambda *args, **kwargs: None
    custom_gvars = merge_dicts([
        gvars,
        {'exec': empty_fn, 'eval': empty_fn}
    ])
    
    exec(code_str, custom_gvars, lvars)