# -*- coding: utf-8 -*-
"""SnipService 头尾保留截断（Phase 7 Tier 1-1 BE）

借鉴 zhikuncode SnipService：
- 保留前 head_ratio 比例 + 后 (1 - head_ratio) 比例
- 中间插入 "...[截断, 共 N 字符 / M 行]..." 标记
- 不超过 budget 字符

修复 abyss shell_exec 输出截断丢失末尾 returncode / 错误堆栈的痛点。
"""
from __future__ import annotations

from typing import Optional


def snip(content: str, budget: int, head_ratio: float = 0.5) -> str:
    """头尾保留截断。

    借鉴 zhikuncode SnipService：
    - 保留前 50% + 后 50%
    - 中间插入 "...[截断, 共 N 字符 / M 行]..." 标记
    - 不超过 budget 字符

    Args:
        content: 原始内容
        budget: 最大字符数（结果长度 <= budget）
        head_ratio: 头部保留比例，范围 [0.0, 1.0]
            - 0.0: 仅保留尾部
            - 0.5: 头尾各半（默认）
            - 1.0: 仅保留头部

    Returns:
        截断后的字符串。若 content 长度 <= budget 原样返回。

    Examples:
        >>> snip("hello world", budget=100)
        'hello world'
        >>> result = snip("a" * 1000, budget=100)
        >>> len(result) <= 100
        True
        >>> "截断" in result
        True
    """
    # 边界情况
    if content is None:
        return ""
    if not isinstance(content, str):
        content = str(content)
    if budget <= 0 or len(content) <= budget:
        return content

    # 限制 head_ratio 范围
    if head_ratio < 0.0:
        head_ratio = 0.0
    elif head_ratio > 1.0:
        head_ratio = 1.0

    lines_count = content.count("\n") + 1
    # 完整标记 + 极短标记两套，按 budget 自适应选择
    full_marker = f"\n...[截断, 共 {len(content)} 字符 / {lines_count} 行]...\n"
    short_marker = f"...[截断 {len(content)} 字]..."

    # 极端 head_ratio 下，优先保证一端完整保留
    # head_ratio=0.0：仅尾部，使用短 marker 让出更多空间给 tail
    # head_ratio=1.0：仅头部，使用短 marker 让出更多空间给 head
    use_short_marker = (
        head_ratio in (0.0, 1.0)
        or budget <= len(full_marker) + 10
    )

    if use_short_marker:
        marker = short_marker
    else:
        marker = full_marker

    # budget 不够容纳短标记 + 至少 1 字符内容时，仅返回 marker 或截断版
    if budget <= len(marker):
        # 极小 budget：返回 marker 截断版
        if budget >= len(short_marker):
            return short_marker[:budget]
        # 实在太小，返回原始内容截断（保持契约：返回值长度 <= budget）
        return content[:budget]

    # 实际可用于内容的预算
    content_budget = budget - len(marker)
    if content_budget <= 0:
        return content[:budget]

    head_budget = int(content_budget * head_ratio)
    tail_budget = content_budget - head_budget

    head = content[:head_budget] if head_budget > 0 else ""
    tail = content[-tail_budget:] if tail_budget > 0 else ""

    return f"{head}{marker}{tail}"


__all__ = ["snip"]
