"""Основной клиент SDK."""

import httpx
from typing import Optional

from .users import UsersAPI
from .profiles import ProfilesAPI
from .nodes import NodesAPI
from .exceptions import AuthenticationError, APIError


class AmnezioClient:
    """Клиент для работы с панелью Amnezio."""
    
    def __init__(
        self,
        base_url: str,
        username: Optional[str] = None,
        password: Optional[str] = None,
        api_token: Optional[str] = None,
        timeout: float = 30.0,
    ):
        """
        Инициализация клиента.
        
        Args:
            base_url: URL панели (например, https://panel.example.com)
            username: Имя пользователя админа (если используется логин/пароль)
            password: Пароль админа (если используется логин/пароль)
            api_token: API токен (альтернатива логину/паролю)
            timeout: Таймаут запросов в секундах
        """
        self.base_url = base_url.rstrip("/")
        self.username = username
        self.password = password
        self.api_token = api_token
        self.timeout = timeout
        
        # Проверка: должен быть либо api_token, либо username+password
        if not api_token and not (username and password):
            raise ValueError("Необходимо указать либо api_token, либо username и password")
        
        self._http_client: Optional[httpx.AsyncClient] = None
        self._token: Optional[str] = None
        
        # API endpoints
        self.users = UsersAPI(self)
        self.profiles = ProfilesAPI(self)
        self.nodes = NodesAPI(self)
    
    async def __aenter__(self):
        """Асинхронный контекстный менеджер."""
        await self._ensure_authenticated()
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """Закрытие клиента."""
        await self.close()
    
    async def close(self):
        """Закрыть HTTP клиент."""
        if self._http_client:
            await self._http_client.aclose()
            self._http_client = None
    
    def _get_http_client(self) -> httpx.AsyncClient:
        """Получить или создать HTTP клиент."""
        if self._http_client is None:
            self._http_client = httpx.AsyncClient(
                base_url=self.base_url,
                timeout=self.timeout,
            )
        return self._http_client
    
    async def _authenticate(self) -> str:
        """
        Аутентификация и получение токена.
        
        Returns:
            Токен доступа
        """
        # Если используется API токен, возвращаем его
        if self.api_token:
            return self.api_token
        
        # Иначе логинимся по username/password
        client = self._get_http_client()
        
        try:
            response = await client.post(
                "/api/auth/login",
                json={
                    "login": self.username,
                    "password": self.password,
                }
            )
            
            if response.status_code == 401:
                raise AuthenticationError("Неверные учетные данные")
            
            if response.status_code != 200:
                raise APIError(response.status_code, response.text)
            
            data = response.json()
            return data.get("access_token") or data.get("token")
        
        except httpx.HTTPError as e:
            raise APIError(0, f"Ошибка соединения: {str(e)}")
    
    async def _ensure_authenticated(self):
        """Убедиться, что клиент аутентифицирован."""
        if not self._token:
            self._token = await self._authenticate()
    
    async def request(
        self,
        method: str,
        path: str,
        **kwargs
    ) -> httpx.Response:
        """
        Выполнить HTTP запрос.
        
        Args:
            method: HTTP метод (GET, POST, PUT, DELETE)
            path: Путь API (например, /api/users)
            **kwargs: Дополнительные параметры для httpx
        
        Returns:
            HTTP ответ
        """
        await self._ensure_authenticated()
        
        client = self._get_http_client()
        
        # Добавляем токен в заголовки
        headers = kwargs.pop("headers", {})
        headers["Authorization"] = f"Bearer {self._token}"
        
        try:
            response = await client.request(
                method=method,
                url=path,
                headers=headers,
                **kwargs
            )
            
            # Повторная аутентификация при 401 (только для JWT, не для API токенов)
            if response.status_code == 401 and not self.api_token:
                self._token = None
                await self._ensure_authenticated()
                headers["Authorization"] = f"Bearer {self._token}"
                
                response = await client.request(
                    method=method,
                    url=path,
                    headers=headers,
                    **kwargs
                )
            
            return response
        
        except httpx.HTTPError as e:
            raise APIError(0, f"Ошибка запроса: {str(e)}")
