"""Discover the federation: which projects carry a ``fed-resources/generated/`` tree.

Read-only. A project participates iff it has a
``fed-resources/generated/manifest.json`` on disk; each discovered project is
wrapped in a :class:`~mgf.fedres.DiskProvider` so the rest of the web reads it
through the spine's seam. Roots come from ``MGF_FED_WEB_ROOTS`` (colon-separated)
or default to the sibling-projects directory this package lives in (the
``PycharmProjects`` workspace). The web never authors anything here.
"""

from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path

from mgf.fedres import DiskProvider

#: The sibling-projects workspace (``…/PycharmProjects``) — five parents up from
#: this file: discovery.py → fed_web → mgf → src → <project-root> → workspace.
_DEFAULT_ROOT = Path(__file__).resolve().parents[4]

#: Env var holding a ``:``-separated list of roots to scan for participants.
ROOTS_ENV = "MGF_FED_WEB_ROOTS"


@dataclass(frozen=True)
class DiscoveredProject:
    """A participating project: its URL slug, its root, and its read provider."""

    slug: str
    root: Path
    provider: DiskProvider


def discover_roots() -> list[Path]:
    """The directories to scan for participants (env override, else the default)."""
    raw = os.environ.get(ROOTS_ENV, "").strip()
    if raw:
        return [Path(p).expanduser() for p in raw.split(os.pathsep) if p.strip()]
    return [_DEFAULT_ROOT]


def _is_participant(child: Path) -> bool:
    return (child / "fed-resources" / "generated" / "manifest.json").is_file()


def discover_projects(roots: list[Path] | None = None) -> list[DiscoveredProject]:
    """Find every participating project under ``roots``, sorted by slug, deduped.

    The slug is the project directory name (what a URL like ``/p/<slug>`` carries);
    discovery only includes a directory that actually has a generated manifest, so
    the federation set is honest — an un-wired project is simply absent (and the web
    renders ``UNKNOWN`` when one is requested by slug).
    """
    seen: dict[str, DiscoveredProject] = {}
    for root in roots if roots is not None else discover_roots():
        if not root.is_dir():
            continue
        for child in sorted(root.iterdir()):
            if not child.is_dir() or not _is_participant(child):
                continue
            slug = child.name
            if slug not in seen:
                seen[slug] = DiscoveredProject(slug, child, DiskProvider(child))
    return [seen[slug] for slug in sorted(seen)]


def find_project(slug: str, roots: list[Path] | None = None) -> DiscoveredProject | None:
    """Return the participant with this slug, or ``None`` (caller renders UNKNOWN)."""
    return next((p for p in discover_projects(roots) if p.slug == slug), None)
