import gradio as gr
import os
import json
import numpy as np
import requests
from openai import OpenAI
import time

def call_gpt3_5(prompt, api_key):
    client = OpenAI(api_key=api_key)
    try:
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "system", "content": "You are a Python expert capable of implementing specific functions for a Swarm Neural Network (SNN). Return only the Python code for the requested function, without any additional text."},
                {"role": "user", "content": prompt}
            ]
        )
        code = response.choices[0].message.content
        # Clean up the code: remove leading/trailing whitespace and any markdown code blocks
        code = code.strip()
        if code.startswith("```python"):
            code = code[10:]
        if code.endswith("```"):
            code = code[:-3]
        return code.strip()
    except Exception as e:
        return f"Error calling GPT-3.5: {str(e)}"

class Agent:
    def __init__(self, api_url):
        self.api_url = api_url
        self.data = None
        self.processing_time = 0

    def make_api_call(self):
        try:
            start_time = time.time()
            response = requests.get(self.api_url)
            if response.status_code == 200:
                self.data = response.json()
            else:
                self.data = {"error": f"API call failed with status code {response.status_code}"}
            self.processing_time = time.time() - start_time
        except Exception as e:
            self.data = {"error": str(e)}
            self.processing_time = time.time() - start_time

class SwarmNeuralNetwork:
    def __init__(self, api_url, num_agents, calls_per_agent, special_config):
        self.api_url = api_url
        self.num_agents = num_agents
        self.calls_per_agent = calls_per_agent
        self.special_config = special_config
        self.agents = [Agent(api_url) for _ in range(num_agents)]
        self.execution_time = 0

    def run(self):
        start_time = time.time()
        for agent in self.agents:
            for _ in range(self.calls_per_agent):
                agent.make_api_call()
        self.execution_time = time.time() - start_time

    def process_data(self):
        # This function will be implemented by GPT-3.5
        pass

def execute_snn(api_url, openai_api_key, num_agents, calls_per_agent, special_config):
    prompt = f"""
    Implement the process_data method for the SwarmNeuralNetwork class. The method should:
    1. Analyze the data collected by all agents (accessible via self.agents[i].data)
    2. Generate a summary of the collected data
    3. Derive insights from the collective behavior
    4. Calculate performance metrics
    5. Return a dictionary with keys 'data_summary', 'insights', and 'performance'

    Consider the following parameters:
    - API URL: {api_url}
    - Number of Agents: {num_agents}
    - Calls per Agent: {calls_per_agent}
    - Special Configuration: {special_config if special_config else 'None'}

    Provide only the Python code for the process_data method, without any additional text or markdown formatting.
    """
    
    process_data_code = call_gpt3_5(prompt, openai_api_key)
    
    if not process_data_code.startswith("Error"):
        try:
            # Create the SNN instance
            snn = SwarmNeuralNetwork(api_url, num_agents, calls_per_agent, special_config)
            
            # Add the process_data method to the SNN class
            exec(process_data_code, globals())
            SwarmNeuralNetwork.process_data = process_data
            
            # Run the SNN
            snn.run()
            
            # Process the data and get results
            result = snn.process_data()
            
            return f"Results from the swarm neural network:\n\n{json.dumps(result, indent=2)}"
        except Exception as e:
            return f"Error executing SNN: {str(e)}\n\nGenerated process_data code:\n{process_data_code}"
    else:
        return process_data_code

# Define the Gradio interface
iface = gr.Interface(
    fn=execute_snn,
    inputs=[
        gr.Textbox(label="API URL for your task"),
        gr.Textbox(label="OpenAI API Key", type="password"),
        gr.Number(label="Number of Agents", minimum=1, maximum=100, step=1),
        gr.Number(label="Calls per Agent", minimum=1, maximum=100, step=1),
        gr.Textbox(label="Special Configuration (optional)")
    ],
    outputs="text",
    title="Swarm Neural Network Simulator",
    description="Enter the parameters for your Swarm Neural Network (SNN) simulation. The SNN will be constructed and executed based on your inputs.",
    examples=[
        ["https://meowfacts.herokuapp.com/", "your-api-key-here", 3, 1, ""],
        ["https://api.publicapis.org/entries", "your-api-key-here", 5, 2, "category=Animals"]
    ]
)

# Launch the interface
iface.launch()