import os

from .exceptions import (
    MissingEnvironmentVariableError,
    InvalidEnvironmentVariableError,
)
from .casting import cast_bool


_REQUIRED_VARS = set()
_NO_DEFAULT = object()


def require(*names: str) -> None:
    """
    Register required environment variables.
    """
    for name in names:
        _REQUIRED_VARS.add(name)


def validate() -> None:
    """
    Validate that all required environment variables are present.
    """
    missing = [name for name in _REQUIRED_VARS if name not in os.environ]

    if missing:
        message = "Missing required environment variables:\n"
        for name in missing:
            message += f"- {name}\n"

        raise MissingEnvironmentVariableError(message)


def env(name: str, cast=None, default=_NO_DEFAULT):
    """
    Retrieve an environment variable safely with optional casting.
    """
    if name not in os.environ:
        if default is not _NO_DEFAULT:
            return default

        raise MissingEnvironmentVariableError(f"{name} is not set")

    value = os.environ[name]

    if cast:
        try:
            if cast is bool:
                return cast_bool(value)
            return cast(value)
        except Exception:
            raise InvalidEnvironmentVariableError(
                f"Invalid value for {name}: {value}"
            )

    return value