"""Slices Pubkey API Client."""

from collections.abc import Collection
from datetime import datetime
from typing import Annotated

from httpx import Client, HTTPError
from msgspec import Meta, Struct
from msgspec.json import Decoder as JsonDecoder
from msgspec.json import encode

from slices_clientlib_core.base.exceptions import from_httpx_exception
from slices_clientlib_core.util.pagination import PagedCollection


class PublicKey(Struct):
    """Public Key."""

    id: int
    user_id: str
    created_at: Annotated[datetime, Meta(tz=True)]
    "Timestamp when this public key was registered."
    public_key: str
    sha256_fingerprint: str
    "SHA256 fingerprint of the public key."

    tags: list[str] | None = None


class PublicKeyCreate(Struct):
    """New Public Key to be registered."""

    public_key: str
    tags: list[str] | None = None


_pubkey_decoder = JsonDecoder(PublicKey)


class PublicKeyClient:
    """Experiment Client."""

    API_BASE_PATH = "/apis/pubkey.slices.eu/v1/pubkeys/"

    def __init__(self, client: Client) -> None:
        """Create Experiment Client."""
        self._client = client

        assert client.base_url is not None, "Expected base_url to be set"

    def register_for_user(self, user_id: str, public_key: str, tags: list[str] | None = None) -> PublicKey:
        """Create experiment."""

        if tags is None:
            tags = []

        response = self._client.post(
            f"{self.API_BASE_PATH}user/{user_id}",
            content=encode(PublicKeyCreate(public_key=public_key, tags=tags)),
        )

        try:
            response.raise_for_status()
            return _pubkey_decoder.decode(response.content)
        except HTTPError as err:
            raise from_httpx_exception(err) from err

    def list_for_user(self, user_id: str) -> Collection[PublicKey]:
        """List public keys."""

        return PagedCollection("public_key", PublicKey, f"{self.API_BASE_PATH}user/{user_id}", self._client)

    def delete(self, public_key: PublicKey) -> PublicKey:
        """Delete public key."""
        return self.delete_by_id(public_key.id)

    def delete_by_id(self, pubkey_id: int) -> PublicKey:
        """Delete public key."""
        response = self._client.delete(f"{self.API_BASE_PATH}{pubkey_id}")

        try:
            response.raise_for_status()
            return _pubkey_decoder.decode(response.content)
        except HTTPError as err:
            raise from_httpx_exception(err) from err
