import logging

from .exceptions import RegistryError

logger = logging.getLogger("django_devicehub")


class DeviceTypeRegistry:
    """Global registry of DeviceType classes.

    Device types are auto-registered when their class is created (via metaclass).
    Models are registered when create_models() is called.
    """

    def __init__(self):
        self._types = {}  # normalized_name -> DeviceType class
        self._models = {}  # normalized_name -> (DeviceModel, ReadingModel, MessageModel)

    def register(self, device_type_cls):
        """Register a DeviceType class."""
        name = self._normalize_name(device_type_cls.__name__)
        if name in self._types:
            existing = self._types[name]
            if existing is not device_type_cls:
                raise RegistryError(
                    f"DeviceType name conflict: '{device_type_cls.__name__}' — "
                    f"already registered by {existing.__module__}.{existing.__qualname__}"
                )
            return  # Same class, idempotent
        self._types[name] = device_type_cls
        logger.debug(
            "Registered DeviceType: %s (%s)",
            device_type_cls.__name__,
            device_type_cls.__module__,
        )

    def register_models(
        self, device_type_cls, device_model, reading_model, message_model
    ):
        """Register the generated models for a DeviceType."""
        name = self._normalize_name(device_type_cls.__name__)
        self._models[name] = (device_model, reading_model, message_model)

    def get(self, name):
        """Look up a DeviceType by name (case-insensitive)."""
        return self._types.get(self._normalize_name(name))

    def get_models(self, name):
        """Look up the model tuple for a DeviceType by name."""
        return self._models.get(self._normalize_name(name))

    def get_by_device_model(self, model):
        """Find the DeviceType that owns a given device model class."""
        for name, (dev_model, _, _) in self._models.items():
            if dev_model is model:
                return self._types.get(name)
        return None

    def all(self):
        """Return all registered DeviceType classes."""
        return list(self._types.values())

    def all_with_models(self):
        """Return list of (DeviceType, DeviceModel, ReadingModel, MessageModel)."""
        result = []
        for name, dt_cls in self._types.items():
            models = self._models.get(name)
            if models:
                result.append((dt_cls, *models))
        return result

    def __len__(self):
        return len(self._types)

    def __contains__(self, name):
        return self._normalize_name(name) in self._types

    def _normalize_name(self, name):
        return name.lower().replace("_", "")

    def clear(self):
        """Clear registry (for testing)."""
        self._types.clear()
        self._models.clear()


registry = DeviceTypeRegistry()
