#
#   Imandra Inc.
#
#   speclogician/presentation/renderers/data_artifact.py
#

from rich.console import Group
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from rich.syntax import Syntax
from rich.rule import Rule

from speclogician.presentation.ctx import RenderCtx
from speclogician.presentation.models.data_artifact import DocRefPM, SrcCodeRefPM


def _kv_table(ctx: RenderCtx) -> Table:
    # tighter + predictable widths
    t = Table(
        show_header=False,
        box=None,            # no box for header table
        show_edge=False,
        pad_edge=False,
        expand=True,
    )
    t.add_column(style="bold", no_wrap=True, width=10)  # fixed key col
    t.add_column(ratio=1)                               # value col fills remaining
    return t


def _add_kv(t: Table, k: str, v: str | None, *, style: str | None = None) -> None:
    if v is None:
        return
    v = v.strip()
    if not v:
        return
    t.add_row(Text(k, style="bold"), Text(v, style=style or ""))


def render_doc_ref(pm: DocRefPM, *, ctx: RenderCtx):
    blocks = []

    # Header
    t = _kv_table(ctx)
    _add_kv(t, "kind", "doc_ref", style="magenta")
    if getattr(ctx, "show_ids", False):
        _add_kv(t, "art_id", pm.core.art_id, style="dim")
    _add_kv(t, "meta", pm.meta)

    if t.row_count > 0:
        blocks.append(t)

    # Text section
    text = (pm.text or "").strip()

    blocks.append(Rule("text"))

    if getattr(ctx, "show_code", True):
        if text:
            blocks.append(Syntax(text, "markdown", word_wrap=True))
        else:
            blocks.append(Text("(empty)", style="dim"))
    else:
        if not text:
            blocks.append(Text("(empty)", style="dim"))
        else:
            snippet = text if len(text) <= 200 else text[:200] + "…"
            blocks.append(Text(snippet))

    return Panel(Group(*blocks), title="[bold]Doc reference[/bold]", border_style="magenta")

# -----------------------------------------------------------------------------
# SrcCodeRef
# -----------------------------------------------------------------------------

def _maybe_code_block(
    *,
    title: str,
    content: str | None,
    lang: str,
    show_code: bool,
) -> list[object]:
    """
    Returns renderables for a section that always shows something:
    - if show_code: Syntax when present, else '(empty)'
    - if not show_code: snippet when present, else '(empty)'
    """
    blocks: list[object] = [Rule(title)]
    text = (content or "").strip()

    if not text:
        blocks.append(Text("(empty)", style="dim"))
        return blocks

    if show_code:
        blocks.append(Syntax(text, lang, word_wrap=True))
    else:
        snippet = text if len(text) <= 200 else text[:200] + "…"
        blocks.append(Text(snippet))
    return blocks


def render_src_code_ref(pm: SrcCodeRefPM, *, ctx: RenderCtx):
    blocks: list[object] = []

    # --- header ---
    t = _kv_table(ctx)
    _add_kv(t, "kind", "src_code_ref", style="magenta")

    if getattr(ctx, "show_ids", False):
        _add_kv(t, "art_id", pm.core.art_id, style="dim")

    _add_kv(t, "language", pm.language)
    _add_kv(t, "file_path", pm.file_path)
    _add_kv(t, "meta", pm.meta)

    if t.row_count > 0:
        blocks.append(t)

    show_code = getattr(ctx, "show_code", True)

    # --- src_code section (always visible; shows (empty) if missing) ---
    lang = (pm.language or "text").lower()
    blocks.extend(
        _maybe_code_block(
            title="src_code",
            content=pm.src_code,
            lang=lang,
            show_code=show_code,
        )
    )

    # --- iml_code section (always visible; shows (empty) if missing) ---
    blocks.extend(
        _maybe_code_block(
            title="iml_code",
            content=pm.iml_code,
            lang="ocaml",
            show_code=show_code,
        )
    )

    return Panel(Group(*blocks), title="[bold]Source code reference[/bold]", border_style="magenta")