"""Async client for NormaAI API — zero external dependencies."""

import asyncio
import json
import urllib.request
import urllib.error
from concurrent.futures import ThreadPoolExecutor
from typing import Optional, Dict, Any, List

from .client import NormaAIError, DEFAULT_API_URL


class AsyncNormaAI:
    """Async wrapper around NormaAI API using thread pool executor.

    Uses only stdlib (urllib + asyncio). HTTP calls are dispatched to a
    ThreadPoolExecutor so they never block the event loop.

    Args:
        api_key: API key NormaAI (inizia con "nai_")
        base_url: URL base API (opzionale)
        max_workers: Numero massimo di thread concorrenti (default 4)
    """

    def __init__(
        self,
        api_key: str,
        base_url: Optional[str] = None,
        max_workers: int = 4,
    ):
        if not api_key:
            raise ValueError("api_key obbligatoria")
        self._api_key = api_key
        self._base_url = base_url or DEFAULT_API_URL
        self._executor = ThreadPoolExecutor(max_workers=max_workers)

    # ------------------------------------------------------------------
    # Internal helpers
    # ------------------------------------------------------------------

    def _sync_request(self, path: str, method: str, body: Optional[Dict[str, Any]]) -> Any:
        """Execute a blocking HTTP request (runs inside the thread pool)."""
        url = f"{self._base_url}{path}"
        headers = {
            "X-API-Key": self._api_key,
            "Content-Type": "application/json",
        }
        data = json.dumps(body).encode("utf-8") if body else None
        req = urllib.request.Request(url, data=data, headers=headers, method=method)

        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except urllib.error.HTTPError as e:
            body_text = e.read().decode("utf-8", errors="replace")
            try:
                err_data = json.loads(body_text)
                raise NormaAIError(
                    err_data.get("message", err_data.get("error", f"HTTP {e.code}")),
                    status=e.code,
                    code=err_data.get("error", ""),
                ) from e
            except json.JSONDecodeError:
                raise NormaAIError(f"HTTP {e.code}: {body_text[:200]}", status=e.code) from e

    async def _request(self, path: str, method: str = "GET", body: Optional[Dict[str, Any]] = None) -> Any:
        """Dispatch a request to the thread pool and await the result."""
        loop = asyncio.get_event_loop()
        return await loop.run_in_executor(self._executor, self._sync_request, path, method, body)

    # ------------------------------------------------------------------
    # Public API — mirrors NormaAI sync client
    # ------------------------------------------------------------------

    async def query(self, question: str, vertical_id: str) -> Dict[str, Any]:
        """Domanda normativa con risposta AI e fonti citate.

        Args:
            question: Domanda in italiano (max 2000 caratteri)
            vertical_id: Verticale (lavoro|commercialista|avvocato|ingegnere|finanziario)

        Returns:
            dict con keys: answer, sources, tokens_used, vertical, response_time_ms
        """
        return await self._request("/query", "POST", {
            "question": question,
            "vertical_id": vertical_id,
        })

    async def verticals(self) -> List[Dict[str, Any]]:
        """Lista verticali disponibili."""
        return await self._request("/verticals")

    async def sources(self, vertical_id: str) -> List[Dict[str, Any]]:
        """Lista fonti normative per verticale."""
        return await self._request(f"/sources?vertical_id={vertical_id}")

    async def usage(self) -> Dict[str, Any]:
        """Statistiche consumo API key."""
        return await self._request("/usage")
