# v0.19 · Chat Agent UX · Trace Tree

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any
from uuid import uuid4


@dataclass
class TraceNode:
    id: str
    label: str
    text: str
    parent_id: str | None = None

    def to_dict(self) -> dict[str, Any]:
        return {
            "id": self.id,
            "label": self.label,
            "text": self.text,
            "parent_id": self.parent_id,
        }


@dataclass
class TraceTreeBuilder:
    """Build hierarchical trace nodes alongside flat trace lines."""

    _nodes: list[TraceNode] = field(default_factory=list)
    _stack: list[str] = field(default_factory=list)

    def add(self, label: str, text: str, *, parent_id: str | None = None) -> str:
        pid = parent_id if parent_id is not None else (self._stack[-1] if self._stack else None)
        node_id = uuid4().hex[:10]
        self._nodes.append(TraceNode(id=node_id, label=label, text=text, parent_id=pid))
        return node_id

    def push(self, label: str, text: str = "") -> str:
        node_id = self.add(label, text)
        self._stack.append(node_id)
        return node_id

    def pop(self) -> None:
        if self._stack:
            self._stack.pop()

    def extend_lines(self, lines: list[str]) -> None:
        for line in lines:
            label, _, body = line.partition("]")
            clean_label = label.lstrip("[").strip() or "trace"
            clean_text = body.strip() if body.strip() else line
            self.add(clean_label, clean_text)

    def to_list(self) -> list[dict[str, Any]]:
        return [n.to_dict() for n in self._nodes]
