"""`SettingDefinition` in-code registry — typed defaults + i18n labels."""

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass
from typing import Any


class SettingsError(Exception):
    """Raised for registry misuse."""


@dataclass(frozen=True)
class SettingDefinition:
    key: str
    type: str  # "string" | "int" | "bool" | "json"
    default: Any
    label_key: str
    description_key: str = ""
    scopes: tuple[str, ...] = ("system", "tenant", "org", "module", "user")
    validator: Callable[[Any], Any] | None = None

    def coerce(self, value: Any) -> Any:
        if self.validator is not None:
            return self.validator(value)
        return value


_REGISTRY: dict[str, SettingDefinition] = {}


def register_setting(definition: SettingDefinition) -> SettingDefinition:
    if "." not in definition.key:
        raise SettingsError(f"setting key must be dotted, got {definition.key!r}")
    existing = _REGISTRY.get(definition.key)
    if existing and existing != definition:
        raise SettingsError(f"setting {definition.key!r} already registered with different spec")
    _REGISTRY[definition.key] = definition
    return definition


def get_definition(key: str) -> SettingDefinition:
    try:
        return _REGISTRY[key]
    except KeyError as exc:
        raise SettingsError(f"unknown setting {key!r}") from exc


def registered_settings() -> dict[str, SettingDefinition]:
    return dict(_REGISTRY)


def reset_registry_for_tests() -> None:
    _REGISTRY.clear()
