"""mindbodypublicapi.

This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ).
"""

# ruff: noqa: E501
import os
import warnings
from enum import Enum

from apimatic_core.http.configurations.http_client_configuration import (
    HttpClientConfiguration,
)
from apimatic_requests_client_adapter.requests_client import (
    RequestsClient,
)
from dotenv import load_dotenv

from mindbodypublicapi.http.proxy_settings import (
    ProxySettings,
)


class Environment(Enum):
    """An enum for SDK environments."""

    PRODUCTION = 0

    @classmethod
    def from_value(cls, value, default=None):
        """Convert a value (string or int) to an Environment enum member.

        Args:
            value (Union[str, int]): The value to convert.
            default (Environment): The fallback enum member if conversion fails.

        Returns:
            Environment: Matching enum member or fallback if invalid.

        """
        if value is None:
            return default

        # Try to match directly by enum member
        if isinstance(value, cls):
            return value

        # Handle integer or string conversion
        for member in cls:
            if (str(member.value).lower() == str(value).lower()
                or member.name.lower() == str(value).lower()):
                return member

        # Fallback to provided default
        return default


class Server(Enum):
    """An enum for API servers."""

    DEFAULT = 0

    @classmethod
    def from_value(cls, value, default=None):
        """Convert a value (string or int) to a Server enum member.

        Args:
            value (Union[str, int]): The value to convert.
            default (Server): The fallback enum member if conversion fails.

        Returns:
            Server: Matching enum member or fallback if invalid.

        """
        if value is None:
            return default

        # Try to match directly by enum member
        if isinstance(value, cls):
            return value

        # Handle integer or string conversion
        for member in cls:
            if (str(member.value).lower() == str(value).lower()
                or member.name.lower() == str(value).lower()):
                return member

        # Fallback to provided default
        return default


class Configuration(HttpClientConfiguration):
    """A class used for configuring the SDK by a user."""

    @property
    def environment(self):
        """Return current environment."""
        return self._environment

    @property
    def api_key(self):
        """Return ApiKey from CustomHeaderAuthenticationCredentials."""
        return self._custom_header_authentication_credentials.api_key

    @property
    def custom_header_authentication_credentials(self):
        """Return CustomHeaderAuthenticationCredentials."""
        return self._custom_header_authentication_credentials

    def __init__(self, http_client_instance=None,
                 override_http_client_configuration=False, http_call_back=None,
                 timeout=60, max_retries=0, backoff_factor=2, retry_statuses=None,
                 retry_methods=None, proxy_settings=None,
                 environment=Environment.PRODUCTION, api_key=None,
                 custom_header_authentication_credentials=None):
        """Initialize Configuration object."""
        if retry_methods is None:
            retry_methods = ["GET", "PUT"]

        if retry_statuses is None:
            retry_statuses = [408, 413, 429, 500, 502, 503, 504, 521,
                522, 524]

        super().__init__(
            http_client_instance=http_client_instance,
            override_http_client_configuration=override_http_client_configuration,
            http_call_back=http_call_back, timeout=timeout,
            max_retries=max_retries, backoff_factor=backoff_factor,
            retry_statuses=retry_statuses, retry_methods=retry_methods,
            proxy_settings=proxy_settings,
        )

        # Current API environment
        self._environment = environment

        self._custom_header_authentication_credentials =\
            self.create_auth_credentials_object(
                api_key, custom_header_authentication_credentials)

        # The Http Client to use for making requests.
        self.set_http_client(self.create_http_client())

    def clone_with(self, http_client_instance=None,
                   override_http_client_configuration=None, http_call_back=None,
                   timeout=None, max_retries=None, backoff_factor=None,
                   retry_statuses=None, retry_methods=None, proxy_settings=None,
                   environment=None, api_key=None,
                   custom_header_authentication_credentials=None):
        """Clone configuration with overrides."""
        http_client_instance = http_client_instance or self.http_client_instance
        override_http_client_configuration =\
            (override_http_client_configuration
            or self.override_http_client_configuration)
        http_call_back = http_call_back or self.http_callback
        timeout = timeout or self.timeout
        max_retries = max_retries or self.max_retries
        backoff_factor = backoff_factor or self.backoff_factor
        retry_statuses = retry_statuses or self.retry_statuses
        retry_methods = retry_methods or self.retry_methods
        proxy_settings = proxy_settings or self.proxy_settings
        environment = environment or self.environment
        custom_header_authentication_credentials = self.create_auth_credentials_object(
            api_key,
            custom_header_authentication_credentials
            or self.custom_header_authentication_credentials,
            stack_level=3)
        return Configuration(
            http_client_instance=http_client_instance,
            override_http_client_configuration=override_http_client_configuration,
            http_call_back=http_call_back, timeout=timeout, max_retries=max_retries,
            backoff_factor=backoff_factor, retry_statuses=retry_statuses,
            retry_methods=retry_methods, proxy_settings=proxy_settings,
            environment=environment,
            custom_header_authentication_credentials=custom_header_authentication_credentials,
        )

    def create_http_client(self):
        """Create the HTTP client instance."""
        return RequestsClient(
            timeout=self.timeout, max_retries=self.max_retries,
            backoff_factor=self.backoff_factor, retry_statuses=self.retry_statuses,
            retry_methods=self.retry_methods,
            http_client_instance=self.http_client_instance,
            override_http_client_configuration=self.override_http_client_configuration,
            response_factory=self.http_response_factory,
            proxies=self.proxy_settings.to_proxies() if self.proxy_settings else None,
        )

    # All the environments the SDK can run in
    environments = {
        Environment.PRODUCTION: {
            Server.DEFAULT: "https://api.mindbodyonline.com",
        },
    }

    def get_base_uri(self, server=Server.DEFAULT):
        """Generate the appropriate base URI for the environment and the server.

        Args:
            server (Configuration.Server): The server enum for which the base
            URI is required.

        Returns:
            String: The base URI.

        """
        return self.environments[self.environment][server]

    @staticmethod
    def create_auth_credentials_object(api_key,
                                       custom_header_authentication_credentials,
                                       stack_level=4):
        """Create auth credentials object."""
        if api_key is None:
            return custom_header_authentication_credentials

        warnings.warn(message=("The 'api_key' params are deprecated. Use 'custom_head"
                               "er_authentication_credentials' param instead."),
                      category=DeprecationWarning,
                      stacklevel=stack_level)

        if custom_header_authentication_credentials is not None:
            return custom_header_authentication_credentials.clone_with(api_key)

        from mindbodypublicapi.http.auth.custom_header_authentication import (
            CustomHeaderAuthenticationCredentials,
        )
        return CustomHeaderAuthenticationCredentials(api_key)

    @classmethod
    def from_environment(cls, dotenv_path=None, **overrides):
        """Create Configuration object from .env and environment variables.

        Args:
            dotenv_path (str, optional): Path to the .env file to load.
             If None, the default .env file is used.
            **overrides: Optional values overriding setting from environment variables.

        Returns:
            Configuration: A configuration object populated with the resolved values.

        """
        # load .env automatically
        load_dotenv(dotenv_path or None, override=True)

        override_http_client_configuration = os.getenv(
            "OVERRIDE_HTTP_CLIENT_CONFIGURATION", "false").lower() == "true"
        timeout = int(os.getenv("TIMEOUT", "60"))
        max_retries = int(os.getenv("MAX_RETRIES", "0"))
        backoff_factor = float(os.getenv("BACKOFF_FACTOR", "2"))
        statuses = os.getenv("RETRY_STATUSES", None)
        retry_statuses = [int(v.strip()) for v in statuses.split(",")
                          if v.strip().isdigit()] if statuses else None
        methods = os.getenv("RETRY_METHODS", None)
        retry_methods = [v.strip() for v in methods.split(",") if v.strip()]\
            if methods else None
        environment = Environment.from_value(
            os.getenv("ENVIRONMENT"), Environment.PRODUCTION)

        from mindbodypublicapi.http.auth.custom_header_authentication import (
            CustomHeaderAuthenticationCredentials,
        )

        # Preparing default configuration
        default_config = cls(
            override_http_client_configuration=override_http_client_configuration,
            timeout=timeout,
            max_retries=max_retries,
            backoff_factor=backoff_factor,
            retry_statuses=retry_statuses,
            retry_methods=retry_methods,
            environment=environment,
            proxy_settings=ProxySettings.from_environment(),
            custom_header_authentication_credentials=CustomHeaderAuthenticationCredentials.from_environment(),
        )

        return default_config.clone_with(**overrides)
