from __future__ import annotations

import pytest

from django_anyllm.permissions import PermissionDenied
from django_anyllm.registry import ModelNotRegistered, ModelRegistry

from .models import Author, Book


class TestModelRegistry:
    """Tests for the ModelRegistry."""

    def test_register_by_class(self):
        reg = ModelRegistry()
        reg.register(Author)
        assert reg.is_registered("tests", "author")

    def test_register_by_string(self):
        reg = ModelRegistry()
        reg.register("tests.Author")
        assert reg.is_registered("tests", "author")

    def test_unregister(self):
        reg = ModelRegistry()
        reg.register(Author)
        reg.unregister("tests", "author")
        assert not reg.is_registered("tests", "author")

    def test_get_model(self, registry):
        assert registry.get_model("tests", "author") is Author
        assert registry.get_model("tests", "book") is Book

    def test_get_model_not_registered(self):
        reg = ModelRegistry()
        with pytest.raises(ModelNotRegistered):
            reg.get_model("tests", "author")

    def test_default_permissions(self, registry):
        reg = registry.get_registration("tests", "author")
        assert reg.permissions == {"read", "create", "update", "delete"}

    def test_custom_permissions(self):
        reg = ModelRegistry()
        reg.register(Author, permissions={"read"})
        reg.check_permission("tests", "author", "read")
        with pytest.raises(PermissionDenied):
            reg.check_permission("tests", "author", "delete")

    def test_invalid_permissions(self):
        reg = ModelRegistry()
        with pytest.raises(ValueError):
            reg.register(Author, permissions={"read", "fly"})

    def test_list_models(self, registry):
        models = registry.list_models()
        assert len(models) == 2
        labels = {m["model_name"] for m in models}
        assert labels == {"author", "book"}

        author_meta = next(m for m in models if m["model_name"] == "author")
        assert author_meta["app_label"] == "tests"
        assert author_meta["verbose_name"] == "author"
        assert author_meta["docstring"] == "A writer of books."
