"""Rich-based terminal output for the CLI chat."""

from __future__ import annotations

import json
import sys
from typing import Any

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

console = Console(stderr=True)
# Separate console for stdout markdown rendering (not stderr)
_stdout_console = Console()
_stdout = sys.stdout

# Tracks whether we're in raw streaming mode
_streaming_buffer: list[str] = []
_use_markdown = True


def set_markdown_mode(enabled: bool) -> None:
    global _use_markdown
    _use_markdown = enabled


def render_token(content: str) -> None:
    """Buffer token content for later markdown rendering."""
    _streaming_buffer.append(content)
    _stdout.write(content)
    _stdout.flush()


def render_response_end() -> None:
    """Finalize response - re-render with markdown if content has formatting."""
    global _streaming_buffer
    full_text = "".join(_streaming_buffer)
    _streaming_buffer = []

    if not _use_markdown or not full_text.strip():
        _stdout.write("\n")
        _stdout.flush()
        return

    has_code_blocks = "```" in full_text
    has_headers = "\n#" in full_text or full_text.startswith("#")
    has_lists = "\n- " in full_text or "\n* " in full_text

    if has_code_blocks or has_headers or has_lists:
        # Move cursor up to overwrite raw streamed text
        line_count = full_text.count("\n") + 1
        # Clear the raw output
        _stdout.write(f"\033[{line_count}A\033[J")
        _stdout.flush()
        # Re-render with Rich Markdown
        from rich.markdown import Markdown
        _stdout_console.print(Markdown(full_text))
    else:
        _stdout.write("\n")
        _stdout.flush()


def render_newline() -> None:
    _stdout.write("\n")
    _stdout.flush()


def render_tool_call_start(tool_name: str, arguments: dict[str, Any]) -> None:
    # Flush streaming buffer before tool output
    if _streaming_buffer:
        _stdout.write("\n")
        _stdout.flush()
    args_str = json.dumps(arguments, indent=None, default=str)
    if len(args_str) > 200:
        args_str = args_str[:200] + "..."
    console.print(f"\n  [dim]> {escape(tool_name)}({escape(args_str)})[/dim]")


def render_tool_call_end(tool_name: str, status: str, output: Any) -> None:
    if status == "success":
        style = "green"
    else:
        style = "red"

    output_str = ""
    if isinstance(output, dict):
        if "error" in output:
            output_str = f" - {output['error']}"
        elif "content" in output:
            content = output["content"]
            if isinstance(content, str) and len(content) > 200:
                content = content[:200] + "..."
            output_str = f" - {content}"
        elif "stdout" in output:
            stdout = output["stdout"]
            if stdout and len(stdout) > 200:
                stdout = stdout[:200] + "..."
            output_str = f" - {stdout}" if stdout else ""
    text = Text(
        f"  < {tool_name}: {status}{output_str}",
        style=f"dim {style}",
    )
    console.print(text)


def render_error(message: str) -> None:
    console.print(f"\n[red bold]Error:[/red bold] {escape(message)}")


def render_welcome(
    model: str,
    tool_count: int,
    instructions_loaded: bool,
    working_dir: str,
    git_branch: str | None = None,
) -> None:
    console.print(f"\n[bold]Parlor CLI[/bold] - {escape(working_dir)}")
    inst = "loaded" if instructions_loaded else "none"
    branch_info = f" | Branch: {git_branch}" if git_branch else ""
    console.print(
        f"  Model: {escape(model)} | Tools: {tool_count}"
        f" | Instructions: {inst}{branch_info}"
    )
    console.print(
        "  Type [bold]/help[/bold] for commands, "
        "[bold]Ctrl+D[/bold] to exit\n"
    )


def render_help() -> None:
    console.print("\n[bold]Commands:[/bold]")
    console.print("  /new        - Start a new conversation")
    console.print("  /last       - Resume the most recent conversation")
    console.print("  /list       - Show recent conversations")
    console.print("  /resume N   - Resume conversation by number or ID")
    console.print("  /compact    - Summarize and compact message history")
    console.print("  /tools      - List available tools")
    console.print("  /skills     - List available skills")
    console.print("  /model NAME - Switch to a different model")
    console.print("  /quit       - Exit")
    console.print("  Ctrl+C      - Cancel current response")
    console.print("  Ctrl+D      - Exit")
    console.print("\n[bold]Input:[/bold]")
    console.print("  @<path>     - Reference a file or directory")
    console.print("  /<skill>    - Run a registered skill")
    console.print("  Alt+Enter   - Newline (multiline input)\n")


def render_tools(tool_names: list[str]) -> None:
    console.print("\n[bold]Available tools:[/bold]")
    for name in sorted(tool_names):
        console.print(f"  - {name}")
    console.print()


def render_compact_done(original: int, compacted: int) -> None:
    console.print(
        f"\n[dim]Compacted {original} messages -> {compacted} messages[/dim]"
    )


def render_context_footer(
    current_tokens: int,
    auto_compact_threshold: int,
    response_tokens: int = 0,
    max_context: int = 128_000,
) -> None:
    """Render a footer showing context usage after each response."""
    pct_full = min(100, (current_tokens / max_context) * 100)
    tokens_remaining = auto_compact_threshold - current_tokens

    if pct_full > 75:
        color = "red"
    elif pct_full > 50:
        color = "yellow"
    else:
        color = "dim"

    bar_width = 20
    filled = int(bar_width * pct_full / 100)
    bar = "=" * filled + "-" * (bar_width - filled)

    resp_info = f" | response: {response_tokens:,}" if response_tokens else ""
    console.print(
        f"[{color}]  [{bar}] {current_tokens:,}/{max_context:,} "
        f"tokens ({pct_full:.0f}%){resp_info}"
        f" | {tokens_remaining:,} until auto-compact[/{color}]"
    )


def render_streaming_tokens(token_count: int) -> None:
    """Overwrite the current line with token count during streaming."""
    sys.stderr.write(f"\r\033[K  tokens: {token_count:,}")
    sys.stderr.flush()


def clear_streaming_tokens() -> None:
    """Clear the streaming token counter line."""
    sys.stderr.write("\r\033[K")
    sys.stderr.flush()
