
from __future__ import annotations

import base64
from pathlib import Path

import requests

from yurolabs.config import load_base_url, load_key


def _headers() -> dict:
    return {"Authorization": load_key()}


def list_models() -> list[dict]:
    """Return available models from the configured S3 bucket."""
    response = requests.get(_build_url("/models"), headers=_headers(), timeout=30)
    _raise_for_status(response)

    try:
        payload = response.json()
    except ValueError:
        return []

    if isinstance(payload, list):
        return payload

    if isinstance(payload, dict):
        models = payload.get("models", [])
        return models if isinstance(models, list) else []

    return []


def deploy_model(s3_key: str, name: str | None = None) -> dict:
    payload = {"s3_key": s3_key}
    if name:
        payload["name"] = name
    response = requests.post(_build_url("/deploy"), json=payload, headers=_headers(), timeout=60)
    _raise_for_status(response)
    return response.json()


def run_inference_from_bytes(image_bytes: bytes) -> dict:
    files = {"image": ("upload.jpg", image_bytes)}
    response = requests.post(_build_url("/infer"), files=files, headers=_headers(), timeout=120)
    _raise_for_status(response)
    return response.json()


def run_inference_from_path(image_path: str | Path) -> dict:
    with open(image_path, "rb") as fh:
        return run_inference_from_bytes(fh.read())


def run_inference_from_base64(content: str) -> dict:
    image_bytes = base64.b64decode(content)
    return run_inference_from_bytes(image_bytes)


def _build_url(path: str) -> str:
    base = load_base_url().rstrip("/")
    return f"{base}{path}"


def _raise_for_status(response: requests.Response) -> None:
    if response.ok:
        return

    message = _extract_error_message(response)
    if message:
        raise requests.HTTPError(message, response=response)

    response.raise_for_status()


def _extract_error_message(response: requests.Response) -> str:
    try:
        payload = response.json()
    except ValueError:
        return ""
    if isinstance(payload, dict):
        error = payload.get("error") or payload.get("detail")
        details = payload.get("details")
        if error and details:
            return f"{error}: {details}"
        if error:
            return error
        if details:
            return str(details)
    text = response.text.strip()
    if text:
        return text
    return ""
