from fastapi import FastAPI, Query
from fastapi.responses import StreamingResponse
import time
from app import settings

# Initializes the OpenAI client, allowing interaction with OpenAI's API.
from openai import OpenAI

from dotenv import load_dotenv, find_dotenv
_: bool = load_dotenv(find_dotenv())  # read local .env file

app = FastAPI()

# Initialize OpenAI client
client = OpenAI(api_key=str(settings.OPENAI_API_KEY))


@app.get("/")
async def read_root():
    return {"response": "streaming openai with fastapi"}


@app.post("/dummy_streaming_fastapi_openai")
# Dummy generator function to simulate streaming response
def dummy_event_stream():
    messages = [
        "This is part 1 of the response.\n",
        "This is part 2 of the response.\n",
        "This is part 3 of the response.\n",
    ]
    for message in messages:
        yield message
    return StreamingResponse(dummy_event_stream(), media_type="text/plain")


# Returns a StreamingResponse that streams the content generated by dummy_event_stream, with a MIME type of text/plain.


# Creates a streaming completion request to the OpenAI API using the specified model and message.
@app.post("/streaming_fastapi_openai")
async def stream_openai():
    stream = client.chat.completions.create(
        model="gpt-3.5-turbo-1106",
        messages=[{"role": "user", "content": "Say this is a test"}],
        stream=True,
    )

    # Defines an inner generator function event_stream to generate parts of the response.
    def event_stream():
        for part in stream:
            # Extracts the content from the current part of the response, defaulting to an empty string if content is None.
            content = part.choices[0].delta.content or ""
            # If there is content, it yields the content, allowing it to be sent to the client incrementally.
            if content:
                yield content

    # Returns a StreamingResponse that streams the content generated by event_stream, with a MIME type of text/plain.
    return StreamingResponse(event_stream(), media_type="text/plain")


@app.get("/dummy_streaming_fastapi_openai_get")
async def dummy_stream_openai_get(
    query: str = Query(..., description="User input for the dummy model")
    # What is Generative AI?
):
    def dummy_event_stream():
        # Simulating a response by yielding hardcoded content with a delay
        responses = [
            "Generative AI is a type of artificial intelligence",
            " that is designed to create new content, such as images, text, or music,",
            " by learning patterns and structures from existing data.",
            " It uses machine learning algorithms, particularly generative models",
            " such as Generative Adversarial Networks (GANs) and recurrent neural networks,",
            " to generate new and original content that mimics the style",
            " and characteristics of the input data.",
            " Generative AI has applications in various fields,",
            " including art, design, music composition, and language generation.",
        ]
        for part in responses:
            time.sleep(1)  # Simulate delay
            yield part

    return StreamingResponse(dummy_event_stream(), media_type="text/plain")


@app.get("/streaming_fastapi_openai_get")
async def stream_openai_get(
    user_input: str = Query(..., description="User input for the OpenAI model")
):
    stream = client.chat.completions.create(
        model="gpt-3.5-turbo-1106",
        messages=[{"role": "user", "content": user_input}],
        stream=True,
    )

    def event_stream():
        for part in stream:
            content = part.choices[0].delta.content or ""
            if content:
                yield content

    return StreamingResponse(event_stream(), media_type="text/plain")
