from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Optional


@dataclass
class Block:
    index: int
    content_type: str  # "text" | "thinking" | "tool_use" | "mcp_result" | "user_message"
    role: str  # "assistant" | "user"
    where_to_show: str  # "assistant_panel" | "output_panel"
    msg_id: str = ""

    # --- filled depending on content_type ---
    text: Optional[str] = None  # text / thinking / user_message content
    tool_name: Optional[str] = None  # tool_use or mcp_result
    tool_input: Any = None  # tool_use input dict
    tool_result: Any = None  # mcp_result content
    timestamp: Optional[int] = None

    @property
    def assistant_message(self) -> Optional[str]:
        if self.content_type == "text" and self.role == "assistant":
            return self.text
        return None

    @property
    def is_output_panel(self) -> bool:
        return self.where_to_show == "output_panel"

    @property
    def is_bash(self) -> bool:
        return self.tool_name in ("Bash", "bash")

    @classmethod
    def from_raw(cls, index: int, raw: dict) -> Block:
        ct = raw.get("content_type", "")
        role = raw.get("role", "assistant")
        where = raw.get("where_to_show", "assistant_panel")
        msg_id = raw.get("message_id", "")

        if ct == "text" or ct == "thinking":
            return cls(
                index=index, content_type=ct, role=role,
                where_to_show=where, msg_id=msg_id,
                text=raw.get("content", ""),
            )

        if ct == "tool_use":
            content = raw.get("content", {})
            return cls(
                index=index, content_type=ct, role=role,
                where_to_show=where, msg_id=msg_id,
                tool_name=content.get("name"),
                tool_input=content.get("input"),
            )

        if ct == "mcp_result":
            return cls(
                index=index, content_type=ct, role=role,
                where_to_show=where, msg_id=msg_id,
                tool_name=raw.get("tool_name"),
                tool_result=raw.get("content"),
                timestamp=raw.get("timestamp"),
            )

        # user_message or unknown
        return cls(
            index=index, content_type=ct or "user_message", role=role,
            where_to_show=where, msg_id=msg_id,
            text=raw.get("content") if isinstance(raw.get("content"), str) else None,
        )


@dataclass
class BashOutput:
    index: int
    command: Optional[str] = None
    output: Optional[str] = None
    exit_code: Optional[int] = None

    @classmethod
    def from_block(cls, block: Block) -> Optional[BashOutput]:
        if not block.is_bash:
            return None
        result = block.tool_result or {}
        if isinstance(result, dict):
            return cls(
                index=block.index,
                command=result.get("command") or (block.tool_input or {}).get("command"),
                output=result.get("output"),
                exit_code=result.get("exitCode"),
            )
        return cls(index=block.index, output=str(result))
