import os
from dataclasses import dataclass, field

import requests


DEFAULT_BASE_URL = (
    os.getenv("UNVII_BASE_URL", "https://unvii.onrender.com").strip()
    or "https://unvii.onrender.com"
)


def _format_server_error(response: requests.Response, context: str) -> str:
    detail = ""
    content_type = response.headers.get("Content-Type", "")
    if "application/json" in content_type:
        try:
            payload = response.json()
        except ValueError:
            payload = None
        if isinstance(payload, dict):
            detail = str(payload.get("error") or payload.get("message") or "").strip()
            if not detail:
                detail = str(payload).strip()
    if not detail:
        detail = (response.text or "").strip()
    if len(detail) > 280:
        detail = f"{detail[:277]}..."

    message = f"{context} failed ({response.status_code}) for {response.url}."
    if detail:
        return f"{message} Server response: {detail}"
    return message


def _raise_for_status(response: requests.Response, context: str) -> None:
    if response.ok:
        return
    raise requests.HTTPError(_format_server_error(response, context), response=response)


def generate_api_key(base_url: str = DEFAULT_BASE_URL, timeout: float = 15.0) -> str:
    url = f"{base_url.rstrip('/')}/v1/api-keys/generate"
    response = requests.post(url, timeout=timeout)
    _raise_for_status(response, "API key generation")
    payload = response.json()
    api_key = payload.get("api_key")
    if not api_key:
        raise RuntimeError("Server response did not include an api_key.")
    return api_key


@dataclass(slots=True)
class Model:
    api_key: str
    system_prompt: str
    base_url: str = DEFAULT_BASE_URL
    timeout: float = 60.0
    model_id: str = field(init=False)

    def __post_init__(self) -> None:
        if not self.api_key:
            raise ValueError("api_key is required.")
        if not self.system_prompt.strip():
            raise ValueError("system_prompt is required.")

        url = f"{self.base_url.rstrip('/')}/v1/models"
        response = requests.post(
            url,
            json={"system_prompt": self.system_prompt},
            headers=self._headers(),
            timeout=self.timeout,
        )
        _raise_for_status(response, "Model creation")
        payload = response.json()
        self.model_id = payload["model_id"]

    def generate_text(self, prompt: str) -> str:
        if not prompt.strip():
            raise ValueError("prompt is required.")

        url = f"{self.base_url.rstrip('/')}/v1/models/{self.model_id}/generate"
        response = requests.post(
            url,
            json={"prompt": prompt},
            headers=self._headers(),
            timeout=self.timeout,
        )
        _raise_for_status(response, f"Text generation for model {self.model_id}")
        payload = response.json()
        text = payload.get("text")
        if not text:
            raise RuntimeError("Server response did not include generated text.")
        return text

    def _headers(self) -> dict[str, str]:
        return {"X-API-Key": self.api_key}
