"""Adapter interface + REST execution base."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, Iterable

import httpx

from .types import AdapterCall, AdapterResult, B2AIntent


class RESTIntentAdapter(ABC):
    """Translates B2A intents to REST calls and normalizes responses."""

    name: str = "adapter"
    intent_patterns: tuple[str, ...] = ()

    def can_handle(self, intent: str) -> bool:
        for pattern in self.intent_patterns:
            if pattern.endswith(".*") and intent.startswith(pattern[:-1]):
                return True
            if intent == pattern:
                return True
        return False

    @abstractmethod
    def build_call(self, intent: B2AIntent) -> AdapterCall:
        """Convert a B2A intent into an HTTP request definition."""

    def normalize_response(self, response: httpx.Response) -> Any:
        """Return JSON when available, otherwise raw text."""
        try:
            return response.json()
        except Exception:
            return {"text": response.text}

    def execute(
        self,
        intent: B2AIntent,
        *,
        base_url: str,
        shared_headers: dict[str, str] | None = None,
    ) -> AdapterResult:
        call = self.build_call(intent)
        headers: dict[str, str] = dict(shared_headers or {})
        headers.update(call.headers)
        url = f"{base_url.rstrip('/')}/{call.path.lstrip('/')}"

        response = httpx.request(
            call.method,
            url,
            params=call.query,
            headers=headers,
            json=call.json_body,
            timeout=call.timeout_s,
        )
        data = self.normalize_response(response)
        return AdapterResult(
            status_code=response.status_code,
            ok=response.status_code < 400,
            data=data,
            adapter=self.name,
        )


def list_supported_intents(adapters: Iterable[RESTIntentAdapter]) -> list[str]:
    patterns: list[str] = []
    for adapter in adapters:
        patterns.extend(adapter.intent_patterns)
    return sorted(set(patterns))

