"""Authentik directory API client.

Authentik is the user-directory source (replacing the Jellyfin-backed Users
page). This client wraps the Authentik REST API for browsing the user directory
with pagination and search. OIDC authentication is unchanged — this client is
for the directory, not SSO.
"""

from __future__ import annotations

import logging
from typing import Any

import requests

logger = logging.getLogger(__name__)


class AuthentikClient:
    """Small wrapper around the Authentik core directory API."""

    def __init__(self, base_url: str, api_token: str, timeout: float = 10.0):
        if not base_url:
            raise ValueError("Authentik base_url is required")
        if not api_token:
            raise ValueError("Authentik API token is required")

        self.base_url = base_url.rstrip("/")
        if self.base_url.endswith("/api/v3"):
            self.base_url = self.base_url[:-7]
        self.api_token = api_token
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update(
            {
                "Authorization": f"Bearer {api_token}",
                "Accept": "application/json",
            }
        )

    def get(self, path: str, **params: Any) -> Any:
        """GET an Authentik endpoint and include useful response text on errors."""
        clean_params = {k: v for k, v in params.items() if v is not None and v != ""}
        logger.debug("Authentik GET %s params=%s", path, sorted(clean_params.keys()))
        response = self.session.get(
            f"{self.base_url}/api/v3{path}",
            params=clean_params,
            timeout=self.timeout,
        )
        try:
            response.raise_for_status()
        except requests.HTTPError as exc:
            detail = response.text[:500]
            logger.warning(
                "Authentik GET %s failed status=%s url=%s",
                path,
                response.status_code,
                response.url,
            )
            raise requests.HTTPError(
                f"{response.status_code} for {response.url}: {detail}",
                response=response,
            ) from exc
        logger.debug("Authentik GET %s ok status=%s", path, response.status_code)
        return response.json()

    def users(
        self,
        search: str | None = None,
        page: int = 1,
        page_size: int = 50,
    ) -> dict[str, Any]:
        """Return a normalized page of Authentik users.

        Calls ``GET /api/v3/core/users/`` and normalizes the paginated
        Authentik response into ``{items, total, page, page_size}``. Each item
        is the raw Authentik user dict (pk, username, name, email, avatar, …)
        so the frontend can pick the fields it needs.
        """
        payload = self.get(
            "/core/users/",
            search=search,
            page=page,
            page_size=page_size,
        )
        if not isinstance(payload, dict):
            logger.warning("Authentik users payload was not a dict: %s", type(payload).__name__)
            return {"items": [], "total": 0, "page": page, "page_size": page_size}

        results = payload.get("results")
        items: list[dict[str, Any]] = (
            [item for item in results if isinstance(item, dict)] if isinstance(results, list) else []
        )

        pagination = payload.get("pagination") or {}
        total = 0
        if isinstance(pagination, dict):
            try:
                total = int(pagination.get("count") or 0)
            except (TypeError, ValueError):
                total = 0

        logger.info(
            "Authentik users page=%s page_size=%s -> %s items (total=%s)",
            page,
            page_size,
            len(items),
            total,
        )
        return {
            "items": items,
            "total": total,
            "page": page,
            "page_size": page_size,
        }
