"""Terminal capability detection for AiCippy CLI.

Provides shared detection of terminal features and safe symbol access:
- UTF-8 encoding support
- Terminal width for responsive layout
- NO_COLOR standard (https://no-color.org/)
- ASCII fallback symbol mappings
"""

from __future__ import annotations

import os
import shutil
import sys
from typing import Final

# ============================================================================
# Cached Detection
# ============================================================================

_utf8_cache: bool | None = None
_no_color_cache: bool | None = None


def supports_utf8() -> bool:
    """Detect if the terminal supports UTF-8 encoding.

    Checks stdout encoding and LANG/LC_ALL/LC_CTYPE environment variables.
    Result is cached after first call.
    """
    global _utf8_cache
    if _utf8_cache is not None:
        return _utf8_cache

    encoding = getattr(sys.stdout, "encoding", None) or ""
    normalized = encoding.lower().replace("-", "")
    if normalized in ("utf8", "utf16", "utf32"):
        _utf8_cache = True
        return True

    for env_var in ("LC_ALL", "LANG", "LC_CTYPE"):
        val = os.environ.get(env_var, "").lower()
        if "utf-8" in val or "utf8" in val:
            _utf8_cache = True
            return True

    _utf8_cache = False
    return False


def is_no_color() -> bool:
    """Check if NO_COLOR environment variable is set.

    See https://no-color.org/ for the standard.
    """
    global _no_color_cache
    if _no_color_cache is not None:
        return _no_color_cache
    _no_color_cache = "NO_COLOR" in os.environ
    return _no_color_cache


def get_terminal_width() -> int:
    """Get the current terminal width in columns, defaulting to 80."""
    return shutil.get_terminal_size((80, 24)).columns


def is_narrow_terminal(threshold: int = 80) -> bool:
    """Check if the terminal is narrower than the threshold."""
    return get_terminal_width() < threshold


def is_compact_terminal(threshold: int = 60) -> bool:
    """Check if the terminal is very narrow (compact mode)."""
    return get_terminal_width() < threshold


# ============================================================================
# Terminal Layout Hints
# ============================================================================

# Width thresholds for responsive layout
LAYOUT_FULL_WIDTH: Final[int] = 80  # Full layout with sidebar
LAYOUT_COMPACT_WIDTH: Final[int] = 60  # Compact layout (no sidebar)
LAYOUT_MINIMAL_WIDTH: Final[int] = 40  # Minimal (plain text, no panels)


def get_layout_mode() -> str:
    """Determine the appropriate layout mode based on terminal width.

    Returns:
        One of 'full', 'compact', or 'minimal'.

    """
    width = get_terminal_width()
    if width >= LAYOUT_FULL_WIDTH:
        return "full"
    if width >= LAYOUT_COMPACT_WIDTH:
        return "compact"
    return "minimal"


# ============================================================================
# Symbol Mappings — UTF-8 with ASCII Fallbacks
# ============================================================================

_SYMBOLS_UTF8: Final[dict[str, str]] = {
    "bullet": "\u25cf",
    "bullet_half": "\u25d0",
    "check": "\u2713",
    "cross": "\u2717",
    "circle": "\u25cb",
    "circle_dot": "\u25cc",
    "diamond": "\u25c8",
    "diamond_empty": "\u25c7",
    "lightning": "\u26a1",
    "clipboard": "\U0001f4cb",
    "keyboard": "\u2328",
    "block_full": "\u2588",
    "block_light": "\u2591",
    "corner_tl": "\u256d",
    "corner_tr": "\u256e",
    "corner_bl": "\u2570",
    "corner_br": "\u256f",
    "line_h": "\u2500",
    "line_v": "\u2502",
    "arrow_right": "\u2192",
    "arrow_left": "\u2190",
    "ellipsis": "\u2026",
    "eye": "\u25d5",
    "nose": "\u25bd",
    "sparkle": "\u2728",
    "spinner_0": "\u25cb",
    "spinner_1": "\u25d0",
    "spinner_2": "\u25d1",
    "spinner_3": "\u25d3",
}

_SYMBOLS_ASCII: Final[dict[str, str]] = {
    "bullet": "*",
    "bullet_half": "o",
    "check": "+",
    "cross": "x",
    "circle": "o",
    "circle_dot": ".",
    "diamond": "*",
    "diamond_empty": "o",
    "lightning": "!",
    "clipboard": "#",
    "keyboard": "K",
    "block_full": "#",
    "block_light": ".",
    "corner_tl": "+",
    "corner_tr": "+",
    "corner_bl": "+",
    "corner_br": "+",
    "line_h": "-",
    "line_v": "|",
    "arrow_right": ">",
    "arrow_left": "<",
    "ellipsis": "...",
    "eye": "o",
    "nose": "v",
    "sparkle": "*",
    "spinner_0": "-",
    "spinner_1": "\\",
    "spinner_2": "|",
    "spinner_3": "/",
}


def sym(name: str) -> str:
    """Get a terminal-safe symbol by name.

    Returns the UTF-8 symbol if the terminal supports it,
    otherwise the ASCII fallback.

    Args:
        name: Symbol key (e.g. 'check', 'bullet', 'arrow_right').

    Returns:
        The appropriate symbol string.

    """
    if supports_utf8():
        return _SYMBOLS_UTF8.get(name, "?")
    return _SYMBOLS_ASCII.get(name, "?")


# ============================================================================
# Status Icon Mapping (replaces hardcoded STATUS_ICONS)
# ============================================================================


def status_icon(status: str) -> str:
    """Get a terminal-safe status icon.

    Args:
        status: One of 'running', 'thinking', 'complete', 'error',
                'idle', 'pending', 'in_progress'.

    """
    mapping = {
        "running": "bullet",
        "thinking": "bullet_half",
        "complete": "check",
        "error": "cross",
        "idle": "circle",
        "pending": "circle_dot",
        "in_progress": "bullet",
    }
    return sym(mapping.get(status, "circle"))
