"""application_credentials platform for Withings."""

from typing import Any, override

from aiowithings import AUTHORIZATION_URL, TOKEN_URL

from homeassistant.components.application_credentials import (
    AuthImplementation,
    AuthorizationServer,
    ClientCredential,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_entry_oauth2_flow

from .const import DOMAIN


async def async_get_auth_implementation(
    hass: HomeAssistant, auth_domain: str, credential: ClientCredential
) -> config_entry_oauth2_flow.AbstractOAuth2Implementation:
    """Return auth implementation."""
    return WithingsLocalOAuth2Implementation(
        hass,
        DOMAIN,
        credential,
        authorization_server=AuthorizationServer(
            authorize_url=AUTHORIZATION_URL,
            token_url=TOKEN_URL,
        ),
    )


class WithingsLocalOAuth2Implementation(AuthImplementation):
    """Oauth2 implementation that only uses the external url."""

    @override
    async def _token_request(self, data: dict) -> dict:
        """Make a token request and adapt Withings API reply."""
        new_token = await super()._token_request(data)
        # Withings API returns habitual token data under json key "body":
        # {
        #     "status": [{integer} Withings API response status],
        #     "body": {
        #         "access_token": [{string} Your new access_token],
        #         "expires_in": [{integer} Access token expiry delay in seconds],
        #         "token_type": [{string] HTTP Authorization Header format: Bearer],
        #         "scope": [{string} Scopes the user accepted],
        #         "refresh_token": [{string} Your new refresh_token],
        #         "userid": [{string} The Withings ID of the user]
        #     }
        # }
        # so we copy that to token root.
        if body := new_token.pop("body", None):
            new_token.update(body)
        return new_token

    @override
    async def async_resolve_external_data(self, external_data: Any) -> dict:
        """Resolve the authorization code to tokens."""
        return await self._token_request(
            {
                "action": "requesttoken",
                "grant_type": "authorization_code",
                "code": external_data["code"],
                "redirect_uri": external_data["state"]["redirect_uri"],
            }
        )

    @override
    async def _async_refresh_token(self, token: dict) -> dict:
        """Refresh tokens."""
        new_token = await self._token_request(
            {
                "action": "requesttoken",
                "grant_type": "refresh_token",
                "client_id": self.client_id,
                "refresh_token": token["refresh_token"],
            }
        )
        return {**token, **new_token}


async def async_get_description_placeholders(hass: HomeAssistant) -> dict[str, str]:
    """Return description placeholders for the credentials dialog."""
    return {
        "developer_dashboard_url": "https://developer.withings.com/dashboard/welcome",
        "redirect_url": "https://my.home-assistant.io/redirect/oauth",
    }
