from __future__ import annotations

import json

from cybervisor.stream_logging import CanonicalLogEvent, canonicalize_message_text


def _extract_message_text(payload: object) -> str | None:
    if not isinstance(payload, dict):
        return None

    message = payload.get("message")
    if isinstance(message, dict):
        content = message.get("content")
        if isinstance(content, list):
            text_parts = [
                item.get("text", "").strip()
                for item in content
                if isinstance(item, dict) and item.get("type") == "text" and item.get("text")
            ]
            if text_parts:
                return "\n".join(part for part in text_parts if part)

    content_block = payload.get("content_block")
    if isinstance(content_block, dict) and content_block.get("type") == "text":
        text = content_block.get("text")
        if isinstance(text, str) and text.strip():
            return text.strip()

    delta = payload.get("delta")
    if isinstance(delta, dict):
        text = delta.get("text")
        if isinstance(text, str) and text.strip():
            return text.strip()

    return None


def _extract_tool_events(payload: object) -> list[CanonicalLogEvent]:
    if not isinstance(payload, dict):
        return []

    message = payload.get("message")
    if isinstance(message, dict):
        content = message.get("content")
        if isinstance(content, list):
            for item in content:
                if not isinstance(item, dict):
                    continue
                if item.get("type") == "tool_use":
                    return [
                        CanonicalLogEvent(
                            kind="tool_call",
                            tool_name=item.get("name") if isinstance(item.get("name"), str) else None,
                            tool_input=item.get("input") if isinstance(item.get("input"), dict) else None,
                        )
                    ]
                if item.get("type") == "tool_result":
                    return [CanonicalLogEvent(kind="tool_result")]

    content_block = payload.get("content_block")
    if isinstance(content_block, dict):
        content_type = content_block.get("type")
        if content_type == "tool_use":
            return [
                CanonicalLogEvent(
                    kind="tool_call",
                    tool_name=content_block.get("name") if isinstance(content_block.get("name"), str) else None,
                    tool_input=content_block.get("input") if isinstance(content_block.get("input"), dict) else None,
                )
            ]
        if content_type == "tool_result":
            return [CanonicalLogEvent(kind="tool_result")]

    delta = payload.get("delta")
    if isinstance(delta, dict) and delta.get("type") == "tool_use":
        return [
            CanonicalLogEvent(
                kind="tool_call",
                tool_name=delta.get("name") if isinstance(delta.get("name"), str) else None,
                tool_input=delta.get("input") if isinstance(delta.get("input"), dict) else None,
            )
        ]

    return []


def parse_output_line(line: str) -> list[CanonicalLogEvent]:
    if not line:
        return []

    try:
        payload = json.loads(line)
    except json.JSONDecodeError:
        return [CanonicalLogEvent(kind="plain_text", text=line)]

    if not isinstance(payload, dict):
        return [CanonicalLogEvent(kind="plain_text", text=line)]

    message_text = _extract_message_text(payload)
    if message_text:
        return canonicalize_message_text(
            message_text,
            as_hook_feedback=payload.get("type") == "user" and bool(payload.get("isSynthetic")),
        )

    tool_events = _extract_tool_events(payload)
    if tool_events:
        return tool_events

    payload_type = payload.get("type")
    if payload_type == "system":
        parts: list[str] = []
        subtype = payload.get("subtype")
        if isinstance(subtype, str) and subtype:
            parts.append(subtype)
        model = payload.get("model")
        if isinstance(model, str) and model:
            parts.append(f"model={model}")
        cwd = payload.get("cwd")
        if isinstance(cwd, str) and cwd:
            parts.append(f"cwd={cwd}")
        return [CanonicalLogEvent(kind="session_start", summary_parts=tuple(parts))]

    if payload_type == "assistant":
        return []

    if payload_type == "result":
        summary_parts: list[str] = []
        subtype = payload.get("subtype")
        if isinstance(subtype, str) and subtype:
            summary_parts.append(subtype)
        duration = payload.get("duration_ms")
        if isinstance(duration, (int, float)):
            summary_parts.append(f"duration={duration}ms")
        cost = payload.get("total_cost_usd")
        if isinstance(cost, (int, float)):
            summary_parts.append(f"cost=${cost:.4f}")
        num_turns = payload.get("num_turns")
        if isinstance(num_turns, int):
            summary_parts.append(f"turns={num_turns}")
        return [
            CanonicalLogEvent(
                kind="completed",
                summary_parts=tuple(summary_parts),
                status=subtype if isinstance(subtype, str) else None,
            )
        ]

    return []
