"""Small async client for the internal AuthZ service."""

from __future__ import annotations

from typing import Any

import httpx


class AuthzClient:
    def __init__(self, base_url: str, timeout_seconds: int = 10) -> None:
        self.base_url = base_url.rstrip("/")
        self.timeout_seconds = timeout_seconds

    async def _request(self, method: str, path: str, *, json_body: dict[str, Any] | None = None) -> Any:
        async with httpx.AsyncClient(
            timeout=self.timeout_seconds,
            follow_redirects=True,
            trust_env=False,
        ) as client:
            response = await client.request(method, f"{self.base_url}{path}", json=json_body)
        response.raise_for_status()
        if not response.content:
            return None
        return response.json()

    async def issue_token(
        self,
        *,
        client_id: str,
        client_secret: str,
        audience: str,
        scopes: list[str],
    ) -> dict[str, Any]:
        data = await self._request(
            "POST",
            "/oauth/token",
            json_body={
                "grant_type": "client_credentials",
                "client_id": client_id,
                "client_secret": client_secret,
                "aud": audience,
                "scopes": list(scopes),
            },
        )
        return data if isinstance(data, dict) else {}

    async def get_permissions(self, backend_id: str) -> dict[str, Any]:
        data = await self._request("GET", f"/backends/{backend_id}/permissions")
        return data if isinstance(data, dict) else {}

    async def set_permissions(self, backend_id: str, payload: dict[str, Any]) -> dict[str, Any]:
        data = await self._request("POST", f"/backends/{backend_id}/permissions", json_body=payload)
        return data if isinstance(data, dict) else {}

    async def register_user(
        self,
        *,
        username: str,
        password: str,
        email: str | None = None,
        backend_name: str | None = None,
        backend_id: str | None = None,
        base_url: str | None = None,
        frontend_base_url: str | None = None,
    ) -> dict[str, Any]:
        payload: dict[str, Any] = {
            "username": username,
            "password": password,
        }
        optional = {
            "email": email,
            "backend_name": backend_name,
            "backend_id": backend_id,
            "base_url": base_url,
            "frontend_base_url": frontend_base_url,
        }
        payload.update({key: value for key, value in optional.items() if value})
        data = await self._request("POST", "/oauth/register", json_body=payload)
        return data if isinstance(data, dict) else {}

    async def register_backend(
        self,
        *,
        name: str,
        base_url: str,
        frontend_base_url: str | None = None,
        backend_id: str | None = None,
    ) -> dict[str, Any]:
        payload: dict[str, Any] = {
            "name": name,
            "base_url": base_url,
        }
        if frontend_base_url:
            payload["frontend_base_url"] = frontend_base_url
        if backend_id:
            payload["backend_id"] = backend_id
        data = await self._request("POST", "/backends/register", json_body=payload)
        return data if isinstance(data, dict) else {}

    async def get_outlook_settings(self, backend_id: str) -> dict[str, Any]:
        data = await self._request("GET", f"/backends/{backend_id}/settings/outlook")
        return data if isinstance(data, dict) else {}

    async def set_outlook_settings(self, backend_id: str, payload: dict[str, Any]) -> dict[str, Any]:
        data = await self._request("POST", f"/backends/{backend_id}/settings/outlook", json_body=payload)
        return data if isinstance(data, dict) else {}

    async def delete_outlook_settings(self, backend_id: str) -> dict[str, Any]:
        data = await self._request("DELETE", f"/backends/{backend_id}/settings/outlook")
        return data if isinstance(data, dict) else {}

    async def get_minio_settings(self, backend_id: str) -> dict[str, Any]:
        data = await self._request("GET", f"/backends/{backend_id}/settings/minio")
        return data if isinstance(data, dict) else {}

    async def set_minio_settings(self, backend_id: str, payload: dict[str, Any]) -> dict[str, Any]:
        data = await self._request("POST", f"/backends/{backend_id}/settings/minio", json_body=payload)
        return data if isinstance(data, dict) else {}

    async def delete_minio_settings(self, backend_id: str) -> dict[str, Any]:
        data = await self._request("DELETE", f"/backends/{backend_id}/settings/minio")
        return data if isinstance(data, dict) else {}
