"""
Formatting Utilities

Helpers for formatting output, dates, sizes, and other display elements.
"""

from datetime import datetime
from typing import Any


def format_datetime(dt: datetime, include_time: bool = True) -> str:
    """
    Format a datetime object for display.

    Args:
        dt: Datetime to format
        include_time: Whether to include time (default: True)

    Returns:
        Formatted datetime string
    """
    if include_time:
        # Format: "2024-11-22 14:30:45"
        return dt.strftime("%Y-%m-%d %H:%M:%S")
    else:
        # Format: "2024-11-22"
        return dt.strftime("%Y-%m-%d")


def format_relative_time(dt: datetime) -> str:
    """
    Format a datetime as relative time (e.g., "2 hours ago").

    Args:
        dt: Datetime to format

    Returns:
        Relative time string
    """
    now = datetime.now()
    diff = now - dt

    seconds = diff.total_seconds()

    if seconds < 60:
        return "just now"
    elif seconds < 3600:
        minutes = int(seconds / 60)
        return f"{minutes} minute{'s' if minutes != 1 else ''} ago"
    elif seconds < 86400:
        hours = int(seconds / 3600)
        return f"{hours} hour{'s' if hours != 1 else ''} ago"
    elif seconds < 604800:
        days = int(seconds / 86400)
        return f"{days} day{'s' if days != 1 else ''} ago"
    elif seconds < 2592000:
        weeks = int(seconds / 604800)
        return f"{weeks} week{'s' if weeks != 1 else ''} ago"
    elif seconds < 31536000:
        months = int(seconds / 2592000)
        return f"{months} month{'s' if months != 1 else ''} ago"
    else:
        years = int(seconds / 31536000)
        return f"{years} year{'s' if years != 1 else ''} ago"


def format_size_bytes(size_bytes: int) -> str:
    """
    Format byte size in human-readable format.

    Args:
        size_bytes: Size in bytes

    Returns:
        Formatted size string (e.g., "1.5 MB")
    """
    if size_bytes < 1024:
        return f"{size_bytes} B"
    elif size_bytes < 1024 * 1024:
        kb = size_bytes / 1024
        return f"{kb:.1f} KB"
    elif size_bytes < 1024 * 1024 * 1024:
        mb = size_bytes / (1024 * 1024)
        return f"{mb:.1f} MB"
    else:
        gb = size_bytes / (1024 * 1024 * 1024)
        return f"{gb:.1f} GB"


def format_message_count(count: int) -> str:
    """
    Format message count with proper pluralization.

    Args:
        count: Number of messages

    Returns:
        Formatted string (e.g., "5 messages")
    """
    return f"{count} message{'s' if count != 1 else ''}"


def format_duration_ms(duration_ms: float) -> str:
    """
    Format duration in milliseconds to human-readable format.

    Args:
        duration_ms: Duration in milliseconds

    Returns:
        Formatted duration string
    """
    if duration_ms < 1000:
        return f"{duration_ms:.0f}ms"
    elif duration_ms < 60000:
        seconds = duration_ms / 1000
        return f"{seconds:.1f}s"
    else:
        minutes = duration_ms / 60000
        return f"{minutes:.1f}m"


def format_session_title(title: str, max_length: int = 50) -> str:
    """
    Format session title with truncation if needed.

    Args:
        title: Session title
        max_length: Maximum length before truncation

    Returns:
        Formatted title
    """
    if len(title) <= max_length:
        return title

    return title[:max_length - 3] + "..."


def format_table_row(columns: list[str], widths: list[int]) -> str:
    """
    Format a table row with fixed column widths.

    Args:
        columns: Column values
        widths: Column widths

    Returns:
        Formatted row string
    """
    formatted_cols = []
    for col, width in zip(columns, widths):
        # Truncate if too long
        if len(col) > width:
            col = col[:width - 3] + "..."
        # Pad if too short
        formatted_cols.append(col.ljust(width))

    return " ".join(formatted_cols)


def format_provider_name(provider: str) -> str:
    """
    Format provider name for display (capitalize).

    Args:
        provider: Provider identifier

    Returns:
        Formatted provider name
    """
    provider_map = {
        "openai": "OpenAI",
        "anthropic": "Anthropic",
        "gemini": "Google Gemini",
    }
    return provider_map.get(provider.lower(), provider.title())


def format_model_name(model: str) -> str:
    """
    Format model name for display (remove redundant prefixes).

    Args:
        model: Model identifier

    Returns:
        Formatted model name
    """
    # Remove common prefixes for cleaner display
    if model.startswith("models/"):
        return model[7:]  # Remove "models/" prefix
    return model


def format_event_data(event_type: str, data: dict[str, Any]) -> str:
    """
    Format event data for display.

    Args:
        event_type: Type of event
        data: Event data dictionary

    Returns:
        Formatted event string
    """
    if event_type == "tool_call":
        tool_name = data.get("tool_name", "unknown")
        return f"🔧 Calling tool: {tool_name}"
    elif event_type == "tool_result":
        tool_name = data.get("tool_name", "unknown")
        success = data.get("success", False)
        status = "✓" if success else "✗"
        return f"{status} Tool result: {tool_name}"
    elif event_type == "request_started":
        model = data.get("model", "unknown")
        return f"📤 Sending request to {model}..."
    elif event_type == "response_received":
        return "📥 Response received"
    else:
        return f"Event: {event_type}"


def truncate_text(text: str, max_length: int, suffix: str = "...") -> str:
    """
    Truncate text to maximum length with suffix.

    Args:
        text: Text to truncate
        max_length: Maximum length
        suffix: Suffix to add when truncated

    Returns:
        Truncated text
    """
    if len(text) <= max_length:
        return text

    return text[:max_length - len(suffix)] + suffix


def format_config_value(value: Any, is_sensitive: bool = False) -> str:
    """
    Format configuration value for display.

    Args:
        value: Configuration value
        is_sensitive: Whether value is sensitive (e.g., API key)

    Returns:
        Formatted value string
    """
    if value is None:
        return "[not set]"

    if is_sensitive:
        if isinstance(value, str) and len(value) > 0:
            # Show first 4 chars only
            return f"{value[:4]}...***"
        return "***"

    if isinstance(value, bool):
        return "enabled" if value else "disabled"

    return str(value)
