
"""
pay_quicker_sdk

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

import logging
import os

from apimatic_core.logger.configuration.api_logging_configuration import (
    ApiLoggingConfiguration,
    ApiRequestLoggingConfiguration,
    ApiResponseLoggingConfiguration,
)


class RequestLoggingConfiguration(ApiRequestLoggingConfiguration):
    """
    Configuration for controlling how API request details are logged.
    Provides options to include or exclude data such as headers, query
    parameters and request body to support flexible logging behavior.
    """

    def __init__(self, log_body=False, log_headers=False, headers_to_include=None,
                 headers_to_exclude=None, headers_to_unmask=None,
                 include_query_in_path=False):
        """
        Initialize the Request Logging Configuration.

        Args:
            log_body (bool): Controls the logging of the request body.
            log_headers (bool): Controls the logging of request headers.
            headers_to_include (List[str]): Includes only specified headers in
             the log output.
            headers_to_exclude (List[str]): Excludes specified headers from
             the log output.
            headers_to_unmask (List[str]): Logs specified headers without masking,
             revealing their actual values.
            include_query_in_path (bool): Determines whether to include query
             parameters in the logged request path.

        """
        super().__init__(
            log_body,
            log_headers,
            headers_to_include,
            headers_to_exclude,
            headers_to_unmask,
            include_query_in_path,
        )

    def clone_with(self, log_body=None, log_headers=None,
                   headers_to_include=None, headers_to_exclude=None,
                   headers_to_unmask=None, include_query_in_path=False):
        """
        Create a copy of this configuration with overridden attributes.

        Args:
            log_body (bool): Optional override for logging the body.
            log_headers (bool): Optional override for logging headers.
            headers_to_include (List[str]): Optional override for included headers.
            headers_to_exclude (List[str]): Optional override for excluded headers.
            headers_to_unmask (List[str]): Optional override for unmasked headers.
            include_query_in_path (bool): Optional override for including queries.

        Returns:
            RequestLoggingConfiguration: A new configuration instance.

        """
        log_body = log_body or self.log_body
        log_headers = log_headers or self.log_headers
        headers_to_include = headers_to_include or self.headers_to_include
        headers_to_exclude = headers_to_exclude or self.headers_to_exclude
        headers_to_unmask = headers_to_unmask or self.headers_to_unmask
        include_query_in_path = include_query_in_path or self.include_query_in_path

        return RequestLoggingConfiguration(
            log_body,
            log_headers,
            headers_to_include,
            headers_to_exclude,
            headers_to_unmask,
            include_query_in_path,
        )

    @classmethod
    def from_dict(cls, dictionary):
        """
        Create an instance of RequestLoggingConfiguration from a dictionary.

        Args:
            dictionary (dict): The input data to convert from.

        """
        if not dictionary:
            return cls()

        headers_to_include = dictionary.get("headers_to_include")
        headers_to_include = [
            v.strip() for v in headers_to_include.split(",") if v.strip()
        ] if headers_to_include else None

        headers_to_exclude = dictionary.get("headers_to_exclude")
        headers_to_exclude = [
            v.strip() for v in headers_to_exclude.split(",") if v.strip()
        ] if headers_to_exclude else None

        headers_to_unmask = dictionary.get("headers_to_unmask")
        headers_to_unmask = [
            v.strip() for v in headers_to_unmask.split(",") if v.strip()
        ] if headers_to_unmask else None

        return cls(
            log_body=dictionary.get("log_body", False),
            log_headers=dictionary.get("log_headers", False),
            headers_to_include=headers_to_include,
            headers_to_exclude=headers_to_exclude,
            headers_to_unmask=headers_to_unmask,
            include_query_in_path=dictionary.get("include_query_in_path", False),
        )

class ResponseLoggingConfiguration(ApiResponseLoggingConfiguration):
    """
    Configuration for controlling how API response details are logged.
    Supports selective logging of headers and body data while allowing
    masking of sensitive response information.
    """

    def __init__(self, log_body=False, log_headers=False, headers_to_include=None,
                 headers_to_exclude=None, headers_to_unmask=None):
        """
        Initialize the Response Logging Configuration.

        Args:
            log_body (bool): Controls the logging of the request body.
            log_headers (bool): Controls the logging of request headers.
            headers_to_include (List[str]): Includes only specified headers in the log
             output.
            headers_to_exclude (List[str]): Excludes specified headers from the log
             output.
            headers_to_unmask (List[str]): Logs specified headers without
             masking, revealing their actual values.

        """
        super().__init__(
            log_body,
            log_headers,
            headers_to_include,
            headers_to_exclude,
            headers_to_unmask,
        )

    def clone_with(self, log_body=None, log_headers=None,
                   headers_to_include=None, headers_to_exclude=None,
                   headers_to_unmask=None):
        """
        Create a copy of this configuration with overridden attributes.

        Args:
            log_body (bool): Optional override for logging the body.
            log_headers (bool): Optional override for logging headers.
            headers_to_include (List[str]): Optional override for included headers.
            headers_to_exclude (List[str]): Optional override for excluded headers.
            headers_to_unmask (List[str]): Optional override for unmasked headers.

        Returns:
            ResponseLoggingConfiguration: A new configuration instance.

        """
        log_body = log_body or self.log_body
        log_headers = log_headers or self.log_headers
        headers_to_include = headers_to_include or self.headers_to_include
        headers_to_exclude = headers_to_exclude or self.headers_to_exclude
        headers_to_unmask = headers_to_unmask or self.headers_to_unmask

        return ResponseLoggingConfiguration(
            log_body,
            log_headers,
            headers_to_include,
            headers_to_exclude,
            headers_to_unmask,
        )

    @classmethod
    def from_dict(cls, dictionary):
        """
        Create an instance of ResponseLoggingConfiguration from a dictionary.

        Args:
            dictionary (dict): The input data to convert from.

        """
        if not dictionary:
            return cls()

        headers_to_include = dictionary.get("headers_to_include")
        headers_to_include = [
            v.strip() for v in headers_to_include.split(",") if v.strip()
        ] if headers_to_include else None

        headers_to_exclude = dictionary.get("headers_to_exclude")
        headers_to_exclude = [
            v.strip() for v in headers_to_exclude.split(",") if v.strip()
        ] if headers_to_exclude else None

        headers_to_unmask = dictionary.get("headers_to_unmask")
        headers_to_unmask = [
            v.strip() for v in headers_to_unmask.split(",") if v.strip()
        ] if headers_to_unmask else None

        return cls(
            log_body=dictionary.get("log_body", False),
            log_headers=dictionary.get("log_headers", False),
            headers_to_include=headers_to_include,
            headers_to_exclude=headers_to_exclude,
            headers_to_unmask=headers_to_unmask,
        )

class LoggingConfiguration(ApiLoggingConfiguration):
    """
    High-level configuration for API logging behavior. Aggregates both
    request and response logging settings and applies shared options such
    as log level and header masking across log events.
    """

    def __init__(self, logger=None, log_level=None, mask_sensitive_headers=True,
                 request_logging_config=None, response_logging_config=None):
        """
        Initialize the Logging Configuration.

        Args:
            logger (Logger): The logging implementation to log with.
            log_level (LogLevel): The log level to apply to the log message.
            mask_sensitive_headers (bool): Flag to control masking of sensitive headers.
            request_logging_config (RequestLoggingConfiguration): The API request
             logging configuration.
            response_logging_config (ResponseLoggingConfiguration): The API response
             logging configuration.

        """
        request_logging_config = request_logging_config or RequestLoggingConfiguration()
        response_logging_config =\
            response_logging_config or ResponseLoggingConfiguration()
        super().__init__(
            logger,
            log_level,
            mask_sensitive_headers,
            request_logging_config,
            response_logging_config,
        )

    def clone_with(self, logger=None, log_level=None, mask_sensitive_headers=None,
                   request_logging_config=None, response_logging_config=None):
        """
        Create a copy of this configuration with overridden attributes.

        Args:
            logger (Logger): Optional override for the logging implementation.
            log_level (bool): Optional override for logging level.
            mask_sensitive_headers (bool): Optional override for masking headers.
            request_logging_config (RequestLoggingConfiguration): Optional
             override for request logging configuration.
            response_logging_config (ResponseLoggingConfiguration): Optional
             override for response logging configuration.

        Returns:
            LoggingConfiguration: A new configuration instance.

        """
        logger = logger or self.logger
        log_level = log_level or self.log_level
        mask_sensitive_headers = mask_sensitive_headers or self.mask_sensitive_headers
        request_logging_config = request_logging_config or self.request_logging_config
        response_logging_config =\
            response_logging_config or self.response_logging_config

        return LoggingConfiguration(
            logger,
            log_level,
            mask_sensitive_headers,
            request_logging_config,
            response_logging_config,
        )

    @classmethod
    def from_dict(cls, dictionary):
        """
        Create an instance of LoggingConfiguration from a dictionary.
        Supports nested request/response logging config dictionaries.

        Args:
            dictionary (dict): The input data to convert from.

        """
        if not dictionary:
            return None

        req_config_dict = dictionary.get("request_logging_config") or {}
        res_config_dict = dictionary.get("response_logging_config") or {}

        return cls(
            logger=dictionary.get("logger"),
            log_level=dictionary.get("log_level"),
            mask_sensitive_headers=dictionary.get("mask_sensitive_headers", True),
            request_logging_config=RequestLoggingConfiguration.from_dict(req_config_dict),
            response_logging_config=ResponseLoggingConfiguration.from_dict(res_config_dict),
        )

    @classmethod
    def from_environment(cls):
        """
        Create a LoggingConfiguration instance based on environment variables.
        Environment flags determine whether logging is enabled and how it is
        configured for requests and responses.
        """
        request_logging_env = {
            "log_body": os.getenv("REQUEST_LOG_BODY", None),
            "log_headers": os.getenv("REQUEST_LOG_HEADERS", None),
            "headers_to_include": os.getenv("REQUEST_HEADERS_TO_INCLUDE", None),
            "headers_to_exclude": os.getenv("REQUEST_HEADERS_TO_EXCLUDE", None),
            "headers_to_unmask": os.getenv("REQUEST_HEADERS_TO_UNMASK", None),
            "include_query_in_path": os.getenv("REQUEST_INCLUDE_QUERY_IN_PATH", None),
        }
        # Only include if at least one env var is set
        request_logging_config = (
                {k: (v.lower() == "true" if v and v.lower() in ["true", "false"] else v)
                 for k, v in request_logging_env.items() if v is not None}
                or None
        )

        # Collect environment variables for response logging
        response_logging_env = {
            "log_body": os.getenv("RESPONSE_LOG_BODY", None),
            "log_headers": os.getenv("RESPONSE_LOG_HEADERS", None),
            "headers_to_include": os.getenv("RESPONSE_HEADERS_TO_INCLUDE", None),
            "headers_to_exclude": os.getenv("RESPONSE_HEADERS_TO_EXCLUDE", None),
            "headers_to_unmask": os.getenv("RESPONSE_HEADERS_TO_UNMASK", None),
        }
        response_logging_config = (
                {k: (v.lower() == "true" if v and v.lower() in ["true", "false"] else v)
                 for k, v in response_logging_env.items() if v is not None}
                or None
        )

        # Determine if any logging-related env variable is set
        has_logging_env = any([
            os.getenv("LOG_LEVEL", None),
            os.getenv("MASK_SENSITIVE_HEADERS", None),
            request_logging_config,
            response_logging_config,
        ])

        log_level = cls._resolve_level(os.getenv("LOG_LEVEL", None))

        # Only instantiate LoggingConfiguration if something is configured
        return cls.from_dict({
            "log_level": log_level,
            "mask_sensitive_headers": os.getenv("MASK_SENSITIVE_HEADERS",
                                                "true").lower() == "true",
            "request_logging_config": request_logging_config,
            "response_logging_config": response_logging_config,
        }) if has_logging_env else None

    @staticmethod
    def _resolve_level(value):
        """
        Resolve a log level from a string or numeric representation.

        Args:
            value (str|int): The desired level or its textual name.

        Returns:
            int: The resolved Python logging level constant.

        """
        if value is None:
            return None

        possible_levels = {
            logging.CRITICAL,
            logging.ERROR,
            logging.WARNING,
            logging.INFO,
            logging.DEBUG,
            logging.NOTSET,
        }
        # handle numeric values (string or int)
        if value.isdigit():
            return int(value) if int(value) in possible_levels else logging.INFO
        # handle string log level names
        if isinstance(value, str):
            level = logging.getLevelName(value.upper())
            if isinstance(level, int):
                return level

        return logging.INFO
