"""Renderers for the ResultTable API.

This module provides a Rich-based Renderer implementation that returns a
`rich.table.Table` renderable. The implementation is intentionally small and
focused on the command-line display use-case; keep logic side-effect-free where
possible and let callers decide whether to `Console.print()` or capture output.
"""
from __future__ import annotations

from typing import Any, Dict, Iterable, Optional
import logging

logger = logging.getLogger(__name__)

from SYS.result_table import (
    apply_result_table_layout,
    get_result_table_appearance_mode,
    get_result_table_border_style,
    get_result_table_header_style,
    get_result_table_row_style,
)
from SYS.result_table_api import ColumnSpec, ResultModel, ResultTable, Renderer


class RichRenderer(Renderer):
    """Rich renderer implementing the `Renderer` protocol.

    Usage:
        from rich.console import Console
        table = RichRenderer().render(rows, columns, meta)
        Console().print(table)
    """

    def render(self, rows: Iterable[ResultModel], columns: Iterable[ColumnSpec], meta: Optional[Dict[str, Any]] = None) -> Any:  # pragma: no cover - simple wrapper
        try:
            from rich.table import Table as RichTable
        except Exception as exc:
            raise RuntimeError("rich is required for RichRenderer") from exc

        table = RichTable(
            show_header=True,
            header_style=get_result_table_header_style(),
            border_style=get_result_table_border_style(),
            box=None,
            padding=(0, 1),
            pad_edge=False,
            collapse_padding=True,
            expand=False,
        )
        apply_result_table_layout(table)
        appearance_mode = get_result_table_appearance_mode()
        cols = list(columns)
        for col in cols:
            if str(col.header or "").strip().lower() == "tag":
                table.add_column(col.header, overflow="fold")
            else:
                table.add_column(col.header)

        for row_idx, r in enumerate(rows):
            cells = []
            for col in cols:
                try:
                    raw = col.extractor(r)
                    if col.format_fn:
                        try:
                            cell = col.format_fn(raw)
                        except Exception as exc:
                            logger.exception("Column format function failed for '%s': %s", col.header, exc)
                            cell = str(raw or "")
                    else:
                        cell = str(raw or "")
                except Exception as exc:
                    logger.exception("Column extractor failed for '%s': %s", col.header, exc)
                    cell = ""
                cells.append(cell)
            table.add_row(
                *cells,
                style=get_result_table_row_style(
                    row_idx,
                    appearance_mode=appearance_mode,
                ),
            )

        return table


# Small convenience function

def render_to_console(rows: Iterable[ResultModel], columns: Iterable[ColumnSpec], meta: Optional[Dict[str, Any]] = None) -> None:
    try:
        from rich.console import Console
    except Exception:
        # If rich isn't present, fall back to simple text output
        for r in rows:
            print(" ".join(str((col.extractor(r) or "")) for col in columns))
        return

    table = RichRenderer().render(rows, columns, meta)
    Console().print(table)


def render_result_table(table: ResultTable, renderer: Optional[Renderer] = None) -> Any:
    """Render a ResultTable with the provided renderer (RichRenderer by default)."""

    rend = renderer or RichRenderer()
    return rend.render(table.rows, table.columns, table.meta)


def render_result_table_to_console(table: ResultTable, renderer: Optional[Renderer] = None) -> None:
    try:
        from rich.console import Console
    except Exception:
        for r in table.rows:
            print(" ".join(str((col.extractor(r) or "")) for col in table.columns))
        return

    console = Console()
    console.print(render_result_table(table, renderer))
