"""
Registry mapping rdf_type IRIs to Model classes.

ModelRegistry is auto-populated when Model subclasses are defined.
Abstract models (Meta.abstract = True) are excluded from registration.
"""

from typing import TYPE_CHECKING, ClassVar

if TYPE_CHECKING:
    from .model.base import Model


class ModelRegistry:
    """Tracks registered Model classes and their rdf_type mappings.

    Populated automatically when Model subclasses are defined (via the model
    metaclass). Abstract models are excluded.

    Example:
        >>> ModelRegistry.get_model_for_type("http://schema.org/Person")
        <class 'myapp.models.Person'>
    """

    # TODO(#89): _type_to_model is a plain dict with no locking. If register()
    # and get_subclass_models() are called concurrently (e.g. from multiple
    # threads in a web application), iteration may be inconsistent. Consider
    # adding a threading.RLock mirroring the SchemaRegistry pattern.
    _type_to_model: ClassVar[dict[str, "type[Model]"]] = {}

    @classmethod
    def register(cls, model: "type[Model]") -> None:
        """Register a model class by its rdf_type default value.

        Args:
            model: Model class to register
        """
        rdf_type_val: str | None = model.rdf_type_iri()
        if rdf_type_val:
            cls._type_to_model[rdf_type_val] = model

    @classmethod
    def unregister(cls, model: "type[Model]") -> None:
        """Unregister a model class (used in tests).

        Args:
            model: Model class to unregister
        """
        rdf_type_val: str | None = model.rdf_type_iri()
        if rdf_type_val and rdf_type_val in cls._type_to_model:
            del cls._type_to_model[rdf_type_val]

    @classmethod
    def get_model_for_type(cls, rdf_type: str) -> "type[Model] | None":
        """Look up a model class by its rdf_type IRI.

        Args:
            rdf_type: The rdf_type IRI to look up

        Returns:
            Model class or None if not registered
        """
        return cls._type_to_model.get(rdf_type)

    @classmethod
    def get_subclass_models(cls, base_model: "type[Model]") -> "list[type[Model]]":
        """Get all registered non-abstract subclasses of base_model.

        Args:
            base_model: The base model class

        Returns:
            List of non-abstract registered subclasses (excluding base_model itself)
        """
        return [
            m
            for m in cls._type_to_model.values()
            if issubclass(m, base_model)
            and m is not base_model
            and not getattr(m, "_abstract", False)
        ]

    @classmethod
    def clear(cls) -> None:
        """Clear all registrations (for testing)."""
        cls._type_to_model.clear()


__all__ = ["ModelRegistry"]
