"""ThoughtBlock domain model representing actor reasoning traces."""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict, Field

_DEFAULT_MAX_LINES: int = 10


class ThoughtBlock(BaseModel):
    """Represents an actor reasoning/thought trace block.

    Attributes:
        content: The full text content of the thought.
        max_lines: Maximum number of lines shown when collapsed (default 10).
        expanded: Whether the block is currently expanded to show full content.
    """

    model_config = ConfigDict(arbitrary_types_allowed=True)

    content: str
    max_lines: int = Field(default=_DEFAULT_MAX_LINES)
    expanded: bool = Field(default=False)

    def lines(self) -> list[str]:
        """Return all content lines."""
        if not self.content:
            return []
        return self.content.splitlines()

    def visible_lines(self) -> list[str]:
        """Return lines visible in the current state.

        When collapsed, returns up to ``max_lines`` lines.
        When expanded, returns all lines.
        """
        all_lines = self.lines()
        if self.expanded or len(all_lines) <= self.max_lines:
            return all_lines
        return all_lines[: self.max_lines]

    def is_truncated(self) -> bool:
        """Return True when content is truncated in collapsed state."""
        return not self.expanded and len(self.lines()) > self.max_lines

    def hidden_line_count(self) -> int:
        """Return the number of lines hidden when collapsed."""
        all_lines = self.lines()
        if self.expanded or len(all_lines) <= self.max_lines:
            return 0
        return len(all_lines) - self.max_lines

    def toggle(self) -> None:
        """Toggle the expanded/collapsed state."""
        self.expanded = not self.expanded

    def expand(self) -> None:
        """Expand the block to show full content."""
        self.expanded = True

    def collapse(self) -> None:
        """Collapse the block to show only max_lines."""
        self.expanded = False

    def rendered_text(self) -> str:
        """Return the text to display given the current state.

        Appends a truncation indicator when content is truncated.
        """
        visible = self.visible_lines()
        if not visible:
            return ""
        text = "\n".join(visible)
        if self.is_truncated():
            hidden = self.hidden_line_count()
            plural = "s" if hidden != 1 else ""
            text += f"\n... ({hidden} more line{plural} — space to expand)"
        return text
