"""
Basic Chat — Microsoft Agent Framework version.

Migrated from the Prompt Flow chat-basic example.
Original flow: Input (question + chat_history) → LLM node → answer

This workflow uses a single Agent with FoundryChatClient to replicate
the same chat behaviour: a helpful assistant that remembers conversation
history and responds to user questions.
"""

import asyncio
import os
from dataclasses import dataclass

from dotenv import load_dotenv
from typing_extensions import Never

from agent_framework import Agent, Executor, WorkflowBuilder, WorkflowContext, handler
from agent_framework.openai import OpenAIChatClient

load_dotenv()


@dataclass
class ChatInput:
    """Mirrors the Prompt Flow inputs: question + chat_history."""

    question: str
    chat_history: list | None = None


class InputExecutor(Executor):
    """Replaces the Prompt Flow Input node.

    Accepts a ChatInput, formats the conversation history into the prompt,
    and forwards the assembled prompt string to the LLM executor.
    """

    @handler
    async def receive(self, chat_input: ChatInput, ctx: WorkflowContext[str]) -> None:
        parts = []

        # Replay chat history as a formatted conversation
        if chat_input.chat_history:
            for turn in chat_input.chat_history:
                parts.append(f"User: {turn['inputs']['question']}")
                parts.append(f"Assistant: {turn['outputs']['answer']}")

        # Append the current user question
        parts.append(chat_input.question)

        await ctx.send_message("\n".join(parts))


class ChatExecutor(Executor):
    """Replaces the Prompt Flow LLM (chat) node.

    Uses OpenAIChatClient (Azure routing) + Agent with the same system prompt
    as the original chat.jinja2 template: "You are a helpful assistant."
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        client = OpenAIChatClient(
            azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
            model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
            api_key=os.environ["AZURE_OPENAI_API_KEY"],
        )
        self._agent = Agent(
            client=client,
            name="ChatAgent",
            instructions="You are a helpful assistant.",
        )

    @handler
    async def call_llm(self, question: str, ctx: WorkflowContext[Never, str]) -> None:
        response = await self._agent.run(question)
        await ctx.yield_output(response.text)


# ── Build the workflow ────────────────────────────────────────────────────────
def create_workflow():
    """Return a fresh workflow instance (safe for concurrent / repeated runs)."""
    _input = InputExecutor(id="input")
    _chat = ChatExecutor(id="chat")
    return (
        WorkflowBuilder(name="BasicChatWorkflow", start_executor=_input)
        .add_edge(_input, _chat)
        .build()
    )


async def main():
    # Simple single-turn test (no history)
    workflow = create_workflow()
    result = await workflow.run(ChatInput(question="What is ChatGPT?"))
    print("Answer:", result.get_outputs()[0])
    print()

    # Multi-turn test (with chat history)
    history = [
        {
            "inputs": {"question": "What is ChatGPT?"},
            "outputs": {"answer": "ChatGPT is a large language model chatbot developed by OpenAI."},
        }
    ]
    workflow2 = create_workflow()
    result = await workflow2.run(
        ChatInput(
            question="What is the difference between ChatGPT and GPT-4?",
            chat_history=history,
        )
    )
    print("Answer:", result.get_outputs()[0])


if __name__ == "__main__":
    asyncio.run(main())
