"""
Core module: orchestrates all checkers.
"""

from .checkers import numeric, multilingual, roman, math_eval, base_convert, cultural, creative


_CHECKERS = [
    numeric,
    multilingual,
    roman,
    math_eval,
    base_convert,
    cultural,
    creative,
]


def is_42(value) -> bool:
    """Check if value represents the number 42 in any conceivable way.

    Supports:
        - Numeric types: int, float, complex, Decimal, Fraction
        - Multilingual words: 30+ languages (e.g. 四十二, forty-two, quarante-deux)
        - Roman numerals: XLII, Unicode Roman characters
        - Math expressions: "(6+1)*6" or "2^5 + 10" etc. (safe sandbox)
        - Base conversions: 0b101010, 0x2A, 0o52, 4.2e1, ４２, ④②
        - Cultural references: "The Answer to Life, the Universe, and Everything"
        - Creative: 42 identical characters, Morse code, tally marks

    Args:
        value: Any value to check.

    Returns:
        True if the value represents 42, False otherwise.

    Examples:
        >>> is_42(42)
        True
        >>> is_42("四十二")
        True
        >>> is_42("XLII")
        True
        >>> is_42("6 * 7")
        True
        >>> is_42("!" * 42)
        True
        >>> is_42(43)
        False
    """
    return why_42(value) is not None


def why_42(value) -> str | None:
    """Explain *why* the value is 42, or return None if it isn't.

    Returns a human-readable explanation string if the value represents 42,
    or None if it doesn't.

    Args:
        value: Any value to check.

    Returns:
        A string explanation if 42, None otherwise.

    Examples:
        >>> why_42("XLII")
        'Roman numeral: XLII = XLII = 42'
        >>> why_42(43)

    """
    # Try plain string "42" first (before math checker grabs it)
    if isinstance(value, str) and value.strip() == "42":
        return 'string literal: "42"'

    for checker in _CHECKERS:
        try:
            result = checker.check(value)
            if result is not None:
                return result
        except Exception:
            continue

    return None
