from __future__ import annotations

from typing import TypeVar

from django.apps import apps

from allauth.core.internal.cryptokit import UserCodeFormat


_T = TypeVar("_T")


class AppSettings:
    def __init__(self, prefix: str) -> None:
        self.prefix = prefix

    def _setting(self, name: str, dflt: _T) -> _T:
        from allauth.utils import get_setting

        return get_setting(self.prefix + name, dflt)

    @property
    def SITES_ENABLED(self) -> bool:
        return apps.is_installed("django.contrib.sites")

    @property
    def SOCIALACCOUNT_ENABLED(self) -> bool:
        return apps.is_installed("allauth.socialaccount")

    @property
    def SOCIALACCOUNT_ONLY(self) -> bool:
        from allauth.utils import get_setting

        return get_setting("SOCIALACCOUNT_ONLY", False)

    @property
    def MFA_ENABLED(self) -> bool:
        return apps.is_installed("allauth.mfa")

    @property
    def USERSESSIONS_ENABLED(self) -> bool:
        return apps.is_installed("allauth.usersessions")

    @property
    def HEADLESS_ENABLED(self) -> bool:
        return apps.is_installed("allauth.headless")

    @property
    def HEADLESS_ONLY(self) -> bool:
        from allauth.utils import get_setting

        return get_setting("HEADLESS_ONLY", False)

    @property
    def DEFAULT_AUTO_FIELD(self):
        return self._setting("DEFAULT_AUTO_FIELD", None)

    @property
    def TRUSTED_PROXY_COUNT(self) -> int:
        """
        As the ``X-Forwarded-For`` header can be spoofed, you need to
        configure the number of proxies that are under your control and hence,
        can be trusted. The default is 0, meaning, no proxies are trusted.  As a
        result, the ``X-Forwarded-For`` header will be disregarded by default.
        """
        return self._setting("TRUSTED_PROXY_COUNT", 0)

    @property
    def TRUSTED_CLIENT_IP_HEADER(self) -> str | None:
        """
        If your service is running behind a trusted proxy that sets a custom header
        containing the client IP address, specify that header name here. The client
        IP will be extracted from this header instead of ``X-Forwarded-For``.
        Examples: ``"CF-Connecting-IP"`` (Cloudflare), ``"X-Real-IP"`` (nginx).
        """
        return self._setting("TRUSTED_CLIENT_IP_HEADER", None)

    @property
    def RATE_LIMIT_IPV6_PREFIX(self) -> int:
        """
        For rate limiting purposes, IPv6 addresses are truncated to their network
        prefix to prevent attackers from bypassing rate limits by rotating through
        addresses within their allocated prefix. This setting controls the prefix
        length. The default is 64, which corresponds to a standard /64 subnet.
        """
        return self._setting("RATE_LIMIT_IPV6_PREFIX", 64)

    @property
    def USER_CODE_FORMAT(self) -> UserCodeFormat:
        """
        Controls the format of user-facing verification codes (e.g. email
        verification, phone verification, login codes).
        """
        return self._setting("USER_CODE_FORMAT", UserCodeFormat())


_app_settings = AppSettings("ALLAUTH_")


def __getattr__(name):
    # See https://peps.python.org/pep-0562/
    return getattr(_app_settings, name)
