from typing import Any
from urllib.parse import urlencode

import httpx

from src.config import Settings


def build_login_redirect_url(
    *,
    settings: Settings,
    redirect_uri: str,
    state: str,
) -> str:
    query = urlencode(
        {
            "response_type": "code",
            "client_id": settings.authentik_client_id,
            "redirect_uri": redirect_uri,
            "scope": "openid profile email",
            "state": state,
        }
    )
    return f"{settings.resolved_authentik_authorize_url}?{query}"


async def exchange_code_for_tokens(
    *,
    settings: Settings,
    code: str,
    redirect_uri: str,
    client: httpx.AsyncClient,
) -> dict[str, str]:
    response = await client.post(
        settings.resolved_authentik_token_url,
        data={
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redirect_uri,
            "client_id": settings.authentik_client_id,
            "client_secret": settings.authentik_client_secret,
        },
    )
    response.raise_for_status()
    payload = response.json()
    return {
        "access_token": payload["access_token"],
        "refresh_token": payload.get("refresh_token"),
    }


async def fetch_user_info(
    *,
    settings: Settings,
    access_token: str,
    client: httpx.AsyncClient,
) -> dict[str, Any]:
    """Fetch user info from Authentik userinfo endpoint."""
    response = await client.get(
        f"{settings.authentik_base_url}/application/o/userinfo/",
        headers={"Authorization": f"Bearer {access_token}"},
    )
    response.raise_for_status()
    return response.json()
