"""Task delegation indicators for the talk session.

Renders progress indicators for ctl_delegate (single task) and ctl_await
(batch wait) in the terminal. Also emits JSON events for machine consumers.

Spec source: docs/proposals/subagent-coordination.md UX Rendering section.
"""

from __future__ import annotations

import asyncio
import json
from typing import TYPE_CHECKING

from rich.console import Console
from rich.text import Text

if TYPE_CHECKING:
    from anima.shell.cli_commands.talk_deps import TalkDeps


# --- Glyphs and styles ---

GLYPH_TASK_ACTIVE = "\u25c7"  # ◇ hollow diamond = waiting
GLYPH_TASK_DONE = "\u25c6"  # ◆ filled diamond = done
GLYPH_CHECK = "\u2713"  # ✓
GLYPH_CROSS = "\u2717"  # ✗
GLYPH_SPINNER = "\u28ff"  # ⣿ braille spinner
GLYPH_TREE_BRANCH = "\u251c"  # ├
GLYPH_TREE_LAST = "\u2514"  # └


def format_task_wait_line(
    description: str,
    elapsed_seconds: int,
    status: str | None = None,
) -> str:
    """Format a single-task wait indicator line.

    >>> format_task_wait_line("Analyze auth", 8)
    '  ◇ delegate: Analyze auth ── 0:08'
    >>> format_task_wait_line("Analyze auth", 47, status="completed")
    '  ◆ delegate: Analyze auth ── 0:47 ✓'
    >>> format_task_wait_line("Analyze auth", 47, status="failed")
    '  ◆ delegate: Analyze auth ── 0:47 ✗'
    """
    desc = description[:40] + ("..." if len(description) > 40 else "")
    mins, secs = divmod(elapsed_seconds, 60)
    timer = f"{mins}:{secs:02d}"

    if status == "completed":
        return f"  {GLYPH_TASK_DONE} delegate: {desc} \u2500\u2500 {timer} {GLYPH_CHECK}"
    elif status == "failed":
        return f"  {GLYPH_TASK_DONE} delegate: {desc} \u2500\u2500 {timer} {GLYPH_CROSS}"
    else:
        return f"  {GLYPH_TASK_ACTIVE} delegate: {desc} \u2500\u2500 {timer}"


def format_await_header(
    total: int,
    completed: int,
    elapsed_seconds: int,
) -> str:
    """Format the await tree header line.

    >>> format_await_header(3, 0, 12)
    '  ◇ awaiting 3 tasks ── 0:12'
    >>> format_await_header(3, 2, 34)
    '  ◇ awaiting 3 tasks ── 0:34 (2/3 done)'
    """
    mins, secs = divmod(elapsed_seconds, 60)
    timer = f"{mins}:{secs:02d}"
    progress = f" ({completed}/{total} done)" if completed > 0 else ""
    return f"  {GLYPH_TASK_ACTIVE} awaiting {total} tasks \u2500\u2500 {timer}{progress}"


def format_await_summary(
    total: int,
    failed: int,
    elapsed_seconds: int,
) -> str:
    """Format the collapsed await summary line.

    >>> format_await_summary(3, 0, 41)
    '  ◇ 3 tasks completed ── 0:41'
    >>> format_await_summary(3, 1, 41)
    '  ◇ 3 tasks completed (1 failed) ── 0:41'
    """
    mins, secs = divmod(elapsed_seconds, 60)
    timer = f"{mins}:{secs:02d}"
    fail_note = f" ({failed} failed)" if failed > 0 else ""
    return f"  {GLYPH_TASK_ACTIVE} {total} tasks completed{fail_note} \u2500\u2500 {timer}"


def format_await_child_line(
    description: str,
    elapsed_seconds: int,
    status: str,
    is_last: bool = False,
) -> str:
    """Format one child line in the await tree.

    >>> '✓ Analyze auth' in format_await_child_line("Analyze auth", 8, "completed")
    True
    >>> '└' in format_await_child_line("Check tests", 34, "running", is_last=True)
    True
    """
    branch = GLYPH_TREE_LAST if is_last else GLYPH_TREE_BRANCH
    desc = description[:36] + ("..." if len(description) > 36 else "")
    mins, secs = divmod(elapsed_seconds, 60)
    timer = f"{mins}:{secs:02d}"

    if status == "completed":
        glyph = GLYPH_CHECK
    elif status in ("failed", "killed", "cancelled"):
        glyph = GLYPH_CROSS
    else:
        glyph = GLYPH_SPINNER

    # Pad description to align timers
    padded_desc = f"{desc:<36}"
    return f"    {branch} {glyph} {padded_desc} {timer}"


async def render_task_indicator(
    *,
    console: Console,
    task_description: str,
    cancel_event: asyncio.Event,
    json_output: bool,
    child_id: str | None = None,
    deps: "TalkDeps | None" = None,
) -> None:
    """Render a live task wait indicator with elapsed timer.

    Runs until cancel_event is set. Updates the line every 1 second.
    For JSON mode, emits task_start and task_done events.
    """
    if json_output:
        console.file.write(
            json.dumps({
                "event": "task_start",
                "task": task_description,
                "child_id": child_id,
            }) + "\n"
        )
        await cancel_event.wait()
        return

    start = asyncio.get_event_loop().time()
    while not cancel_event.is_set():
        elapsed = int(asyncio.get_event_loop().time() - start)
        line = format_task_wait_line(task_description, elapsed)

        def _emit(l: str = line) -> None:
            console.file.write("\r\033[K")
            console.file.flush()
            console.print(Text(l, style="dim cyan"))

        if deps is not None:
            deps.emit_with_prompt_coordination(emit=_emit)
        else:
            _emit()

        try:
            await asyncio.wait_for(cancel_event.wait(), timeout=1.0)
        except asyncio.TimeoutError:
            pass


def emit_task_done(
    *,
    console: Console,
    task_description: str,
    elapsed_seconds: int,
    status: str,
    json_output: bool,
    child_id: str | None = None,
    deps: "TalkDeps | None" = None,
) -> None:
    """Emit the final task completion line."""
    if json_output:
        console.file.write(
            json.dumps({
                "event": "task_done",
                "task": task_description,
                "child_id": child_id,
                "elapsed_s": elapsed_seconds,
                "status": status,
            }) + "\n"
        )
        return

    line = format_task_wait_line(task_description, elapsed_seconds, status=status)

    def _emit() -> None:
        console.file.write("\r\033[K")
        console.file.flush()
        console.print(Text(line, style="dim green" if status == "completed" else "red"))

    if deps is not None:
        deps.emit_with_prompt_coordination(emit=_emit)
    else:
        _emit()


__all__ = [
    "format_task_wait_line",
    "format_await_header",
    "format_await_summary",
    "format_await_child_line",
    "render_task_indicator",
    "emit_task_done",
]
