"""The federation roster + release-wave order.

Source of truth is the ``mgf-standard`` registry (``MGF_LIBRARIES.json``), read from
the sibling repo on disk so v0 needs no install of ``mgf-standard``. The same data is
also resolvable at runtime via ``import mgf.standard`` once that becomes convenient.
"""

from __future__ import annotations

import json
import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any


def federation_root() -> Path:
    """The directory holding the sibling mgf-* repos.

    Resolution order: ``$MGF_ROOT`` → ``~/PycharmProjects`` → cwd.
    """
    env = os.environ.get("MGF_ROOT")
    if env:
        return Path(env).expanduser()
    default = Path.home() / "PycharmProjects"
    return default if default.is_dir() else Path.cwd()


def _registry_path(root: Path) -> Path:
    return root / "mgf-standard" / "MGF_LIBRARIES.json"


@dataclass(frozen=True, slots=True)
class Member:
    """One federation member as the registry sees it."""

    repo: str  # == published package name == Codeberg repo slug
    lang: str  # "python" | "zig" | "other"
    registry_version: str
    extras: tuple[str, ...] = ()
    deps: tuple[str, ...] = ()  # mgf-* deps only
    used_by: tuple[str, ...] = ()
    wave: int = -1
    root: Path = field(default_factory=federation_root)

    @property
    def repo_dir(self) -> Path:
        return self.root / self.repo

    @property
    def has_standards_extra(self) -> bool:
        return "standards" in self.extras


def load_registry(root: Path | None = None) -> dict[str, Any]:
    root = root or federation_root()
    path = _registry_path(root)
    if not path.is_file():
        raise FileNotFoundError(
            f"registry not found at {path} — is MGF_ROOT correct, and mgf-standard cloned there?"
        )
    data: dict[str, Any] = json.loads(path.read_text(encoding="utf-8"))
    return data


def members(root: Path | None = None) -> list[Member]:
    """Every federation member, each tagged with its release wave."""
    root = root or federation_root()
    data = load_registry(root)
    waves: list[list[str]] = list(data.get("release_waves", []))
    wave_of: dict[str, int] = {repo: i for i, w in enumerate(waves) for repo in w}
    out: list[Member] = []
    for lib in data.get("libraries", []):
        repo = str(lib["repo"])
        out.append(
            Member(
                repo=repo,
                lang=str(lib.get("lang", "other")),
                registry_version=str(lib.get("version", "?")),
                extras=tuple(lib.get("extras", []) or ()),
                deps=tuple((lib.get("deps", {}) or {}).keys()),
                used_by=tuple(lib.get("used_by", []) or ()),
                wave=wave_of.get(repo, -1),
                root=root,
            )
        )
    out.sort(key=lambda m: (m.wave if m.wave >= 0 else 99, m.repo))
    return out
