"""``ALL_MANAGED`` resolution — the fleet of repos a fleet-wide surface covers.

The set of managed repos is the union of the two library registries
(``MGF_LIBRARIES.json`` ``libraries[].repo`` + ``SOOTH_LIBRARIES.json``
``repos[].name``) and the Woodpecker activated-repos list (SPEC §3). Reading the
committed registries is what lets C5 know a *newly activated* repo must carry the
fleet deploy key even before a human updates a doc.
"""

from __future__ import annotations

import json
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from collections.abc import Iterable
    from pathlib import Path


def _names_from_libraries(path: Path) -> set[str]:
    if not path.is_file():
        return set()
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return set()
    out: set[str] = set()
    # MGF shape: {"libraries": [{"repo": ...}]}
    for lib in data.get("libraries", []) or []:
        name = lib.get("repo") or lib.get("name") or lib.get("slug")
        if name:
            out.add(str(name))
    # Sooth shape: {"repos": [{"name": ..., "slug": ...}]}
    for repo in data.get("repos", []) or []:
        if isinstance(repo, str):
            out.add(repo)
        else:
            name = repo.get("name") or repo.get("slug") or repo.get("repo")
            if name:
                out.add(str(name))
    return out


def resolve_all_managed(
    *,
    fed_root: Path,
    activated_repos: Iterable[str] = (),
) -> set[str]:
    """Every managed repo name: both library registries plus Woodpecker-activated."""
    managed: set[str] = set()
    managed |= _names_from_libraries(fed_root / "mgf-standard" / "MGF_LIBRARIES.json")
    managed |= _names_from_libraries(fed_root / "sooth-standard" / "SOOTH_LIBRARIES.json")
    managed |= {str(r) for r in activated_repos}
    return managed
