"""Output engine for CLI"""

from typing import AsyncIterator

from diona.project.cli.core.models import ExecutionResult, StreamChunk
from diona.project.cli.executor import StreamChunk as ExecutorStreamChunk


class OutputEngine:
    """Engine for handling output"""
    
    def __init__(self):
        pass
    
    def output_result(self, result: ExecutionResult) -> None:
        """Output a result synchronously
        
        Args:
            result: ExecutionResult to output
        """
        if result.stdout:
            print(result.stdout, end="")
        if result.stderr:
            print(result.stderr, end="", file=__import__('sys').stderr)
        if result.error_message:
            print(f"Error: {result.error_message}", file=__import__('sys').stderr)
    
    async def output_stream(self, stream: AsyncIterator[StreamChunk]) -> None:
        """Output a streaming result
        
        Args:
            stream: Async iterator of StreamChunk
        """
        async for chunk in stream:
            if chunk.is_error:
                print(chunk.content, end="", file=__import__('sys').stderr)
            else:
                print(chunk.content, end="", flush=True)
        
        print()
    
    def output_stream_from_executor(self, stream: AsyncIterator[ExecutorStreamChunk]) -> None:
        """Output a streaming result from executor
        
        Args:
            stream: Async iterator of ExecutorStreamChunk
        """
        import asyncio
        
        async def run():
            async for chunk in stream:
                if chunk.is_error:
                    print(chunk.content, end="", file=__import__('sys').stderr)
                else:
                    print(chunk.content, end="", flush=True)
                
                if chunk.is_final:
                    print()
        
        asyncio.run(run())


def get_output_engine() -> OutputEngine:
    """Get the output engine instance"""
    global _output_engine
    if _output_engine is None:
        _output_engine = OutputEngine()
    return _output_engine


_output_engine = None