from __future__ import annotations

import json
from typing import Any

import yaml
from rich.console import Console
from rich.table import Table

from .utils import to_plain_data


def render_output(console: Console, payload: Any, output_format: str = "json") -> None:
    plain = to_plain_data(payload)
    if output_format == "json":
        console.print_json(json.dumps(plain, ensure_ascii=False, default=str))
        return
    if output_format == "yaml":
        console.print(yaml.safe_dump(plain, allow_unicode=True, sort_keys=False))
        return
    if output_format == "table":
        _render_table(console, plain)
        return
    console.print(str(plain))


def _render_table(console: Console, payload: Any) -> None:
    if isinstance(payload, list) and payload and all(isinstance(item, dict) for item in payload):
        keys = sorted({key for item in payload for key in item})
        table = Table(show_lines=False)
        for key in keys:
            table.add_column(key)
        for item in payload:
            table.add_row(*(stringify(item.get(key)) for key in keys))
        console.print(table)
        return

    if isinstance(payload, dict):
        table = Table(show_header=True)
        table.add_column("key")
        table.add_column("value")
        for key, value in payload.items():
            table.add_row(str(key), stringify(value))
        console.print(table)
        return

    console.print(stringify(payload))


def stringify(value: Any) -> str:
    plain = to_plain_data(value)
    if isinstance(plain, (dict, list)):
        return json.dumps(plain, ensure_ascii=False, default=str)
    return "" if plain is None else str(plain)
