"""
Stream 工具函数和常量
"""

import sys
from pathlib import Path, PurePath
from enum import Enum


# === 状态标记常量 ===
SUCCESS_PREFIX = "[OK]"
FAILURE_PREFIX = "[FAILED]"


# === 工具状态指示器 ===
class ToolStatus(str, Enum):
    """工具执行状态指示器"""
    RUNNING = "●"   # 执行中 - 黄色
    SUCCESS = "●"   # 成功 - 绿色
    ERROR = "●"     # 失败 - 红色
    PENDING = "○"   # 等待 - 灰色


def get_status_symbol(status: ToolStatus) -> str:
    """获取状态符号"""
    try:
        supports_unicode = (
            sys.stdout.encoding
            and 'utf' in sys.stdout.encoding.lower()
        )
    except Exception:
        supports_unicode = False

    if supports_unicode:
        return status.value

    fallback = {
        ToolStatus.RUNNING: "*",
        ToolStatus.SUCCESS: "+",
        ToolStatus.ERROR: "x",
        ToolStatus.PENDING: "-",
    }
    return fallback.get(status, "?")


# === 显示限制常量 ===
class DisplayLimits:
    """显示相关的长度限制"""
    THINKING_STREAM = 1000      # 流式显示时的 thinking 长度
    THINKING_FINAL = 2000       # 最终显示时的 thinking 长度
    ARGS_INLINE = 100           # 内联显示的参数长度
    ARGS_FORMATTED = 300        # 格式化显示的参数长度
    TOOL_RESULT_STREAM = 500    # 流式显示时的工具结果长度
    TOOL_RESULT_FINAL = 800     # 最终显示时的工具结果长度
    TOOL_RESULT_MAX = 2000      # 工具结果最大长度


def has_args(args) -> bool:
    """检查 args 是否有内容"""
    return args is not None and args != {}


def is_success(content: str) -> bool:
    """判断工具输出是否表示成功执行"""
    content = content.strip()
    if content.startswith(SUCCESS_PREFIX):
        return True
    if content.startswith(FAILURE_PREFIX):
        return False
    error_patterns = [
        'Traceback (most recent call last)',
        'Exception:',
        'Error:',
    ]
    return not any(pattern in content for pattern in error_patterns)


def resolve_path(file_path: str, working_directory: Path) -> Path:
    """解析文件路径"""
    path = Path(file_path).expanduser()
    if not path.is_absolute():
        path = working_directory / path
    return path


def truncate(content: str, max_length: int, suffix: str = "\n... (truncated)") -> str:
    """截断内容"""
    if len(content) > max_length:
        return content[:max_length] + suffix
    return content


def format_tool_compact(name: str, args: dict | None) -> str:
    """格式化为紧凑格式"""
    if not args:
        return f"{name}()"

    name_lower = name.lower()

    if name_lower == "bash":
        cmd = args.get("command", "")
        if len(cmd) > 50:
            cmd = cmd[:47] + "..."
        return f"Bash({cmd})"

    elif name_lower == "read":
        path = args.get("file_path", "")
        if len(path) > 40:
            path_obj = PurePath(path)
            parts = path_obj.parts
            if len(parts) > 2:
                path = ".../" + "/".join(parts[-2:])
        return f"Read({path})"

    elif name_lower == "write":
        path = args.get("file_path", "")
        if len(path) > 40:
            path_obj = PurePath(path)
            parts = path_obj.parts
            if len(parts) > 2:
                path = ".../" + "/".join(parts[-2:])
        return f"Write({path})"

    elif name_lower == "edit":
        path = args.get("file_path", "")
        if len(path) > 40:
            path_obj = PurePath(path)
            parts = path_obj.parts
            if len(parts) > 2:
                path = ".../" + "/".join(parts[-2:])
        return f"Edit({path})"

    elif name_lower == "glob":
        pattern = args.get("pattern", "")
        if len(pattern) > 40:
            pattern = pattern[:37] + "..."
        return f"Glob({pattern})"

    elif name_lower == "grep":
        pattern = args.get("pattern", "")
        path = args.get("path", ".")
        if len(pattern) > 30:
            pattern = pattern[:27] + "..."
        return f"Grep({pattern}, {path})"

    elif name_lower == "list_dir":
        path = args.get("path", ".")
        return f"ListDir({path})"

    elif name_lower == "load_skill":
        skill_name = args.get("skill_name", "")
        return f"load_skill({skill_name})"

    params = []
    for k, v in list(args.items())[:2]:
        v_str = str(v)
        if len(v_str) > 20:
            v_str = v_str[:17] + "..."
        params.append(f"{k}={v_str}")

    params_str = ", ".join(params)
    if len(params_str) > 50:
        params_str = params_str[:47] + "..."

    return f"{name}({params_str})"


def format_tree_output(lines: list[str], max_lines: int = 5, indent: str = "  ") -> str:
    """将输出格式化为树形结构"""
    if not lines:
        return ""

    result = []
    display_lines = lines[:max_lines]

    for i, line in enumerate(display_lines):
        prefix = "└" if i == 0 else " "
        result.append(f"{indent}{prefix} {line}")

    remaining = len(lines) - max_lines
    if remaining > 0:
        result.append(f"{indent}  ... +{remaining} lines")

    return "\n".join(result)


def count_lines(content: str) -> int:
    """统计内容行数"""
    if not content:
        return 0
    return len(content.strip().split("\n"))


def truncate_with_line_hint(content: str, max_lines: int = 5) -> tuple[str, int]:
    """按行数截断内容"""
    lines = content.strip().split("\n")
    total = len(lines)

    if total <= max_lines:
        return content.strip(), 0

    truncated = "\n".join(lines[:max_lines])
    remaining = total - max_lines
    return truncated, remaining
