"""
Relation registry — declarative entity relationship definitions.

Relations are defined as s-expressions using ``defrelation`` and stored
in a global registry.  All services load the same definitions at startup
via ``load_relation_registry()``.
"""

from __future__ import annotations

from shared.sx.types import RelationDef


# ---------------------------------------------------------------------------
# Registry
# ---------------------------------------------------------------------------

_RELATION_REGISTRY: dict[str, RelationDef] = {}


def register_relation(defn: RelationDef) -> None:
    """Add a RelationDef to the global registry."""
    _RELATION_REGISTRY[defn.name] = defn


def get_relation(name: str) -> RelationDef | None:
    """Look up a relation by name (e.g. ``"page->market"``)."""
    return _RELATION_REGISTRY.get(name)


def relations_from(entity_type: str) -> list[RelationDef]:
    """All relations where *entity_type* is the ``from`` side."""
    return [d for d in _RELATION_REGISTRY.values() if d.from_type == entity_type]


def relations_to(entity_type: str) -> list[RelationDef]:
    """All relations where *entity_type* is the ``to`` side."""
    return [d for d in _RELATION_REGISTRY.values() if d.to_type == entity_type]


def all_relations() -> list[RelationDef]:
    """Return all registered relations."""
    return list(_RELATION_REGISTRY.values())


def clear_registry() -> None:
    """Clear all registered relations (for testing)."""
    _RELATION_REGISTRY.clear()


# ---------------------------------------------------------------------------
# Built-in relation definitions (s-expression source)
# ---------------------------------------------------------------------------

_BUILTIN_RELATIONS = '''
(begin

  (defrelation :page->market
    :from "page"
    :to "market"
    :cardinality :one-to-many
    :inverse :market->page
    :nav :submenu
    :nav-icon "fa fa-shopping-bag"
    :nav-label "markets")

  (defrelation :page->calendar
    :from "page"
    :to "calendar"
    :cardinality :one-to-many
    :inverse :calendar->page
    :nav :submenu
    :nav-icon "fa fa-calendar"
    :nav-label "calendars")

  (defrelation :post->calendar_entry
    :from "post"
    :to "calendar_entry"
    :cardinality :many-to-many
    :inverse :calendar_entry->post
    :nav :inline
    :nav-icon "fa fa-file-alt"
    :nav-label "events")

  (defrelation :page->menu_node
    :from "page"
    :to "menu_node"
    :cardinality :one-to-one
    :nav :hidden)

)
'''


def load_relation_registry() -> None:
    """Parse built-in defrelation s-expressions and populate the registry."""
    from shared.sx.evaluator import evaluate
    from shared.sx.parser import parse

    tree = parse(_BUILTIN_RELATIONS)
    evaluate(tree)
