#!/usr/bin/env python3
import argparse
import contextlib
import io
import json
import os
import sys
import traceback


def text_from_content(content):
    if isinstance(content, str):
        return content
    if isinstance(content, list):
        parts = []
        for item in content:
            if isinstance(item, str):
                parts.append(item)
            elif isinstance(item, dict):
                value = item.get("text") or item.get("content")
                if isinstance(value, str):
                    parts.append(value)
        return "\n".join(part for part in parts if part)
    return ""


def extract_response(result, events, captured_stdout):
    messages = []
    response = ""

    if isinstance(result, dict):
        response = text_from_content(result.get("final_response")) or text_from_content(result.get("response"))
        messages = result.get("messages") or []
    elif result is not None:
        response = text_from_content(result)

    if response and response.strip() and response.strip() != "(empty)":
        return response.strip(), messages

    streamed = "".join(
        event.get("delta", "")
        for event in events
        if event.get("type") == "text" and isinstance(event.get("delta"), str)
    ).strip()
    if streamed and streamed != "(empty)":
        return streamed, messages

    for message in reversed(messages):
        if not isinstance(message, dict):
            continue
        if message.get("role") == "assistant":
            content = text_from_content(message.get("content")).strip()
            if content and content != "(empty)":
                return content, messages

    tool_outputs = []
    for event in events:
        if event.get("type") == "tool_result" and event.get("output"):
            tool_outputs.append(f"### {event.get('name', 'tool_result')}\n\n{event['output']}")
    if tool_outputs:
        return "\n\n".join(tool_outputs), messages

    clean_stdout = "\n".join(
        line for line in captured_stdout.splitlines()
        if line.strip() and not line.startswith(("Could not import tool module", "INFO:", "WARNING:"))
    ).strip()
    if clean_stdout:
        return clean_stdout, messages

    return "", messages


def main():
    parser = argparse.ArgumentParser(description="Run one Hermes command for madarX OS.")
    parser.add_argument("--hermes-dir", required=True)
    parser.add_argument("--prompt", required=True)
    parser.add_argument("--session-id")
    parser.add_argument("--model")
    parser.add_argument("--provider")
    parser.add_argument("--base-url")
    parser.add_argument("--api-mode")
    parser.add_argument("--cwd")
    args = parser.parse_args()

    hermes_dir = os.path.abspath(args.hermes_dir)
    if not os.path.isdir(hermes_dir):
        raise RuntimeError(f"Hermes directory not found: {hermes_dir}")

    sys.path.insert(0, hermes_dir)
    os.chdir(hermes_dir)

    from run_agent import AIAgent

    if args.cwd:
        cwd = os.path.abspath(args.cwd)
        if not os.path.isdir(cwd):
            raise RuntimeError(f"Working directory not found: {cwd}")
        os.chdir(cwd)

    events = []

    def on_delta(delta):
        events.append({"type": "text", "delta": str(delta)})

    def on_tool_start(tool_id, name, tool_args):
        events.append({"type": "tool_start", "id": tool_id, "name": name, "input": tool_args})

    def on_tool_complete(tool_id, name, tool_args, result):
        events.append({
            "type": "tool_result",
            "id": tool_id,
            "name": name,
            "input": tool_args,
            "output": str(result),
        })

    provider = args.provider
    model = args.model
    base_url = args.base_url
    api_mode = args.api_mode
    api_key = None

    if not provider and os.environ.get("ANTHROPIC_API_KEY"):
        provider = "anthropic"
        model = model or os.environ.get("HERMES_ANTHROPIC_MODEL") or "claude-sonnet-4-6"
        base_url = base_url or "https://api.anthropic.com"
        api_mode = api_mode or "anthropic_messages"
        api_key = os.environ.get("ANTHROPIC_API_KEY")

    agent = AIAgent(
        model=model or "",
        provider=provider,
        base_url=base_url,
        api_key=api_key,
        api_mode=api_mode,
        session_id=args.session_id,
        platform="madarx",
        quiet_mode=True,
        tool_start_callback=on_tool_start,
        tool_complete_callback=on_tool_complete,
    )

    buffer = io.StringIO()
    with contextlib.redirect_stdout(buffer):
        result = agent.run_conversation(args.prompt, stream_callback=on_delta)

    response, messages = extract_response(result, events, buffer.getvalue())
    if not response:
        raise RuntimeError(
            "Hermes completed without a final response. "
            f"provider={getattr(agent, 'provider', provider)} "
            f"model={getattr(agent, 'model', model)} "
            f"turn_exit_reason={result.get('turn_exit_reason') if isinstance(result, dict) else None}"
        )

    print(json.dumps({
        "ok": True,
        "response": response,
        "session_id": getattr(agent, "session_id", args.session_id),
        "model": model or getattr(agent, "model", None),
        "provider": provider or getattr(agent, "provider", None),
        "events": events[-100:],
        "turn_exit_reason": result.get("turn_exit_reason") if isinstance(result, dict) else None,
        "completed": result.get("completed") if isinstance(result, dict) else None,
    }, ensure_ascii=False))


if __name__ == "__main__":
    try:
        main()
    except Exception as exc:
        print(json.dumps({
            "ok": False,
            "error": str(exc),
            "traceback": traceback.format_exc(),
        }, ensure_ascii=False))
        sys.exit(1)
