from __future__ import annotations

from typing import Any

import httpx

from arp_standard_client.errors import ArpApiError
from arp_standard_model import (
    DaemonCreateInstancesRequest,
    DaemonDeleteInstanceRequest,
    DaemonDeleteRuntimeProfileRequest,
    DaemonGetRunResultRequest,
    DaemonGetRunStatusRequest,
    DaemonGetRunTraceRequest,
    DaemonHealthRequest,
    DaemonListInstancesRequest,
    DaemonListRunsRequest,
    DaemonListRuntimeProfilesRequest,
    DaemonRegisterInstanceRequest,
    DaemonSubmitRunRequest,
    DaemonUpsertRuntimeProfileRequest,
    DaemonVersionRequest,
    Health,
    InstanceCreateRequest,
    InstanceCreateResponse,
    InstanceListResponse,
    InstanceRegisterRequest,
    InstanceRegisterResponse,
    RunListResponse,
    RunRequest,
    RunResult,
    RunStatus,
    RuntimeProfile,
    RuntimeProfileListResponse,
    RuntimeProfileUpsertRequest,
    TraceResponse,
    VersionInfo,
)

from .api.health import (
    health,
)

from .api.instances import (
    create_instances,
    delete_instance,
    list_instances,
    register_instance,
)

from .api.runs import (
    get_run_result,
    get_run_status,
    get_run_trace,
    list_runs,
    submit_run,
)

from .api.runtime_profiles import (
    delete_runtime_profile,
    list_runtime_profiles,
    upsert_runtime_profile,
)

from .api.version import (
    version,
)

from .client import Client as _LowLevelClient
from arp_standard_model import ErrorEnvelope as _ErrorEnvelope
from .types import Response as _Response
from .types import Unset as _Unset
from .types import UNSET as _UNSET

def _raise_for_error_envelope(*, envelope: _ErrorEnvelope, status_code: int | None, raw: Any | None) -> None:
    details: Any | None = None
    if not isinstance(envelope.error.details, _Unset):
        details = envelope.error.details
    raise ArpApiError(
        code=str(envelope.error.code),
        message=str(envelope.error.message),
        details=details,
        status_code=status_code,
        raw=raw,
    )

def _unwrap(response: _Response[Any], *, allow_none: bool = False) -> Any:
    parsed = response.parsed
    if parsed is None:
        if allow_none:
            return None
        raise ArpApiError(
            code="unexpected_empty_response",
            message="API returned an empty response",
            status_code=int(response.status_code),
            raw=response.content,
        )
    if isinstance(parsed, _ErrorEnvelope):
        _raise_for_error_envelope(
            envelope=parsed,
            status_code=int(response.status_code),
            raw=parsed.model_dump(exclude_none=True),
        )
    return parsed

class DaemonClient:
    def __init__(
        self,
        base_url: str | None = None,
        *,
        client: _LowLevelClient | None = None,
        timeout: httpx.Timeout | None = None,
        headers: dict[str, str] | None = None,
        cookies: dict[str, str] | None = None,
        verify_ssl: Any = True,
        follow_redirects: bool = False,
        raise_on_unexpected_status: bool = False,
        httpx_args: dict[str, Any] | None = None,
    ) -> None:
        if client is None:
            if base_url is None:
                raise ValueError("base_url is required when client is not provided")
            client = _LowLevelClient(
                base_url=base_url,
                timeout=timeout,
                headers={} if headers is None else dict(headers),
                cookies={} if cookies is None else dict(cookies),
                verify_ssl=verify_ssl,
                follow_redirects=follow_redirects,
                raise_on_unexpected_status=raise_on_unexpected_status,
                httpx_args={} if httpx_args is None else dict(httpx_args),
            )
        self._client = client

    @property
    def raw_client(self) -> _LowLevelClient:
        return self._client

    def create_instances(self, request: DaemonCreateInstancesRequest) -> InstanceCreateResponse:
        resp = create_instances.sync_detailed(client=self._client, body=request.body)
        return _unwrap(resp)

    def delete_instance(self, request: DaemonDeleteInstanceRequest) -> None:
        params = request.params
        resp = delete_instance.sync_detailed(client=self._client, instance_id=params.instance_id)
        _unwrap(resp, allow_none=True)
        return None

    def delete_runtime_profile(self, request: DaemonDeleteRuntimeProfileRequest) -> None:
        params = request.params
        resp = delete_runtime_profile.sync_detailed(client=self._client, runtime_profile=params.runtime_profile)
        _unwrap(resp, allow_none=True)
        return None

    def get_run_result(self, request: DaemonGetRunResultRequest) -> RunResult:
        params = request.params
        resp = get_run_result.sync_detailed(client=self._client, run_id=params.run_id)
        return _unwrap(resp)

    def get_run_status(self, request: DaemonGetRunStatusRequest) -> RunStatus:
        params = request.params
        resp = get_run_status.sync_detailed(client=self._client, run_id=params.run_id)
        return _unwrap(resp)

    def get_run_trace(self, request: DaemonGetRunTraceRequest) -> TraceResponse:
        params = request.params
        resp = get_run_trace.sync_detailed(client=self._client, run_id=params.run_id)
        return _unwrap(resp)

    def health(self, request: DaemonHealthRequest) -> Health:
        _ = request
        resp = health.sync_detailed(client=self._client)
        return _unwrap(resp)

    def list_instances(self, request: DaemonListInstancesRequest) -> InstanceListResponse:
        _ = request
        resp = list_instances.sync_detailed(client=self._client)
        return _unwrap(resp)

    def list_runs(self, request: DaemonListRunsRequest) -> RunListResponse:
        params = request.params
        resp = list_runs.sync_detailed(client=self._client, page_size=_UNSET if params.page_size is None else params.page_size, page_token=_UNSET if params.page_token is None else params.page_token)
        return _unwrap(resp)

    def list_runtime_profiles(self, request: DaemonListRuntimeProfilesRequest) -> RuntimeProfileListResponse:
        _ = request
        resp = list_runtime_profiles.sync_detailed(client=self._client)
        return _unwrap(resp)

    def register_instance(self, request: DaemonRegisterInstanceRequest) -> InstanceRegisterResponse:
        resp = register_instance.sync_detailed(client=self._client, body=request.body)
        return _unwrap(resp)

    def submit_run(self, request: DaemonSubmitRunRequest) -> RunStatus:
        resp = submit_run.sync_detailed(client=self._client, body=request.body)
        return _unwrap(resp)

    def upsert_runtime_profile(self, request: DaemonUpsertRuntimeProfileRequest) -> RuntimeProfile:
        params = request.params
        resp = upsert_runtime_profile.sync_detailed(client=self._client, runtime_profile=params.runtime_profile, body=request.body)
        return _unwrap(resp)

    def version(self, request: DaemonVersionRequest) -> VersionInfo:
        _ = request
        resp = version.sync_detailed(client=self._client)
        return _unwrap(resp)

__all__ = [
    'DaemonClient',
]
