"""
Debug output formatters for the Amplitude AI SDK.

Provides :func:`format_debug_line` (colored, human-readable) and
:func:`format_dry_run_line` (compact JSON, machine-parseable) used
by the debug/dry-run hook in :class:`~amplitude_ai.client.AmplitudeAI`.
"""

from __future__ import annotations

import json
import sys
from typing import Any

from amplitude import BaseEvent

from ..core.tracking import (
    EVENT_AI_RESPONSE,
    EVENT_EMBEDDING,
    EVENT_SCORE,
    EVENT_SESSION_END,
    EVENT_SESSION_ENRICHMENT,
    EVENT_SPAN,
    EVENT_TOOL_CALL,
    PROP_AGENT_ID,
    PROP_COST_USD,
    PROP_EMBEDDING_DIMENSIONS,
    PROP_INPUT_TOKENS,
    PROP_IS_ERROR,
    PROP_LATENCY_MS,
    PROP_MODEL_NAME,
    PROP_OUTPUT_TOKENS,
    PROP_SCORE_NAME,
    PROP_SCORE_VALUE,
    PROP_SESSION_ID,
    PROP_SPAN_NAME,
    PROP_TOOL_NAME,
    PROP_TOOL_SUCCESS,
    PROP_TOTAL_TOKENS,
    PROP_TURN_ID,
)

_CYAN = "\033[36m"
_GREEN = "\033[32m"
_YELLOW = "\033[33m"
_RED = "\033[31m"
_BOLD = "\033[1m"
_DIM = "\033[2m"
_RESET = "\033[0m"

_PREFIX = f"{_CYAN}{_BOLD}[amplitude-ai]{_RESET}"
_PREFIX_PLAIN = "[amplitude-ai]"


def _use_color() -> bool:
    try:
        return sys.stderr.isatty()
    except Exception:
        return False


def _label(key: str, value: Any, *, color: bool) -> str:
    if color:
        return f"{_DIM}{key}={_RESET}{value}"
    return f"{key}={value}"


def _compute_total_tokens(props: dict[str, Any]) -> int | None:
    total = props.get(PROP_TOTAL_TOKENS)
    if total is not None:
        return int(total)
    inp = props.get(PROP_INPUT_TOKENS)
    out = props.get(PROP_OUTPUT_TOKENS)
    if inp is not None and out is not None:
        return int(inp) + int(out)
    return None


def format_debug_line(event: BaseEvent, *, color: bool | None = None) -> str:
    """Format an event as a colored, human-readable one-liner.

    Parameters
    ----------
    event:
        The Amplitude ``BaseEvent`` to format.
    color:
        Force color on/off.  *None* (default) auto-detects from
        ``sys.stderr.isatty()``.
    """
    if color is None:
        color = _use_color()

    props: dict[str, Any] = event.event_properties or {}
    event_type = event.event_type or "(unknown)"

    prefix = _PREFIX if color else _PREFIX_PLAIN
    etype = f"{_GREEN}{event_type}{_RESET}" if color else event_type

    parts: list[str] = [prefix, etype]

    if event.user_id:
        parts.append(_label("user", event.user_id, color=color))

    session = props.get(PROP_SESSION_ID)
    if session:
        short = str(session)[:8]
        parts.append(_label("session", f"{short}...", color=color))

    agent = props.get(PROP_AGENT_ID)
    if agent:
        parts.append(_label("agent", agent, color=color))

    if event_type == EVENT_AI_RESPONSE:
        _append_ai_response_fields(parts, props, color)
    elif event_type == EVENT_TOOL_CALL:
        _append_tool_call_fields(parts, props, color)
    elif event_type == EVENT_SCORE:
        _append_score_fields(parts, props, color)
    elif event_type == EVENT_EMBEDDING:
        _append_embedding_fields(parts, props, color)
    elif event_type == EVENT_SPAN:
        _append_span_fields(parts, props, color)
    elif event_type == EVENT_SESSION_END:
        pass
    elif event_type == EVENT_SESSION_ENRICHMENT:
        pass
    else:
        turn = props.get(PROP_TURN_ID)
        if turn is not None:
            parts.append(_label("turn", turn, color=color))

    return " | ".join(parts)


def _append_ai_response_fields(
    parts: list[str], props: dict[str, Any], color: bool
) -> None:
    model = props.get(PROP_MODEL_NAME)
    if model:
        parts.append(_label("model", model, color=color))

    tokens = _compute_total_tokens(props)
    if tokens is not None:
        parts.append(_label("tokens", f"{tokens:,}", color=color))

    cost = props.get(PROP_COST_USD)
    if cost is not None:
        parts.append(_label("cost", f"${cost:.4f}", color=color))

    latency = props.get(PROP_LATENCY_MS)
    if latency is not None:
        parts.append(_label("latency", f"{latency:.0f}ms", color=color))

    if props.get(PROP_IS_ERROR):
        err = f"{_RED}ERROR{_RESET}" if color else "ERROR"
        parts.append(err)


def _append_tool_call_fields(
    parts: list[str], props: dict[str, Any], color: bool
) -> None:
    tool = props.get(PROP_TOOL_NAME)
    if tool:
        parts.append(_label("tool", tool, color=color))

    success = props.get(PROP_TOOL_SUCCESS)
    if success is not None:
        parts.append(_label("success", str(success).lower(), color=color))

    latency = props.get(PROP_LATENCY_MS)
    if latency is not None:
        parts.append(_label("latency", f"{latency:.0f}ms", color=color))


def _append_score_fields(
    parts: list[str], props: dict[str, Any], color: bool
) -> None:
    name = props.get(PROP_SCORE_NAME)
    if name:
        parts.append(_label("name", name, color=color))

    value = props.get(PROP_SCORE_VALUE)
    if value is not None:
        parts.append(_label("value", value, color=color))


def _append_embedding_fields(
    parts: list[str], props: dict[str, Any], color: bool
) -> None:
    model = props.get(PROP_MODEL_NAME)
    if model:
        parts.append(_label("model", model, color=color))

    dims = props.get(PROP_EMBEDDING_DIMENSIONS)
    if dims is not None:
        parts.append(_label("dims", dims, color=color))

    latency = props.get(PROP_LATENCY_MS)
    if latency is not None:
        parts.append(_label("latency", f"{latency:.0f}ms", color=color))


def _append_span_fields(
    parts: list[str], props: dict[str, Any], color: bool
) -> None:
    span = props.get(PROP_SPAN_NAME)
    if span:
        parts.append(_label("span", span, color=color))

    latency = props.get(PROP_LATENCY_MS)
    if latency is not None:
        parts.append(_label("latency", f"{latency:.0f}ms", color=color))

    if props.get(PROP_IS_ERROR):
        err = f"{_RED}ERROR{_RESET}" if color else "ERROR"
        parts.append(err)


def format_dry_run_line(event: BaseEvent) -> str:
    """Format an event as compact JSON for dry-run output."""
    props = event.event_properties or {}
    summary: dict[str, Any] = {"event": event.event_type, "user_id": event.user_id}

    for key in (PROP_SESSION_ID, PROP_MODEL_NAME, PROP_TOOL_NAME, PROP_SCORE_NAME,
                PROP_LATENCY_MS, PROP_COST_USD, PROP_TOTAL_TOKENS):
        val = props.get(key)
        if val is not None:
            short_key = key.replace("[Agent] ", "").lower().replace(" ", "_")
            summary[short_key] = val

    return json.dumps(summary, default=str, ensure_ascii=False)
