"""Convert classified messages to ATIF steps."""

from __future__ import annotations

from datetime import datetime

from cc_logger.parser.reassemble import ClassifiedMessage
from cc_logger.types.atif import ATIFMetrics, ATIFStep, ATIFToolCall

# Insert a gap separator before every user message showing idle time


def build_steps(classified: list[ClassifiedMessage]) -> list[ATIFStep]:
    """Convert classified messages into ATIF steps, skipping non-conversation types."""
    raw_steps: list[ATIFStep] = []
    step_id = 1

    for cm in classified:
        if cm.type == "user":
            content = cm.original.content
            message = content if isinstance(content, str) else str(content)
            raw_steps.append(
                ATIFStep(
                    step_id=step_id,
                    timestamp=cm.original.timestamp,
                    source="user",
                    message=message,
                )
            )
            step_id += 1

        elif cm.type == "agent" and cm.reassembled:
            resp = cm.reassembled
            if resp.model == "<synthetic>" and resp.message_text == "No response requested.":
                continue

            tool_calls = None
            if resp.tool_use_blocks:
                tool_calls = [
                    ATIFToolCall(
                        tool_call_id=b.id,
                        function_name=b.name,
                        arguments=b.input,
                    )
                    for b in resp.tool_use_blocks
                ]

            metrics = None
            usage = resp.usage
            if usage.input_tokens or usage.output_tokens:
                metrics = ATIFMetrics(
                    prompt_tokens=usage.input_tokens,
                    completion_tokens=usage.output_tokens,
                    cached_tokens=usage.cache_read_input_tokens or None,
                )

            model_name = resp.model if resp.model and resp.model != "<synthetic>" else None

            message = resp.message_text
            if not message and tool_calls:
                tool_names = ", ".join(tc.function_name for tc in tool_calls)
                message = f"[Called: {tool_names}]"
            if not message and resp.reasoning_text:
                message = "[Thinking...]"

            raw_steps.append(
                ATIFStep(
                    step_id=step_id,
                    timestamp=resp.timestamp,
                    source="agent",
                    message=message,
                    reasoning_content=resp.reasoning_text,
                    tool_calls=tool_calls,
                    metrics=metrics,
                    model_name=model_name,
                )
            )
            step_id += 1

        elif cm.type == "system":
            message = _format_system_message(cm)
            if message:
                raw_steps.append(
                    ATIFStep(
                        step_id=step_id,
                        timestamp=cm.original.timestamp,
                        source="system",
                        message=message,
                    )
                )
                step_id += 1

        elif cm.type == "compact_summary":
            content = cm.original.content
            message = content if isinstance(content, str) else str(content)
            raw_steps.append(
                ATIFStep(
                    step_id=step_id,
                    timestamp=cm.original.timestamp,
                    source="system",
                    message=message,
                )
            )
            step_id += 1

    return _insert_gap_separators(raw_steps)


def _insert_gap_separators(steps: list[ATIFStep]) -> list[ATIFStep]:
    """Insert a system separator before every user message showing idle time.

    The separator gets the user message's timestamp so Harbor shows:
      prev step  →  separator: +Nm (the idle gap)
      separator  →  user step: +0s (reset)
    """
    if not steps:
        return steps

    result: list[ATIFStep] = [steps[0]]
    for step in steps[1:]:
        if step.source == "user" and step.timestamp and result[-1].timestamp:
            gap = _seconds_between(result[-1].timestamp, step.timestamp)
            if gap > 0:
                label = _format_duration(gap)
                result.append(
                    ATIFStep(
                        step_id=0,  # renumbered below
                        timestamp=step.timestamp,
                        source="system",
                        message=f"--- user returned after {label} ---",
                    )
                )
        result.append(step)

    # Renumber step_ids sequentially
    for i, s in enumerate(result):
        s.step_id = i + 1

    return result


def _seconds_between(ts_a: str, ts_b: str) -> float:
    """Return seconds between two ISO-8601 timestamps."""
    try:
        a = datetime.fromisoformat(ts_a.replace("Z", "+00:00"))
        b = datetime.fromisoformat(ts_b.replace("Z", "+00:00"))
        return (b - a).total_seconds()
    except (ValueError, TypeError):
        return 0.0


def _format_duration(seconds: float) -> str:
    """Format seconds into a human-readable duration string."""
    total = int(seconds)
    hours, remainder = divmod(total, 3600)
    minutes, secs = divmod(remainder, 60)
    if hours > 0:
        return f"{hours}h {minutes}m"
    if minutes > 0:
        return f"{minutes}m {secs}s"
    return f"{secs}s"


def _format_system_message(cm: ClassifiedMessage) -> str | None:
    """Format a system message for ATIF."""
    msg = cm.original
    subtype = msg.subtype

    if subtype == "compact_boundary":
        meta = msg.compact_metadata or {}
        trigger = meta.get("trigger", "unknown")
        pre_tokens = meta.get("preTokens", "?")
        return f"Context compacted (trigger: {trigger}, pre-compaction tokens: {pre_tokens})"

    elif subtype == "microcompact_boundary":
        meta = msg.microcompact_metadata or {}
        tokens_saved = meta.get("tokensSaved", "?")
        num_compacted = len(meta.get("compactedToolIds", []))
        return f"Context microcompacted (tokens saved: {tokens_saved}, tool results compacted: {num_compacted})"

    elif subtype == "api_error":
        error = msg.error or {}
        status = error.get("status", "?")
        return f"API error (status: {status})"

    elif subtype == "local_command":
        content = msg.content
        return f"Command: {content}" if content else None

    return None
