"""``abreka branch summary`` — inspect rooted subtree summaries."""

from __future__ import annotations

import json as _json

import click

from abreka.branch import (
    BranchSummary,
    compute_branch_summary,
    render_branch_overview,
    render_branch_summary,
)
from abreka.config import find_abreka_dir, load_config, load_index
from abreka.persistence import normalize_exp_id

_SORT_CHOICES = ("best", "recent", "size", "health", "attention")


@click.command("summary")
@click.argument("exp_id", required=False)
@click.option("--all", "show_all", is_flag=True, help="Summarize every real branch in the DAG.")
@click.option("--compact", is_flag=True, help="One-section-per-branch compact view.")
@click.option("--verbose", is_flag=True, help="Include full findings and tag/term detail.")
@click.option("--json", "as_json", is_flag=True, help="Output structured JSON instead of markdown.")
@click.option(
    "--sort",
    "sort_key",
    type=click.Choice(_SORT_CHOICES),
    default="attention",
    show_default=True,
    help="Sort order for --all.",
)
@click.option(
    "--include-singletons",
    is_flag=True,
    help="With --all, include parentless experiments that have no descendants.",
)
def branch_summary_cmd(
    exp_id: str | None,
    show_all: bool,
    compact: bool,
    verbose: bool,
    as_json: bool,
    sort_key: str,
    include_singletons: bool,
) -> None:
    """Summarize the subtree rooted at EXP_ID (or --all for every branch)."""
    if compact and verbose:
        raise click.ClickException("--compact and --verbose are mutually exclusive.")
    if show_all and exp_id:
        raise click.ClickException("Pass either EXP_ID or --all, not both.")
    if not show_all and not exp_id:
        raise click.ClickException("Either EXP_ID or --all is required.")

    abreka_dir = find_abreka_dir()
    config = load_config(abreka_dir)
    index = load_index(abreka_dir)
    primary = config.experiment.primary_metric
    direction = config.experiment.metric_direction

    if show_all:
        summaries = _compute_all_roots(index, abreka_dir, primary, direction, include_singletons)
        if as_json:
            click.echo(_json.dumps([s.to_dict() for s in _sort_for_output(summaries, sort_key)], indent=2))
            return
        if compact or True:  # overview is inherently compact
            click.echo(render_branch_overview(_sort_for_output(summaries, sort_key), sort_key))
        return

    eid = normalize_exp_id(exp_id)
    if eid not in index:
        raise click.ClickException(f"Experiment {eid!r} not found in index.")
    summary = compute_branch_summary(index, abreka_dir, eid, primary, direction)

    if as_json:
        click.echo(_json.dumps(summary.to_dict(), indent=2))
        return

    mode = "compact" if compact else ("verbose" if verbose else "default")
    click.echo(render_branch_summary(summary, mode=mode))


def _compute_all_roots(
    index: dict,
    abreka_dir,
    primary: str,
    direction: str,
    include_singletons: bool,
) -> list[BranchSummary]:
    roots = [eid for eid, entry in index.items() if not entry.get("parents")]
    summaries: list[BranchSummary] = []
    for rid in roots:
        summary = compute_branch_summary(index, abreka_dir, rid, primary, direction)
        if not include_singletons and summary.subtree_size < 2:
            continue
        summaries.append(summary)
    return summaries


def _sort_for_output(summaries: list[BranchSummary], sort_key: str) -> list[BranchSummary]:
    from abreka.branch import _sort_summaries  # reuse internal helper

    return _sort_summaries(summaries, sort_key)
