"""Output formatting for Horizon CLI."""

from __future__ import annotations

import json as _json
import sys


def output(data, *, json_mode: bool = False):
    """Format and print data as JSON or human-readable text."""
    if json_mode:
        _json.dump(data, sys.stdout, indent=2, default=str)
        print()
        return

    if isinstance(data, dict):
        if "error" in data:
            print(f"Error: {data['error']}", file=sys.stderr)
            raise SystemExit(1)
        _render_dict(data)
    elif isinstance(data, list):
        if not data:
            print("No results.")
            return
        if isinstance(data[0], dict):
            _render_table(data)
        else:
            for item in data:
                print(item)
    else:
        print(data)


def _render_dict(d: dict):
    """Render a dict as aligned key-value pairs."""
    if not d:
        return
    max_key = max(len(str(k)) for k in d)
    for k, v in d.items():
        label = str(k).replace("_", " ")
        if isinstance(v, float):
            v = f"{v:.6f}" if abs(v) < 1 else f"{v:,.2f}"
        print(f"  {label:<{max_key + 2}} {v}")


def _render_table(rows: list[dict]):
    """Render a list of dicts as an aligned table."""
    if not rows:
        return
    keys = list(rows[0].keys())
    # Calculate column widths (cap at 30 chars)
    widths: dict[str, int] = {}
    for k in keys:
        col_vals = [_trunc(str(r.get(k, "")), 30) for r in rows]
        widths[k] = min(30, max(len(str(k)), *(len(v) for v in col_vals)))
    # Header
    header = "  ".join(str(k).ljust(widths[k]) for k in keys)
    print(header)
    print("-" * len(header))
    for row in rows:
        cols = []
        for k in keys:
            val = _trunc(_format_val(row.get(k, "")), 30)
            cols.append(val.ljust(widths[k]))
        print("  ".join(cols))


def _format_val(v) -> str:
    """Format a value for table display."""
    if isinstance(v, float):
        if abs(v) < 0.01 and v != 0:
            return f"{v:.6f}"
        return f"{v:.4f}"
    if isinstance(v, bool):
        return "yes" if v else "no"
    return str(v)


def _trunc(s: str, n: int) -> str:
    """Truncate string to n chars."""
    return s[: n - 2] + ".." if len(s) > n else s
