"""Inference client — calls the psyc model server if it is running.

The cockpit venv has no torch; the fine-tuned model only runs inside the CUDA
container behind serve_model.py. This client reaches it over HTTP and degrades
gracefully — if the server is down, callers get None and fall back to rules.
"""

from __future__ import annotations

import json
import os
from typing import Optional

import httpx

from psyc import log
from psyc.lines.train import SEVERITY_INSTRUCTION, severity_features
from psyc.models import Case


INFERENCE_URL = os.environ.get("PSYC_INFERENCE_URL", "http://127.0.0.1:8771")

_log = log.get(__name__)


def server_adapter(timeout: float = 2.0) -> Optional[str]:
    """Return the adapter the server is running, or None if it is unreachable."""
    try:
        with httpx.Client(timeout=timeout) as client:
            resp = client.get(f"{INFERENCE_URL}/healthz")
            resp.raise_for_status()
            return resp.json().get("adapter")
    except httpx.HTTPError:
        return None


def adapter_name(timeout: float = 2.0) -> Optional[str]:
    """Short name of the live adapter, e.g. 'psyc-v5' from '/data/adapters/psyc-v5/final'."""
    path = server_adapter(timeout=timeout)
    if not path:
        return None
    parts = [p for p in path.split("/") if p and p != "final"]
    return parts[-1] if parts else None


def model_severity(case: Case, timeout: float = 15.0) -> Optional[str]:
    """Ask the live model to classify case severity. None if the server is down."""
    payload = {
        "instruction": SEVERITY_INSTRUCTION,
        "input": json.dumps(severity_features(case), ensure_ascii=False),
        "max_new_tokens": 16,
    }
    try:
        with httpx.Client(timeout=timeout) as client:
            resp = client.post(f"{INFERENCE_URL}/infer", json=payload)
            resp.raise_for_status()
            output = str(resp.json().get("output", "")).strip().lower()
    except httpx.HTTPError as exc:
        _log.info("inference.unavailable", error=str(exc))
        return None
    _log.info("inference.severity", case_id=case.case_id, model_answer=output)
    return output
