"""Turn-level execution state for the Agent streaming loop."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from navi.llm.base import ToolCallRequest

if TYPE_CHECKING:
    pass


@dataclass
class AgentTurnContext:
    """Mutable container for state that lives across iterations of a single run_stream() turn.

    Extracting these variables from run_stream() makes the method readable and lets
    services (AntiStallMonitor, Compressor) receive the turn state explicitly instead
    of returning tuples.
    """

    turn_start: float
    tool_call_count: int = 0
    turn_tokens: int = 0
    subagent_tokens: int = 0
    injected_fact_ids: set[str] = field(default_factory=set)
    # Last model reported to the UI via a ModelInfo event this turn. Tracked
    # across iterations so we only re-emit when the fallback backend actually
    # switches to a different model mid-turn.
    resolved_model: str | None = None
    # Final-turn intercept counter: how many times a "stopped to narrate" turn
    # (text without a tool call) was intercepted and continued because the todo
    # still had open steps. Bounded by profile.final_intercept_limit so a model
    # that keeps producing bare text is eventually allowed to finalise.
    final_interceptions: int = 0


@dataclass
class StreamState:
    """Mutable accumulator for a single LLM stream within one iteration."""

    accumulated_text: str = ""
    accumulated_thinking: str = ""
    turn_tool_calls: list[ToolCallRequest] | None = None
    thinking_active: bool = False
    context_tokens: int | None = None
