"""Context window management — token counting and conversation compaction."""

from __future__ import annotations

import json
from typing import Any


# Rough token estimation: ~4 chars per token for English, ~2 chars for Japanese
# This is intentionally conservative (over-estimates) to avoid hitting limits.
def estimate_tokens(text: str) -> int:
    """Estimate token count from text using a simple heuristic."""
    if not text:
        return 0
    # Count ASCII vs non-ASCII characters
    ascii_chars = sum(1 for c in text if ord(c) < 128)
    non_ascii_chars = len(text) - ascii_chars
    return (ascii_chars // 4) + (non_ascii_chars // 2) + 1


def estimate_message_tokens(message: dict[str, Any]) -> int:
    """Estimate tokens for a single message."""
    content = message.get("content", "")
    if isinstance(content, str):
        return estimate_tokens(content) + 4  # role overhead
    elif isinstance(content, list):
        total = 4  # role overhead
        for block in content:
            if isinstance(block, dict):
                if block.get("type") == "text":
                    total += estimate_tokens(block.get("text", ""))
                elif block.get("type") == "tool_use":
                    total += estimate_tokens(block.get("name", ""))
                    total += estimate_tokens(json.dumps(block.get("input", {})))
                elif block.get("type") == "tool_result":
                    total += estimate_tokens(block.get("content", ""))
            else:
                total += estimate_tokens(str(block))
        return total
    return 4


def estimate_conversation_tokens(
    messages: list[dict[str, Any]], system_prompt: str = ""
) -> dict[str, int]:
    """Estimate token usage for the entire conversation.

    Returns dict with: system, messages, total
    """
    system_tokens = estimate_tokens(system_prompt)
    message_tokens = sum(estimate_message_tokens(m) for m in messages)
    total = system_tokens + message_tokens
    return {
        "system": system_tokens,
        "messages": message_tokens,
        "total": total,
        "message_count": len(messages),
    }


def compact_messages(
    messages: list[dict[str, Any]],
    keep_recent: int = 6,
) -> tuple[list[dict[str, Any]], str]:
    """Compact conversation by summarizing older messages.

    Keeps the most recent `keep_recent` messages intact and creates
    a summary of older messages.

    Returns:
        (new_messages, summary_text) — summary_text describes what was compacted
    """
    if len(messages) <= keep_recent:
        return messages, ""

    old_messages = messages[:-keep_recent]
    recent_messages = messages[-keep_recent:]

    # Build summary of old messages
    summary_parts = []
    for msg in old_messages:
        role = msg.get("role", "unknown")
        content = msg.get("content", "")

        if isinstance(content, str):
            text = content
        elif isinstance(content, list):
            text_parts = []
            for block in content:
                if isinstance(block, dict):
                    if block.get("type") == "text":
                        text_parts.append(block.get("text", ""))
                    elif block.get("type") == "tool_use":
                        text_parts.append(f"[tool: {block.get('name', '')}]")
                    elif block.get("type") == "tool_result":
                        result = block.get("content", "")
                        if len(result) > 100:
                            result = result[:100] + "..."
                        text_parts.append(f"[result: {result}]")
            text = " ".join(text_parts)
        else:
            text = str(content)

        # Truncate long text
        if len(text) > 200:
            text = text[:200] + "..."

        if role == "user":
            summary_parts.append(f"- User: {text}")
        elif role == "assistant":
            summary_parts.append(f"- Assistant: {text}")

    summary = "【以前の会話の要約】\n" + "\n".join(summary_parts)
    old_tokens = sum(estimate_message_tokens(m) for m in old_messages)

    # Replace old messages with a summary message
    new_messages = [
        {"role": "user", "content": summary},
        {"role": "assistant", "content": "はい、これまでの会話を把握しました。続けますね！"},
        *recent_messages,
    ]

    compacted_info = (
        f"{len(old_messages)} メッセージを要約しました "
        f"(約 {old_tokens:,} トークン削減)"
    )
    return new_messages, compacted_info
