"""
Migrates a Prompt Flow Python code node.

In MAF, custom logic lives directly inside a @handler method — no separate
YAML snippet, no per-node file registration required.

Prompt Flow equivalent:
    def clean_text(text: str) -> str:
        return text.strip().upper()
"""

import asyncio

from dotenv import load_dotenv
from typing_extensions import Never

from agent_framework import Executor, WorkflowBuilder, WorkflowContext, handler

load_dotenv()


class TextCleanerExecutor(Executor):
    """Replaces the Prompt Flow Python node.

    Any Python logic — library calls, data transforms, API calls — goes
    inside the @handler method. WorkflowContext[str] sends the result downstream.
    """

    @handler
    async def clean(self, text: str, ctx: WorkflowContext[str]) -> None:
        cleaned = text.strip().upper()
        await ctx.send_message(cleaned)


class OutputExecutor(Executor):
    """Terminal executor — yields the final workflow output."""

    @handler
    async def output(self, text: str, ctx: WorkflowContext[Never, str]) -> None:
        await ctx.yield_output(text)


_cleaner = TextCleanerExecutor(id="cleaner")
_output = OutputExecutor(id="output")

workflow = (
    WorkflowBuilder(name="PythonNodeWorkflow", start_executor=_cleaner)
    .add_edge(_cleaner, _output)
    .build()
)


async def main():
    result = await workflow.run("  hello from prompt flow  ")
    print(result.get_outputs()[0])  # → "HELLO FROM PROMPT FLOW"


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