"""
Thinking Indicator

Animated "thinking" indicator displayed while the LLM processes a request.
Provides bee/honeypot-themed visual feedback with graceful terminal degradation.
"""

import asyncio
import random

from rich.console import Console
from rich.status import Status


THINKING_PHRASES = [
    "Pollinating the data...",
    "Checking the honeycomb...",
    "Scouting the threat landscape...",
    "Gathering nectar from the logs...",
    "Decoding the hive mind...",
    "Luring intel from the pot...",
    "Buzzing through the data...",
    "Tending the honeypot...",
    "Extracting threat honey...",
    "Waggle-dancing through results...",
]

FALLBACK_PHRASE = "Working on your request..."

# Seconds between phrase changes
PHRASE_ROTATION_INTERVAL = 2.5

# Alternating emoji prefixes for Unicode terminals
BEE_ICONS = ("🐝 ", "🍯 ")


class ThinkingIndicator:
    """
    Async context manager that displays an animated thinking indicator
    while the LLM processes a request.

    Phrases are shuffled on each use. Degrades gracefully based on
    terminal capabilities.

    Instances are single-use. Do not reuse across multiple LLM requests.

    Usage:
        indicator = ThinkingIndicator(console, unicode_support=True, is_tty=True)
        async with indicator:
            response = await llm_task
    """

    def __init__(self, console: Console, unicode_support: bool = True, is_tty: bool = True):
        """
        Initialize the thinking indicator.

        Args:
            console: Raw Rich Console object (RichConsoleUI.console)
            unicode_support: Whether the terminal supports Unicode/emoji
            is_tty: Whether stdout is an interactive terminal
        """
        self._console = console
        self._unicode_support = unicode_support
        self._is_tty = is_tty
        self._status: Status | None = None
        self._rotation_task: asyncio.Task | None = None
        self._phrases: list[str] = []
        self._phrase_index: int = 0
        # Track whether this instance has ever been used as a context manager.
        # Instances are documented as single-use and should not be reused.
        self._used: bool = False

    def _build_display_text(self, index: int) -> str:
        """Build the display text for a given phrase index."""
        phrase = self._phrases[index]
        if self._unicode_support:
            icon = BEE_ICONS[index % 2]
            return f"{icon}{phrase}"
        return phrase

    async def _rotate_phrases(self) -> None:
        """Coroutine that rotates through phrases on an interval."""
        try:
            while True:
                await asyncio.sleep(PHRASE_ROTATION_INTERVAL)
                self._phrase_index = (self._phrase_index + 1) % len(self._phrases)
                text = self._build_display_text(self._phrase_index)
                if self._status is not None:
                    self._status.update(text)
        except asyncio.CancelledError:
            return

    async def __aenter__(self) -> "ThinkingIndicator":
        if self._used:
            # Enforce documented single-use behavior even when Python assertions
            # are disabled (e.g., with the -O flag).
            raise RuntimeError("ThinkingIndicator instances are single-use")

        if not self._is_tty:
            self._used = True
            self._console.print(FALLBACK_PHRASE)
            return self

        # Shuffle phrases for variety; guard against empty list
        self._phrases = list(THINKING_PHRASES) if THINKING_PHRASES else [FALLBACK_PHRASE]
        random.shuffle(self._phrases)
        self._phrase_index = 0

        initial_text = self._build_display_text(0)
        spinner_name = "dots" if self._unicode_support else "line"

        self._status = Status(initial_text, spinner=spinner_name, console=self._console)
        self._status.start()

        self._rotation_task = asyncio.create_task(self._rotate_phrases())
        self._used = True
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb) -> bool:
        if not self._is_tty:
            return False

        if self._rotation_task is not None:
            task = self._rotation_task
            self._rotation_task = None
            if not task.done():
                task.cancel()
            try:
                await task
            except asyncio.CancelledError:
                pass

        if self._status is not None:
            self._status.stop()
            self._status = None

        # Do not suppress exceptions
        return False
