"""Tests for the federation registry seam ``mgf.standard.libraries()``.

This is the agent-facing, drift-proof way to learn the OTHER federation
projects (the roster + dependency graph), resolved from the installed
package rather than a copied list that catch-up/sync had to keep chasing.
The invariants pinned here (the ``mgf-common`` ↔ ``mgf-standard``
extraction edge, the record schema) are stable across releases.
"""

from __future__ import annotations

import mgf.standard as ds


class TestLibrariesSeam:
    def test_returns_nonempty_list_of_dicts(self) -> None:
        libs = ds.libraries()
        assert isinstance(libs, list)
        assert libs, "registry resolved empty"
        assert all(isinstance(x, dict) for x in libs)

    def test_each_entry_has_the_documented_schema(self) -> None:
        for entry in ds.libraries():
            for key in (
                "repo",
                "lang",
                "version",
                "requires_python",
                "deps",
                "used_by",
                "extras",
                "third_party_count",
                "purpose",
            ):
                assert key in entry, f"{entry.get('repo')!r} missing {key!r}"
            assert isinstance(entry["deps"], dict)
            assert isinstance(entry["used_by"], list)

    def test_cornerstone_present_and_depends_on_standard(self) -> None:
        # The extraction's defining edge: mgf-common depends on
        # mgf-standard. A stable invariant to pin the resolver against.
        libs = {x["repo"]: x for x in ds.libraries()}
        assert "mgf-common" in libs
        assert "mgf-standard" in libs["mgf-common"]["deps"]

    def test_reverse_edge_is_populated(self) -> None:
        libs = {x["repo"]: x for x in ds.libraries()}
        assert "mgf-common" in libs["mgf-standard"]["used_by"]

    def test_sorted_by_repo(self) -> None:
        repos = [x["repo"] for x in ds.libraries()]
        assert repos == sorted(repos)


class TestReleaseWavesSeam:
    def test_returns_list_of_sorted_string_waves(self) -> None:
        waves = ds.release_waves()
        assert isinstance(waves, list)
        assert waves, "release_waves resolved empty"
        for wave in waves:
            assert isinstance(wave, list)
            assert all(isinstance(r, str) for r in wave)
            assert wave == sorted(wave)

    def test_covers_exactly_the_roster(self) -> None:
        # Every library appears in exactly one wave — the walk order is a
        # partition of the roster, so nothing is silently dropped.
        flat = [r for wave in ds.release_waves() for r in wave]
        assert len(flat) == len(set(flat)), "a repo appears in two waves"
        assert set(flat) == {x["repo"] for x in ds.libraries()}

    def test_roots_wave_holds_the_cornerstone_and_corpus(self) -> None:
        wave0 = ds.release_waves()[0]
        assert "mgf-common" in wave0
        assert "mgf-standard" in wave0
