"""Output formatting for CLI commands.

Handles table/JSON rendering, success/error messages, and progress display.
TTY-aware: uses Rich tables in interactive mode, plain text when piped.
"""

from __future__ import annotations

import dataclasses
import json
import sys
from typing import Any

import click


def is_tty() -> bool:
    """Check if stdout is a TTY."""
    return sys.stdout.isatty()


def success(message: str) -> None:
    """Print a success message."""
    click.echo(message)


def error(message: str | Exception) -> None:
    """Print an error message to stderr."""
    text = str(message)
    click.echo(f"Error: {text}", err=True)


def info(message: str) -> None:
    """Print an informational message."""
    click.echo(message)


def render_table(
    items: list[Any],
    columns: list[str],
    fmt: str = "table",
) -> None:
    """Render a list of dataclass items as a table or JSON."""
    if fmt == "json":
        data = [
            dataclasses.asdict(item)
            if dataclasses.is_dataclass(item) and not isinstance(item, type)
            else item
            for item in items
        ]
        click.echo(json.dumps(data, indent=2, default=str, sort_keys=True))
        return

    if not items:
        click.echo("No items found.")
        return

    # Plain text table with headers
    headers = [col.replace("_", " ").title() for col in columns]
    rows: list[list[str]] = []
    for item in items:
        d: dict[str, Any] = (
            dataclasses.asdict(item)
            if dataclasses.is_dataclass(item) and not isinstance(item, type)
            else item
        )
        row = [str(d.get(col, "")) for col in columns]
        rows.append(row)

    # Calculate column widths
    widths = [len(h) for h in headers]
    for row in rows:
        for i, cell in enumerate(row):
            widths[i] = max(widths[i], len(cell))

    # Print header
    header_line = "  ".join(h.ljust(widths[i]) for i, h in enumerate(headers))
    click.echo(header_line)
    click.echo("  ".join("-" * w for w in widths))

    # Print rows
    for row in rows:
        line = "  ".join(cell.ljust(widths[i]) for i, cell in enumerate(row))
        click.echo(line)


def render_detail(title: str, fields: dict[str, str]) -> None:
    """Render key-value detail output (for info commands)."""
    click.echo(f"=== {title}")
    max_key = max(len(k) for k in fields) if fields else 0
    for key, value in fields.items():
        click.echo(f"{key.ljust(max_key)}  {value}")
