"""Client HTTP vers le STT-server (in-cluster).

Le client n'a plus de cerveau : il envoie le texte transcrit au serveur, qui
orchestre l'inférence (LiteLLM → Qwen3/Claude) et renvoie la réponse. Le client
choisit le modèle (alias LiteLLM) et le passe au serveur par requête.
"""

from __future__ import annotations

import uuid
from typing import Any


class ServerClient:
    def __init__(self, cfg: dict[str, Any]):
        self.url = cfg["url"].rstrip("/")
        self.timeout = cfg.get("timeout_sec", 90)
        self.model = cfg.get("model", "hermes-default")
        # contexte présélectionné (None = défaut serveur). Piloté par le HUD.
        self.context = cfg.get("context")
        # dernier contexte assemblé renvoyé par le serveur (pour le visualiseur)
        self.last_context: dict | None = None
        self.last_context_id: str | None = None
        # jetons à transmettre au serveur (ex. {"ghostfolio_token": …}) — source UNIQUE
        # du jeton, côté client ; le serveur les consomme (contexte + /v1/portfolio).
        self.secrets: dict = {}
        # une session par run → mémoire court-terme côté serveur
        self.session_id = uuid.uuid4().hex

    def ask(self, text: str, model: str | None = None) -> str:
        import requests

        payload = {
            "text": text,
            "model": model or self.model,
            "session_id": self.session_id,
        }
        if self.context:
            payload["context"] = self.context
        if self.secrets:
            payload["secrets"] = self.secrets
        r = requests.post(f"{self.url}/v1/ask", json=payload, timeout=self.timeout)
        if r.status_code == 400:
            raise RuntimeError(r.json().get("detail", "requête invalide"))
        r.raise_for_status()
        data = r.json()
        # contexte assemblé (système + sources live + RAG + mémoire) → visualiseur HUD
        self.last_context = data.get("context")
        self.last_context_id = data.get("context_id")
        return data["reply"].strip()

    def portfolio(self) -> str:
        """Valeur du portefeuille Ghostfolio via le serveur (jeton client transmis).

        Unifie le jeton : c'est le serveur qui parle à Ghostfolio. Dégrade en message
        clair si le serveur est antérieur (pas d'endpoint) ou injoignable.
        """
        import requests

        try:
            r = requests.post(
                f"{self.url}/v1/portfolio",
                json={"token": self.secrets.get("ghostfolio_token")},
                timeout=self.timeout,
            )
            r.raise_for_status()
            return (r.json().get("summary") or "").strip() or "Pas de réponse de Ghostfolio."
        except requests.RequestException:
            return "Je n'arrive pas à joindre le serveur pour Ghostfolio."

    def portfolio_details(self) -> dict:
        """Aperçu structuré du portefeuille (page détail du portail HUD).

        {value, currency, performance_pct, holdings:[…]} ou {error: …}. Dégrade en
        clair si le serveur est antérieur (pas d'endpoint) ou injoignable.
        """
        import requests

        try:
            r = requests.post(
                f"{self.url}/v1/portfolio/details",
                json={"token": self.secrets.get("ghostfolio_token")},
                timeout=self.timeout,
            )
            if r.status_code == 404:
                return {"error": "Aperçu indisponible (STT-server antérieur)."}
            r.raise_for_status()
            return r.json()
        except requests.RequestException:
            return {"error": "Je n'arrive pas à joindre le serveur pour Ghostfolio."}

    def contexts(self) -> dict | None:
        """{'default':…, 'contexts':[{id,label,icon,description}]} ; None si indisponible.

        Dégrade en None sur un serveur antérieur (endpoint absent) → pas de sélecteur.
        """
        import requests

        try:
            r = requests.get(f"{self.url}/v1/contexts", timeout=10)
            r.raise_for_status()
            return r.json()
        except requests.RequestException:
            return None

    def reset(self) -> None:
        import requests

        try:
            requests.post(
                f"{self.url}/v1/reset",
                json={"text": "", "session_id": self.session_id},
                timeout=10,
            )
        except requests.RequestException:
            pass

    def models(self) -> dict:
        """{'default': ..., 'available': [...]} depuis le serveur."""
        import requests

        r = requests.get(f"{self.url}/v1/models", timeout=10)
        r.raise_for_status()
        return r.json()

    def healthy(self) -> bool:
        import requests

        try:
            r = requests.get(f"{self.url}/healthz", timeout=5)
            return r.ok
        except requests.RequestException:
            return False
