"""Token endpoints for managing access tokens."""

from typing import NotRequired, TypedDict, Unpack, final

from pydantic import TypeAdapter

from ksef2.core import routes
from ksef2.endpoints.base import BaseEndpoints
from ksef2.infra.schema.api import spec

ListTokensQueryParams = TypedDict(
    "ListTokensQueryParams",
    {
        "status": NotRequired[list[str] | None],
        "description": NotRequired[str | None],
        "authorIdentifier": NotRequired[str | None],
        "authorIdentifierType": NotRequired[str | None],
        "pageSize": NotRequired[int | None],
    },
)
_LIST_TOKENS_PARAMS = TypeAdapter(ListTokensQueryParams)


@final
class TokenEndpoints(BaseEndpoints):
    """Raw token endpoints backed by generated schema models."""

    def generate_token(
        self, body: spec.GenerateTokenRequest
    ) -> spec.GenerateTokenResponse:
        """Create a token using schema-native request and response models.

        Args:
            body: Request payload expected by the generated API schema.

        Returns:
            The token creation response returned by KSeF.
        """
        return self._parse(
            self._transport.post(
                path=routes.TokenRoutes.GENERATE_TOKEN,
                json=body.model_dump(mode="json", by_alias=True),
            ),
            spec.GenerateTokenResponse,
        )

    def list_tokens(
        self,
        continuation_token: str | None = None,
        **params: Unpack[ListTokensQueryParams],
    ) -> spec.QueryTokensResponse:
        """Fetch one page of tokens.

        Args:
            continuation_token: Pagination token sent in the
                ``x-continuation-token`` header to request the next page.
            **params: Optional query parameters supported by ``GET /tokens``.

        Returns:
            One page of token results from the API.
        """
        headers = (
            {"x-continuation-token": continuation_token} if continuation_token else None
        )

        return self._parse(
            self._transport.get(
                path=routes.TokenRoutes.LIST_TOKENS,
                params=self.build_params(params, _LIST_TOKENS_PARAMS),
                headers=headers,
            ),
            spec.QueryTokensResponse,
        )

    def token_status(self, reference_number: str) -> spec.TokenStatusResponse:
        """Fetch the current activation status for a token reference."""
        return self._parse(
            self._transport.get(
                path=routes.TokenRoutes.TOKEN_STATUS.format(
                    referenceNumber=reference_number
                ),
            ),
            spec.TokenStatusResponse,
        )

    def revoke_token(self, reference_number: str) -> None:
        """Revoke a token by its reference number."""
        _ = self._transport.delete(
            path=routes.TokenRoutes.REVOKE_TOKEN.format(
                referenceNumber=reference_number
            ),
        )
