"""Tarot number namespace - fluent query interface for numerology."""

from typing import TYPE_CHECKING

from utils.query import CollectionAccessor

if TYPE_CHECKING:
    from tarot.card.data import CardDataLoader


def calculate_digital_root(value: int) -> int:
    """
    Calculate the digital root of a number by repeatedly summing its digits.

    Digital root reduces any number to a single digit (1-9) by repeatedly
    summing its digits until a single digit remains.
    """
    if value < 1:
        raise ValueError(f"Value must be positive, got {value}")

    while value >= 10:
        value = sum(int(digit) for digit in str(value))

    return value


class _Number:
    """Fluent query accessor for numerology and number correspondences."""

    def __init__(self) -> None:
        self._initialized: bool = False
        self._loader: "CardDataLoader | None" = None
        self.number = CollectionAccessor(self._get_numbers)
        self.color = CollectionAccessor(self._get_colors)
        self.cipher = CollectionAccessor(self._get_ciphers)

    def _ensure_initialized(self) -> None:
        """Lazy-load data from CardDataLoader on first access."""
        if self._initialized:
            return

        from tarot.card.data import CardDataLoader

        self._loader = CardDataLoader()
        self._initialized = True

    def _require_loader(self) -> "CardDataLoader":
        self._ensure_initialized()
        assert self._loader is not None, "Loader not initialized"
        return self._loader

    def _get_numbers(self):
        loader = self._require_loader()
        return loader.number().copy()

    def _get_colors(self):
        loader = self._require_loader()
        return loader.color().copy()

    def _get_ciphers(self):
        loader = self._require_loader()
        return loader._ciphers.copy()

    def digital_root(self, value: int) -> int:
        """Get the digital root of a value."""
        return calculate_digital_root(value)

    def __str__(self) -> str:
        """Return a nice summary of the number accessor."""
        return (
            "Number Namespace - Numerology and Number Correspondences\n\n"
            "Access methods:\n"
            "  number.number(n)          - Get number 1-9 with correspondences\n"
            "  number.color()            - Get color correspondences\n"
            "  number.cipher()           - Get cipher systems\n"
            "  number.digital_root(n)    - Calculate digital root of any number"
        )

    def __repr__(self) -> str:
        """Return a nice representation of the number accessor."""
        return self.__str__()


# Create singleton instance
number = _Number()
