"""HTTP step implemented with httpx (async)."""

from __future__ import annotations

from typing import Any, Mapping

import httpx
from pydantic import BaseModel, Field

from agentbyte.workflow.core.models import StepMetadata, WorkflowContext
from agentbyte.workflow.steps.step import BaseStep


class HttpRequestInput(BaseModel):
    url: str
    method: str = Field(default="GET")
    headers: Mapping[str, str] | None = None
    data: Any | None = None
    timeout: float | None = None
    verify_ssl: bool = True


class HttpResponseOutput(BaseModel):
    status_code: int
    content: str
    headers: Mapping[str, str]
    url: str
    encoding: str | None = None
    elapsed_time: float | None = None
    error: str | None = None


class HttpStep(BaseStep[HttpRequestInput, HttpResponseOutput]):
    """Makes an HTTP request using httpx.AsyncClient."""

    def __init__(self, step_id: str, metadata: StepMetadata, client: httpx.AsyncClient | None = None) -> None:
        super().__init__(step_id, metadata, HttpRequestInput, HttpResponseOutput)
        self._client = client

    async def execute(self, input_data: HttpRequestInput, context: WorkflowContext) -> HttpResponseOutput:
        client = self._client or httpx.AsyncClient()
        try:
            response = await client.request(
                method=input_data.method,
                url=input_data.url,
                headers=dict(input_data.headers or {}),
                content=input_data.data,
                timeout=input_data.timeout,
            )
            try:
                elapsed = response.elapsed.total_seconds() if response.elapsed else None
            except RuntimeError:
                elapsed = None
            output = HttpResponseOutput(
                status_code=response.status_code,
                content=response.text,
                headers=response.headers,
                url=str(response.url),
                encoding=response.encoding,
                elapsed_time=elapsed,
            )
            context.set(f"{self.step_id}_status", response.status_code)
            return output
        except (httpx.TimeoutException, httpx.RequestError) as exc:
            return HttpResponseOutput(
                status_code=0,
                content="",
                headers={},
                url=input_data.url,
                error=str(exc),
            )
        finally:
            if self._client is None:
                await client.aclose()


__all__ = ["HttpStep", "HttpRequestInput", "HttpResponseOutput"]
