"""
Brynq CLI Theme -- Consistent styling for all terminal output.

Provides branded banners, colored output, tables, and status indicators.
Falls back to plain text if `rich` is not installed.
"""

from __future__ import annotations

import io
import sys
from typing import Optional

# ── Rich availability ─────────────────────────────────────────────────────

try:
    from rich.console import Console
    from rich.table import Table
    from rich.panel import Panel
    from rich.text import Text
    from rich.columns import Columns
    from rich import box
    HAS_RICH = True
except ImportError:
    HAS_RICH = False

# ── Colors ────────────────────────────────────────────────────────────────

CYAN = "#00d4ff"
DIM_CYAN = "#0097b2"
GREEN = "#22c55e"
RED = "#ef4444"
YELLOW = "#f59e0b"
PURPLE = "#a78bfa"
DIM = "#6b7280"
WHITE = "#e0e0e0"
BLUE = "#3b82f6"

# ── Console singleton ────────────────────────────────────────────────────

_console: Optional["Console"] = None


def _make_utf8_file():
    """Create a UTF-8 wrapped stdout for Rich on Windows."""
    if sys.platform == "win32" and sys.stdout and hasattr(sys.stdout, "buffer"):
        return io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace", line_buffering=True)
    return None


def get_console() -> "Console":
    global _console
    if _console is None:
        if HAS_RICH:
            utf8_file = _make_utf8_file()
            if utf8_file:
                _console = Console(file=utf8_file, force_terminal=True)
            else:
                _console = Console(stderr=False)
        else:
            _console = None
    return _console


# ── Banner ────────────────────────────────────────────────────────────────

LOGO = r"""
  ██████╗ ██████╗ ██╗   ██╗███╗   ██╗ ██████╗
  ██╔══██╗██╔══██╗╚██╗ ██╔╝████╗  ██║██╔═══██╗
  ██████╔╝██████╔╝ ╚████╔╝ ██╔██╗ ██║██║   ██║
  ██╔══██╗██╔══██╗  ╚██╔╝  ██║╚██╗██║██║▄▄ ██║
  ██████╔╝██║  ██║   ██║   ██║ ╚████║╚██████╔╝
  ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚═╝  ╚═══╝ ╚══▀▀═╝"""

TAGLINE = "The operating system for AI workforces"


def print_banner(version: str = "0.420.69"):
    """Print the branded Brynq banner."""
    c = get_console()
    if c and HAS_RICH:
        logo_text = Text(LOGO, style=f"bold {CYAN}")
        c.print(logo_text)
        c.print(f"  [dim]{TAGLINE}[/dim]                    [bold {DIM_CYAN}]v{version}[/bold {DIM_CYAN}]")
        c.print()
    else:
        print(LOGO)
        print(f"  {TAGLINE}                    v{version}")
        print()


# ── Help / Command Groups ────────────────────────────────────────────────

COMMAND_GROUPS = [
    (
        "Messaging",
        [
            ("post", "Post a message to a channel"),
            ("read", "Read unread messages from a channel"),
            ("inbox", "Check all channels for unread messages"),
            ("broadcast", "Post a message to all channels"),
            ("say", "Send a human message to agents (HITL)"),
            ("history", "Show full channel history"),
            ("channels", "List all broker channels"),
            ("search", "Search messages across channels"),
        ],
    ),
    (
        "Agents & Swarms",
        [
            ("spawn", "Spawn a local LLM agent"),
            ("swarm", "Spawn a mixed swarm of agents"),
            ("agents", "List all running agents"),
            ("kill", "Kill a running agent by name"),
            ("kill-all", "Kill all running agents"),
            ("backends", "Show available LLM backends"),
            ("chat", "One-shot chat with a local LLM"),
        ],
    ),
    (
        "System",
        [
            ("status", "Session status + auth + unread"),
            ("sessions", "List connected sessions"),
            ("init", "Set up Brynq for this project"),
            ("connect", "Connect an AI platform (API key)"),
            ("ceo", "Interactive CEO terminal + orchestrator"),
            ("tui", "Launch native terminal UI (Textual)"),
            ("daemon", "Persistent agent daemon management"),
        ],
    ),
    (
        "Remote API",
        [
            ("register", "Register with a Brynq API server"),
            ("remote-post", "Post message via REST API"),
            ("remote-inbox", "Check inbox via REST API"),
            ("remote-agents", "List agents via REST API"),
            ("hardware", "Declare hardware capabilities"),
        ],
    ),
    (
        "Workflows",
        [
            ("workflow-executor", "Start the workflow auto-dispatcher"),
        ],
    ),
]


def print_help():
    """Print branded help with grouped commands."""
    print_banner()
    c = get_console()

    if c and HAS_RICH:
        c.print(f"  [bold {WHITE}]Usage:[/bold {WHITE}]  [bold {CYAN}]brynq[/bold {CYAN}] [dim]<command>[/dim] [dim][options][/dim]")
        c.print()

        for group_name, commands in COMMAND_GROUPS:
            c.print(f"  [{YELLOW} bold]{group_name}[/{YELLOW} bold]")
            for cmd, desc in commands:
                c.print(f"    [{CYAN}]{cmd:<22}[/{CYAN}] [dim]{desc}[/dim]")
            c.print()

        c.print(f"  [dim]Run[/dim] [bold {CYAN}]brynq <command> --help[/bold {CYAN}] [dim]for detailed usage[/dim]")
        c.print()
    else:
        print("  Usage:  brynq <command> [options]")
        print()
        for group_name, commands in COMMAND_GROUPS:
            print(f"  {group_name}")
            for cmd, desc in commands:
                print(f"    {cmd:<22} {desc}")
            print()
        print("  Run brynq <command> --help for detailed usage")
        print()


# ── Output helpers ────────────────────────────────────────────────────────

def success(msg: str):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [{GREEN}]✓[/{GREEN}] {msg}")
    else:
        print(f"  [OK] {msg}")


def error(msg: str):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [{RED}]✗[/{RED}] {msg}")
    else:
        print(f"  [ERROR] {msg}")


def warn(msg: str):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [{YELLOW}]![/{YELLOW}] {msg}")
    else:
        print(f"  [WARN] {msg}")


def info(msg: str):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [{DIM}]→[/{DIM}] {msg}")
    else:
        print(f"  {msg}")


def heading(msg: str):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"\n  [bold {CYAN}]{msg}[/bold {CYAN}]")
    else:
        print(f"\n  {msg}")


def dim(msg: str):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [dim]{msg}[/dim]")
    else:
        print(f"  {msg}")


def label_value(label: str, value: str, label_color: str = DIM, value_color: str = WHITE):
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [{label_color}]{label}[/{label_color}]  [{value_color}]{value}[/{value_color}]")
    else:
        print(f"  {label}  {value}")


# ── Status dots ──────────────────────────────────────────────────────────

def status_dot(status: str) -> str:
    """Return a colored status indicator string."""
    if not HAS_RICH:
        return f"[{status.upper()}]"
    s = status.lower()
    if s in ("active", "online", "running", "ok", "connected"):
        return f"[bold {GREEN}]●[/bold {GREEN}] [{GREEN}]{status}[/{GREEN}]"
    elif s in ("idle", "stale", "configured"):
        return f"[bold {YELLOW}]●[/bold {YELLOW}] [{YELLOW}]{status}[/{YELLOW}]"
    elif s in ("dead", "offline", "error", "failed"):
        return f"[bold {RED}]○[/bold {RED}] [{RED}]{status}[/{RED}]"
    elif s in ("not configured", "not running", "not available", "not detected"):
        return f"[{DIM}]○ {status}[/{DIM}]"
    else:
        return f"[{DIM}]● {status}[/{DIM}]"


# ── Tables ───────────────────────────────────────────────────────────────

def print_table(title: str, columns: list[str], rows: list[list[str]]):
    """Print a formatted table."""
    c = get_console()
    if c and HAS_RICH:
        table = Table(
            title=title,
            title_style=f"bold {CYAN}",
            border_style=DIM,
            box=box.ROUNDED,
            show_lines=False,
            padding=(0, 1),
        )
        for col in columns:
            table.add_column(col, style=WHITE, header_style=f"bold {DIM_CYAN}")
        for row in rows:
            table.add_row(*row)
        c.print()
        c.print(table)
    else:
        print(f"\n  {title}")
        header = "  ".join(f"{col:<15}" for col in columns)
        print(f"  {header}")
        print(f"  {'-' * len(header)}")
        for row in rows:
            print(f"  {'  '.join(f'{cell:<15}' for cell in row)}")


# ── Message formatting ───────────────────────────────────────────────────

def format_message(timestamp: str, name: str, platform: str, msg_type: str, message: str, is_you: bool = False) -> str:
    """Format a channel message for display."""
    if not HAS_RICH:
        you = " <-- you" if is_you else ""
        return f"  [{timestamp}] {name}@{platform} ({msg_type}): {message}{you}"

    ts = f"[{DIM}]{timestamp}[/{DIM}]"

    # Color the sender by platform
    platform_colors = {
        "claude": "#d97706",
        "gemini": "#4285f4",
        "ollama": "#6366f1",
        "human": GREEN,
        "system": DIM,
    }
    name_color = platform_colors.get(platform.lower(), PURPLE)
    sender = f"[bold {name_color}]{name}[/bold {name_color}]"

    # Color the message type badge
    type_colors = {
        "error": RED,
        "alert": RED,
        "task": YELLOW,
        "request": PURPLE,
        "status": DIM,
        "info": BLUE,
    }
    type_color = type_colors.get(msg_type, DIM)
    badge = f"[{type_color}]{msg_type}[/{type_color}]"

    you_marker = f" [{GREEN}]◀ you[/{GREEN}]" if is_you else ""
    return f"  {ts} {sender} [{badge}] {message}{you_marker}"


# ── Section separator ────────────────────────────────────────────────────

def separator():
    c = get_console()
    if c and HAS_RICH:
        c.print(f"  [{DIM}]{'─' * 50}[/{DIM}]")
    else:
        print(f"  {'─' * 50}")


# ── Inbox formatting ─────────────────────────────────────────────────────

def format_inbox_channel(channel: str, unread: int, preview: str = ""):
    c = get_console()
    if c and HAS_RICH:
        badge = f"[bold {CYAN}]{unread}[/bold {CYAN}]"
        ch = f"[bold {WHITE}]#{channel}[/bold {WHITE}]"
        prev = f"  [dim]{preview}[/dim]" if preview else ""
        c.print(f"  {badge:>8} unread  {ch}{prev}")
    else:
        prev = f" -- {preview}" if preview else ""
        print(f"  #{channel}: {unread} unread{prev}")
