"""Tests for the ``abreka branch summary`` CLI."""

from __future__ import annotations

import json
import os
from pathlib import Path

from click.testing import CliRunner

from abreka.cli import main


def _seed_index(abreka_dir: Path, index: dict) -> None:
    (abreka_dir / "index.json").write_text(json.dumps(index))


def _exp(
    eid: str,
    *,
    status: str = "completed",
    parents: list[str] | None = None,
    acc: float | None = None,
    created_at: str = "2026-04-08T10:00:00+00:00",
) -> dict:
    entry: dict = {
        "id": eid,
        "status": status,
        "hypothesis": f"hypothesis for {eid}",
        "method": "",
        "parents": parents or [],
        "tags": [],
        "created_at": created_at,
    }
    if acc is not None:
        entry["metrics"] = {"val": {"accuracy": acc}}
    return entry


class TestBranchSummaryCli:
    def test_single_branch_default(self, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed_index(abreka_dir, {
            "0001": _exp("0001", acc=0.80, created_at="2026-04-01T00:00:00+00:00"),
            "0002": _exp("0002", parents=["0001"], acc=0.85, created_at="2026-04-02T00:00:00+00:00"),
            "0003": _exp("0003", parents=["0002"], acc=0.90, created_at="2026-04-03T00:00:00+00:00"),
            "0004": _exp("0004", parents=["0003"], acc=0.92, created_at="2026-04-04T00:00:00+00:00"),
        })
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "0001"])
        assert result.exit_code == 0, result.output
        assert "Branch Summary: 0001" in result.output
        assert "Performance" in result.output
        assert "Health" in result.output

    def test_compact_mode(self, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed_index(abreka_dir, {
            "0001": _exp("0001", acc=0.80),
            "0002": _exp("0002", parents=["0001"], acc=0.90),
        })
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "0001", "--compact"])
        assert result.exit_code == 0, result.output
        assert "### Branch 0001" in result.output
        assert "Performance" not in result.output  # compact omits section headers

    def test_json_mode_is_parseable(self, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed_index(abreka_dir, {
            "0001": _exp("0001", acc=0.80),
            "0002": _exp("0002", parents=["0001"], acc=0.90),
        })
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "0001", "--json"])
        assert result.exit_code == 0, result.output
        data = json.loads(result.output)
        assert data["root_id"] == "0001"
        assert "health_status" in data

    def test_unknown_exp_id_errors(self, abreka_project):
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "9999"])
        assert result.exit_code != 0
        assert "not found" in result.output.lower()

    def test_all_filters_singletons_by_default(self, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed_index(abreka_dir, {
            "0001": _exp("0001", acc=0.80),
            "0002": _exp("0002", parents=["0001"], acc=0.90),
            # Singleton root — should be filtered out by default
            "0050": _exp("0050", acc=0.70),
        })
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "--all"])
        assert result.exit_code == 0, result.output
        assert "Branch 0001" in result.output
        assert "Branch 0050" not in result.output

    def test_all_include_singletons(self, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed_index(abreka_dir, {
            "0001": _exp("0001", acc=0.80),
            "0050": _exp("0050", acc=0.70),
        })
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "--all", "--include-singletons"])
        assert result.exit_code == 0, result.output
        assert "Branch 0001" in result.output
        assert "Branch 0050" in result.output

    def test_all_json(self, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed_index(abreka_dir, {
            "0001": _exp("0001", acc=0.80),
            "0002": _exp("0002", parents=["0001"], acc=0.90),
            "0100": _exp("0100", acc=0.95),
            "0101": _exp("0101", parents=["0100"], acc=0.97),
        })
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "--all", "--json"])
        assert result.exit_code == 0, result.output
        data = json.loads(result.output)
        assert isinstance(data, list)
        root_ids = {s["root_id"] for s in data}
        assert root_ids == {"0001", "0100"}

    def test_requires_id_or_all(self, abreka_project):
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary"])
        assert result.exit_code != 0

    def test_id_and_all_mutually_exclusive(self, abreka_project):
        os.chdir(abreka_project)
        result = CliRunner().invoke(main, ["branch", "summary", "0001", "--all"])
        assert result.exit_code != 0
