import asyncio
import logging
from typing import Any, Optional

import httpx

from core.config import settings

logger = logging.getLogger(__name__)


class WorkspaceProfileClient:
    """Cliente para consultar perfil del usuario en Workspace Hub (/v1/auth/me)."""

    def __init__(
        self,
        base_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        retries: int = 2,
        transport: Optional[httpx.BaseTransport] = None,
    ):
        self.base_url = (base_url or settings.hub_api_base_url).rstrip("/")
        self.timeout_s = max(0.1, float(timeout_ms or settings.HUB_PROFILE_SYNC_TIMEOUT_MS) / 1000.0)
        self.retries = max(0, int(retries))
        self.transport = transport

    async def get_me(self, access_token: str) -> dict[str, Any]:
        if not access_token:
            raise ValueError("access_token is required")

        headers = {"Authorization": f"Bearer {access_token}"}
        url = f"{self.base_url}/v1/auth/me"

        last_error: Optional[Exception] = None
        for attempt in range(self.retries + 1):
            try:
                async with httpx.AsyncClient(
                    timeout=self.timeout_s,
                    transport=self.transport,
                ) as client:
                    response = await client.get(url, headers=headers)

                if response.status_code == 200:
                    payload = response.json()
                    if not isinstance(payload, dict):
                        raise ValueError("Invalid workspace profile payload")
                    return payload

                if response.status_code in (401, 403, 404):
                    # Errores de autenticación/autorización o endpoint no disponible:
                    # no vale la pena reintentar.
                    raise httpx.HTTPStatusError(
                        f"Workspace profile request failed with status {response.status_code}",
                        request=response.request,
                        response=response,
                    )

                # Reintentar solo para errores transitorios 5xx.
                if response.status_code >= 500 and attempt < self.retries:
                    await asyncio.sleep(0.15 * (attempt + 1))
                    continue

                raise httpx.HTTPStatusError(
                    f"Workspace profile request failed with status {response.status_code}",
                    request=response.request,
                    response=response,
                )

            except (httpx.TimeoutException, httpx.NetworkError) as exc:
                last_error = exc
                if attempt >= self.retries:
                    break
                await asyncio.sleep(0.15 * (attempt + 1))
            except Exception as exc:
                last_error = exc
                break

        if last_error:
            raise last_error
        raise RuntimeError("Workspace profile request failed")
