# Copyright (c) Microsoft. All rights reserved.

"""
Message Capture Script - Debug message flow
- This script is intended to provide a reference for the types of events
  that are emitted by the server when agents and workflows are executed
"""

import asyncio
import contextlib
import http.client
import json
import logging
import threading
import time
from collections.abc import Mapping
from pathlib import Path
from typing import Any

import uvicorn
from openai import OpenAI

from agent_framework_devui import DevServer

logger = logging.getLogger(__name__)


def start_server() -> tuple[str, Any]:
    """Start server with samples directory."""
    # Get samples directory - updated path after samples were moved
    current_dir = Path(__file__).parent
    # Samples are now in python/samples/02-agents/devui
    samples_dir = current_dir.parent.parent.parent / "samples" / "02-agents" / "devui"

    if not samples_dir.exists():
        raise RuntimeError(f"Samples directory not found: {samples_dir}")

    logger.info(f"Using samples directory: {samples_dir}")

    # Create and start server with simplified parameters
    server = DevServer(
        entities_dir=str(samples_dir.resolve()),
        host="127.0.0.1",
        port=8085,  # Use different port
        ui_enabled=False,
    )

    app = server.get_app()

    server_config = uvicorn.Config(
        app=app,
        host="127.0.0.1",
        port=8085,
        # log_level="info",  # More verbose to see tracing setup
    )
    server_instance = uvicorn.Server(server_config)

    def run_server():
        asyncio.run(server_instance.serve())

    server_thread = threading.Thread(target=run_server, daemon=True)
    server_thread.start()

    # Wait for server to start
    time.sleep(5)  # Increased wait time

    # Verify server is running with retries
    max_retries = 10
    for attempt in range(max_retries):
        try:
            conn = http.client.HTTPConnection("127.0.0.1", 8085, timeout=5)
            try:
                conn.request("GET", "/health")
                response = conn.getresponse()
                if response.status == 200:
                    break
            finally:
                conn.close()
        except Exception as e:
            if attempt < max_retries - 1:
                time.sleep(2)
            else:
                raise RuntimeError(f"Server failed to start after {max_retries} attempts: {e}") from e

    return "http://127.0.0.1:8085", server_instance


def capture_agent_stream_with_tracing(client: OpenAI, agent_id: str, scenario: str = "success") -> list[dict[str, Any]]:
    """Capture agent streaming events."""

    try:
        stream = client.responses.create(
            metadata={"entity_id": agent_id},
            input="Tell me about the weather in Tokyo. I want details.",
            stream=True,
        )

        events: list[dict[str, Any]] = []
        for event in stream:
            # Serialize the entire event object
            try:
                raw_event_dict = json.loads(event.model_dump_json())
            except Exception:
                # Fallback to dict conversion if model_dump_json fails
                raw_event_dict = event.__dict__ if hasattr(event, "__dict__") else {"event": str(event)}

            event_dict = dict(raw_event_dict) if isinstance(raw_event_dict, Mapping) else {"event": str(event)}

            events.append(event_dict)

            # Just capture everything as-is
            if len(events) >= 200:  # Increased limit
                break

        return events

    except Exception as e:
        # Return error information as events
        error_event = {
            "type": "error",
            "scenario": scenario,
            "error_message": str(e),
            "error_type": type(e).__name__,
            "timestamp": time.time(),
        }
        return [error_event]


def capture_workflow_stream_with_tracing(
    client: OpenAI, workflow_id: str, scenario: str = "success"
) -> list[dict[str, Any]]:
    """Capture workflow streaming events."""

    try:
        stream = client.responses.create(
            metadata={"entity_id": workflow_id},
            input=(
                "Process this spam detection workflow with multiple emails: "
                "'Buy now!', 'Hello mom', 'URGENT: Click here!'"
            ),
            stream=True,
        )

        events: list[dict[str, Any]] = []
        for event in stream:
            # Serialize the entire event object
            try:
                raw_event_dict = json.loads(event.model_dump_json())
            except Exception:
                # Fallback to dict conversion if model_dump_json fails
                raw_event_dict = event.__dict__ if hasattr(event, "__dict__") else {"event": str(event)}

            event_dict = dict(raw_event_dict) if isinstance(raw_event_dict, Mapping) else {"event": str(event)}

            events.append(event_dict)

            # Just capture everything as-is
            if len(events) >= 200:  # Increased limit
                break

        return events

    except Exception as e:
        # Return error information as events
        error_event = {
            "type": "error",
            "scenario": scenario,
            "error_message": str(e),
            "error_type": type(e).__name__,
            "timestamp": time.time(),
            "entity_type": "workflow",
        }
        return [error_event]


def main():
    """Main capture script - testing both success and failure scenarios."""

    # Setup
    output_dir = Path(__file__).parent / "captured_messages"
    output_dir.mkdir(exist_ok=True)

    # Start server
    base_url, server_instance = start_server()

    try:
        # Create OpenAI client for success scenario
        client = OpenAI(base_url=f"{base_url}/v1", api_key="dummy-key")

        # Discover entities
        conn = http.client.HTTPConnection("127.0.0.1", 8085, timeout=10)
        try:
            conn.request("GET", "/v1/entities")
            response = conn.getresponse()
            response_data = response.read().decode("utf-8")
            entities = json.loads(response_data)["entities"]
        finally:
            conn.close()

        all_results = {}

        # Test each entity
        for entity in entities:
            entity_type = entity["type"]
            entity_id = entity["id"]

            if entity_type == "agent":
                events = capture_agent_stream_with_tracing(client, entity_id, "success")
            elif entity_type == "workflow":
                events = capture_workflow_stream_with_tracing(client, entity_id, "success")
            else:
                continue

            all_results[f"{entity_type}_{entity_id}"] = {"entity_info": entity, "events": events}
        # Save results
        file_path = output_dir / "entities_stream_events.json"
        with open(file_path, "w") as f:
            json.dump(
                {"timestamp": time.time(), "server_type": "DevServer", "entities_tested": all_results},
                f,
                indent=2,
                default=str,
            )

    finally:
        # Cleanup server
        with contextlib.suppress(Exception):
            server_instance.should_exit = True


if __name__ == "__main__":
    main()
