"""albus run -- Execute a pathway from YAML file or registered ID."""

from __future__ import annotations

import asyncio
import json as _json
from pathlib import Path

import aiohttp

from core.common import JsonObject
from core.pathways.context import Context
from core.pathways.pathway import Pathway
from core.pathways.vm import PathwayVM
from core.tools import get_tool_registry
from server.transport.cli._models import RunArgs
from stdlib.bootstrap import load_stdlib


def cmd_run(args: RunArgs) -> int:
    """Run a pathway from YAML file or registered ID."""
    if not args.target:
        print("Error: pathway target required (YAML file or pathway ID)")
        return 2

    # Parse inputs
    inputs: JsonObject = {}
    if args.input:
        try:
            inputs = _json.loads(args.input)
        except _json.JSONDecodeError as e:
            print(f"Error: Invalid JSON input: {e}")
            return 1

    # Determine if target is a file or pathway ID
    target_path = Path(args.target)
    is_file = target_path.exists() and target_path.suffix in (".yaml", ".yml")

    if args.server or not is_file:
        return _run_via_server(args.target, inputs, args.host, args.port)
    return _run_direct(target_path, inputs)


def _run_direct(yaml_path: Path, inputs: JsonObject) -> int:
    """Run a pathway YAML directly without server."""

    async def _execute() -> int:
        load_stdlib()

        yaml_content = yaml_path.read_text()
        try:
            pathway = Pathway.from_yaml(yaml_content)
        except Exception as e:
            print(f"Error parsing pathway: {e}")
            return 1

        print(f"\U0001f527 Loaded: {pathway.name} ({pathway.mode.value}, {len(pathway.nodes)} nodes)")
        if pathway.version:
            print(f"   Version: {pathway.version}")

        registry = get_tool_registry()
        ctx = Context(tools={td.name: td.handler for td in registry.list() if td.handler})
        vm = PathwayVM(ctx)

        print("\u26a1 Executing...")
        try:
            result = await vm.execute(pathway, inputs=inputs, timeout=300.0)
        except Exception as e:
            print(f"\u274c Execution failed: {e}")
            return 1

        print(f"\u2705 Completed: {result.status.value}")

        if result.outputs:
            output_data = result.outputs.get("output")
            if not output_data:
                terminal_nodes = [
                    nid for nid in pathway.nodes
                    if not any(c.from_node == nid for c in pathway.connections)
                ]
                for nid in reversed(terminal_nodes):
                    if nid in result.outputs:
                        output_data = result.outputs[nid]
                        break
            if not output_data:
                output_data = result.outputs

            if isinstance(output_data, dict):
                response = (output_data.get("output") or {}).get("response")
                if response:
                    print(f"\n{'='*60}")
                    print(response[:3000])
                    print(f"{'='*60}")
                else:
                    print("\nOutputs:")
                    print(_json.dumps(output_data, indent=2, default=str)[:3000])

        diag = result.metadata.get("_diagnostics", {})
        if diag:
            print(
                f"\n\U0001f4ca Nodes: {diag.get('nodes_executed', 0)} executed, "
                f"{diag.get('nodes_succeeded', 0)} succeeded, "
                f"{diag.get('nodes_failed', 0)} failed, "
                f"{diag.get('nodes_skipped', 0)} skipped"
            )

        return 0

    return asyncio.run(_execute())


def _run_via_server(pathway_id: str, inputs: JsonObject, host: str, port: int) -> int:
    """Run a registered pathway via server."""

    async def _execute() -> int:
        url = f"http://{host}:{port}/api/v1/pathways/{pathway_id}/run"
        timeout = aiohttp.ClientTimeout(total=300)

        try:
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(url, json={"inputs": inputs}) as resp:
                    if resp.status == 404:
                        print(f"Error: Pathway '{pathway_id}' not found")
                        return 1
                    if resp.status != 200:
                        print(f"Error: Server returned {resp.status}")
                        return 1
                    data = await resp.json()

                    if data.get("success"):
                        print("\u2705 Completed")
                        outputs = data.get("outputs", {})
                        if outputs:
                            print(_json.dumps(outputs, indent=2, default=str)[:2000])
                        return 0
                    print(f"Error: {data.get('error', 'Unknown error')}")
                    return 1
        except Exception as e:
            print(f"Error: {e}")
            return 1

    return asyncio.run(_execute())
