"""This module contains generic Pyramid integration with Authlib.

It could be sent to Authlib upstream.
"""

from pyramid.httpexceptions import HTTPFound
from pyramid.threadlocal import get_current_registry


class TokenUpdate:
    """Token update event."""

    def __init__(self, name, token, refresh_token, access_token):
        """Initialize the TokenUpdate event.

        Args:
            name (str): The name of the authlib client.
            token (dict): The set of tokens the provider sent us.
            refresh_token (str): The refresh token.
            access_token (str): The access token.
        """
        self.name = name
        self.token = token
        self.refresh_token = refresh_token
        self.access_token = access_token


class PyramidIntegrationMixin:
    """Pyramid-specific framework integration."""

    def update_token(self, token, refresh_token=None, access_token=None):
        """Send an event notification on token update with Pyramid's facility."""
        event = TokenUpdate(self.name, token, refresh_token, access_token)
        registry = get_current_registry()
        registry.notify(event)

    @staticmethod
    def load_config(oauth, name, params):
        """Load the config from Pyramid's config and the json file generated by oidc-register.

        :param oauth: The OAuth app (unused).
        :param name: The provider name.
        :param params: Additional parameters (unused).

        :return: Dict configuration used to create the OAuth client.
        """
        registry = get_current_registry()
        supported_keys = (
            "client_id", "client_secret", "server_metadata_url", "userinfo_endpoint",
            "authorize_url", "access_token_url",
        )
        config = {}
        for key in supported_keys:
            try:
                config[key] = registry.settings[f"oidc.{name}.{key}"]
            except KeyError:
                continue
        return config


class PyramidAppMixin:
    """Generic methods for a Pyramid Authlib app."""

    def authorize_redirect(self, request, redirect_uri=None, **kwargs):
        """Create a HTTP Redirect for Authorization Endpoint.

        :param request: HTTP request instance from Pyramid view.
        :param redirect_uri: Callback or redirect URI for authorization.
        :param kwargs: Extra parameters to include.
        :return: A HTTP redirect response.
        """
        rv = self.create_authorization_url(redirect_uri, **kwargs)
        self.save_authorize_data(request, redirect_uri=redirect_uri, **rv)
        return HTTPFound(location=rv['url'])
