# 
import re
import sys
from typing import Any, Dict

def _safe_print(*args, **kwargs):
    """: Windows GBK  emoji/"""
    try:
        print(*args, **kwargs)
    except UnicodeEncodeError:
        #  ?
        text = " ".join(str(a) for a in args)
        encoding = sys.stdout.encoding or 'utf-8'
        text = text.encode(encoding, errors='replace').decode(encoding)
        print(text, **{k: v for k, v in kwargs.items() if k != 'end' and k != 'flush'}, 
              end=kwargs.get('end', '\n'), flush=kwargs.get('flush', False))


def _extract_xml_attr(text: str, attr: str) -> str:
    match = re.search(rf'{attr}="([^"]*)"', text)
    return match.group(1).strip() if match else ""


def _parse_terminal_payload(content: str) -> Dict[str, Any]:
    text = str(content or "")
    tag_match = re.search(r"<terminal_(output|command|wait)\s+[^>]*>", text)
    if not tag_match:
        return {}

    parsed: Dict[str, Any] = {
        "tag": tag_match.group(1),
        "name": _extract_xml_attr(text, "name"),
        "op_id": _extract_xml_attr(text, "op_id"),
        "status": _extract_xml_attr(text, "status").lower(),
        "matched_pattern": _extract_xml_attr(text, "matched_pattern"),
        "timed_out": _extract_xml_attr(text, "timed_out").lower() in {"1", "true", "yes", "on"},
        "has_new_output": _extract_xml_attr(text, "has_new_output").lower() in {"1", "true", "yes", "on"},
    }
    body_match = re.search(
        r"<terminal_(?:output|command|wait)[^>]*>\s*(.*?)\s*</terminal_(?:output|command|wait)>",
        text,
        re.DOTALL,
    )
    parsed["body"] = body_match.group(1).strip() if body_match else ""
    return parsed


def _format_terminal_wait_message(parsed: Dict[str, Any]) -> str:
    if not parsed:
        return ""

    status = str(parsed.get("status", "") or "").strip().lower()
    tag = str(parsed.get("tag", "") or "").strip().lower()
    name = str(parsed.get("name", "") or "").strip() or "default"
    op_id = str(parsed.get("op_id", "") or "").strip()
    has_new_output = bool(parsed.get("has_new_output", False))
    matched_pattern = str(parsed.get("matched_pattern", "") or "").strip()
    body = str(parsed.get("body", "") or "").strip()
    op_suffix = f" (op_id={op_id})" if op_id else ""

    if tag == "command" and status == "pending":
        return f"[] {name}{op_suffix} ,,."
    if status in {"pending", "running"}:
        if matched_pattern:
            return f"[] {name}{op_suffix} : {matched_pattern}"
        if has_new_output and body and body != "()":
            return f"[] {name}{op_suffix} ,,."
        return f"[] {name}{op_suffix} ,."
    if status == "timeout" or bool(parsed.get("timed_out", False)):
        return f"[] {name}{op_suffix} ."
    return ""

def run_terminal_agent_stream(
    agent,
    task: str,
    thread_id: str,
    system_prompt_append: str = "",
) -> dict:
    """: agent,,
    
    """
    _safe_print("\n" + "=" * 60)
    _safe_print(f"[Agent ] (Thread: {thread_id})")
    _safe_print("-" * 60)
    
    result = {}
    has_printed_reasoning_header = False
    has_printed_answer_header = False
    has_streamed_reasoning = False
    has_streamed_answer = False
    current_tool_name = ""

    try:
        for event in agent.invoke(
            task=task,
            thread_id=thread_id,
            system_prompt_append=system_prompt_append,
        ):
            etype = event.get("type", "")
            content = event.get("content", "")
            
            if etype == "done":
                result = event
            elif etype == "iteration":
                _safe_print(f"\n{content}")
            elif etype == "reasoning_token":
                if not has_printed_reasoning_header:
                    _safe_print("\n[]", end="\n", flush=True)
                    has_printed_reasoning_header = True
                _safe_print(content, end="", flush=True)
                has_streamed_reasoning = True
            elif etype == "token":
                if not has_printed_answer_header:
                    _safe_print("\n[]", end="\n", flush=True)
                    has_printed_answer_header = True
                _safe_print(content, end="", flush=True)
                has_streamed_answer = True
            elif etype == "reasoning":
                if not has_streamed_reasoning:
                    _safe_print(f"\n[]\n{content}")
            elif etype == "answer":
                if not has_streamed_answer:
                    _safe_print(f"\n[]\n{content}")
            elif etype == "summary":
                _safe_print(f"\n[]\n{content}")
            elif etype == "tool_exec":
                _safe_print(content)
                tool_match = re.match(r"\[ \d+/\d+\]\s+(.+)$", str(content or "").strip())
                if tool_match:
                    current_tool_name = tool_match.group(1).strip()
                    if current_tool_name in {"wait_terminal_until", "run_and_wait", "write_stdin"}:
                        _safe_print("  [] ,.")
                    elif current_tool_name in {"run_in_terminal", "exec_command", "launch_interactive_session"}:
                        _safe_print("  [] ,.")
            elif etype == "tool_result":
                if current_tool_name in {
                    "run_in_terminal",
                    "exec_command",
                    "write_stdin",
                    "launch_interactive_session",
                    "close_exec_session",
                    "read_terminal",
                    "read_terminal_since_last",
                    "wait_terminal_until",
                    "run_and_wait",
                }:
                    terminal_wait_message = _format_terminal_wait_message(
                        _parse_terminal_payload(str(content or ""))
                    )
                    if terminal_wait_message:
                        _safe_print(f"  {terminal_wait_message}")
                _safe_print(f"  :\n{content}")
            elif etype == "tool_calls":
                _safe_print(content)
            elif etype == "token_usage":
                _safe_print(content)
            elif etype == "context_stats":
                _safe_print(content)
            elif etype == "routing":
                _safe_print(content)
            elif etype == "complete":
                _safe_print(f"\n{content}")
            elif etype == "warning":
                _safe_print(f"⚠ {content}")
            elif etype == "error":
                _safe_print(f"✗ {content}")
            elif etype == "info":
                _safe_print(content)
            else:
                pass
                
    except KeyboardInterrupt:
        _safe_print("\n\n[] Agent .")
    except Exception as e:
         _safe_print(f"\n❌ : {e}")
         
    _safe_print("\n" + "-" * 60)
    _safe_print(f"[Agent ]")
    
    # 
    round_tokens = result.get('total_tokens', 0)
    task_completed = result.get('task_completed', False)
    _safe_print(f" Token : {round_tokens}")
    _safe_print(f": {'' if task_completed else ''}")
    _safe_print("=" * 60 + "\n")
    
    return result


def run_terminal_ask_stream(agent, message: str, system_prompt: str = None, thread_id: str = "default") -> str:
    """: agent.ask(),,"""
    has_printed_reasoning_header = False
    has_printed_answer_header = False
    full_answer = ""
    
    for event in agent.ask(message=message, system_prompt=system_prompt, thread_id=thread_id):
        etype = event.get("type", "")
        content = event.get("content", "")
        
        if etype == "reasoning_token":
            if not has_printed_reasoning_header:
                _safe_print("\n[]", end="\n", flush=True)
                has_printed_reasoning_header = True
            _safe_print(content, end="", flush=True)
        elif etype == "token":
            if not has_printed_answer_header:
                _safe_print("\n[]", end="\n", flush=True)
                has_printed_answer_header = True
            _safe_print(content, end="", flush=True)
        elif etype == "reasoning":
            if not has_printed_reasoning_header:
                _safe_print(f"\n[]\n{content}")
        elif etype == "answer":
            if not has_printed_answer_header:
                _safe_print(f"\n[]\n{content}")
        elif etype == "error":
            _safe_print(f"\n❌ {content}")
        elif etype == "done":
            full_answer = event.get("answer", "")
    
    _safe_print()
    return full_answer
