from __future__ import annotations

from typing import Any

import httpx
from flask import jsonify, request

from . import settings


class AriadneError(Exception):
    def __init__(self, message: str, status_code: int = 502) -> None:
        super().__init__(message)
        self.status_code = status_code


def enabled() -> bool:
    return bool(settings.ARIADNE_URL)


def _auth_headers() -> dict[str, str]:
    header = request.headers.get("Authorization", "").strip()
    return {"Authorization": header} if header else {}


def _url(path: str) -> str:
    base = settings.ARIADNE_URL.rstrip("/")
    suffix = path.lstrip("/")
    return f"{base}/{suffix}" if suffix else base


def request_raw(
    method: str,
    path: str,
    *,
    payload: Any | None = None,
    params: dict[str, Any] | None = None,
) -> httpx.Response:
    if not enabled():
        raise AriadneError("ariadne not configured", 503)

    try:
        with httpx.Client(timeout=settings.ARIADNE_TIMEOUT_SEC) as client:
            return client.request(
                method,
                _url(path),
                headers=_auth_headers(),
                json=payload,
                params=params,
            )
    except httpx.RequestError as exc:
        raise AriadneError("ariadne unavailable", 502) from exc


def proxy(
    method: str,
    path: str,
    *,
    payload: Any | None = None,
    params: dict[str, Any] | None = None,
) -> tuple[Any, int]:
    try:
        resp = request_raw(method, path, payload=payload, params=params)
    except AriadneError as exc:
        return jsonify({"error": str(exc)}), exc.status_code

    try:
        data = resp.json()
    except ValueError:
        detail = resp.text.strip()
        data = {"error": detail or "upstream error"}

    return jsonify(data), resp.status_code
