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

from __future__ import annotations

from rich import box
from rich.panel import Panel
from rich.table import Table, Column
from rich.text import Text

from speclogician.presentation.ctx import RenderCtx
from speclogician.presentation.models.instances_list import InstancesListPM


def _bullet_list(changes: str) -> Text:
    """
    Render a comma-separated change list as a left-aligned bullet list.
    """
    if not changes:
        return Text("–", style="dim")

    items = [c.strip() for c in changes.split(",") if c.strip()]
    if not items:
        return Text("–", style="dim")

    txt = Text()
    for i, item in enumerate(items):
        if i > 0:
            txt.append("\n")
        txt.append("• ", style="dim")
        txt.append(item)
    return txt


def render_instances_list(pm: InstancesListPM, *, ctx: RenderCtx):
    b = box.MINIMAL if ctx.compact else box.SIMPLE

    columns = [
        Column(header="State ID", justify="center"),
        Column(header="Changes", justify="left"),
        Column(header="Domain model", justify="center"),
        Column(header="Preds\n# (Errors, Used)", justify="center"),
        Column(header="Scenarios\n# (Errors, Used)", justify="center"),
        Column(header="Test traces\n# (Formalized, Matched)", justify="center"),
        Column(header="Log traces\n# (Formalized, Matched)", justify="center"),
        Column(header="Src code arts\n# (Matched)", justify="center"),
        Column(header="Doc arts\n# (Matched)", justify="center"),
    ]

    t = Table(
        *columns,
        title="SpecLogician State List",
        expand=True,
        highlight=True,
        show_edge=False,
        box=b,
    )

    for idx, row in enumerate(pm.rows):
        if idx > 0:
            t.add_section()  # thin separator between instances

        s = row.summary

        # ---- Domain model ----
        domain_str = str(getattr(s, "base_status", "unknown"))

        # ---- Predicates (totals) ----
        preds_total = int(getattr(s, "num_preds_total", 0) or 0)
        preds_err = int(getattr(s, "num_preds_errored", 0) or 0)
        preds_used = int(getattr(s, "num_preds_matched", 0) or 0)
        preds_str = f"{preds_total} ({preds_err}, {preds_used})"

        # These are also available:
        #   num_state_preds_total / matched / errored
        #   num_action_preds_total / matched / errored

        # ---- Scenarios ----
        sc_total = int(getattr(s, "num_sc_total", 0) or 0)
        sc_missing = int(getattr(s, "num_sc_missing", 0) or 0)
        sc_inconsistent = int(getattr(s, "num_sc_inconsistent", 0) or 0)
        sc_conflicted = int(getattr(s, "num_sc_conflicted", 0) or 0)

        # "Errors" bucket includes: missing + inconsistent + conflicted
        sc_err = sc_missing + sc_inconsistent + sc_conflicted
        sc_used = int(getattr(s, "num_sc_matched", 0) or 0)
        sc_str = f"{sc_total} ({sc_err}, {sc_used})"

        # ---- Test traces ----
        tt_total = int(getattr(s, "num_test_traces_total", 0) or 0)
        tt_formal = int(getattr(s, "num_test_traces_logic_good", 0) or 0)
        tt_matched = int(getattr(s, "num_test_traces_matched", 0) or 0)
        test_str = f"{tt_total} ({tt_formal}, {tt_matched})"

        # ---- Log traces ----
        lt_total = int(getattr(s, "num_log_traces_total", 0) or 0)
        lt_formal = int(getattr(s, "num_log_traces_logic_good", 0) or 0)
        lt_matched = int(getattr(s, "num_log_traces_matched", 0) or 0)
        log_str = f"{lt_total} ({lt_formal}, {lt_matched})"

        # ---- Data artifacts ----
        src_matched = int(getattr(s, "num_src_code_arts_matched", 0) or 0)
        doc_matched = int(getattr(s, "num_doc_arts_matched", 0) or 0)

        t.add_row(
            Text(row.state_label, style="bold green" if idx == 0 else ""),
            _bullet_list(row.changes),
            Text(domain_str),
            Text(preds_str),
            Text(sc_str),
            Text(test_str),
            Text(log_str),
            Text(str(src_matched)),
            Text(str(doc_matched)),
        )

    return Panel(t, title="[bold]Instances[/bold]", border_style="magenta")