"""Custom requests — using client.request() and request_stream() directly.

The SDK doesn't cover every SeaArt API endpoint. For anything not wrapped
by a resource method, use the low-level request interface:

  client.request()        — single request, returns APIEnvelope
  client.request_raw()    — single request, returns raw curl_cffi Response
  client.request_stream() — SSE stream, yields parsed events

All methods handle authentication headers, base URL construction,
and logging automatically — you only provide the path and payload.

Requires:
    SEAART_EMAIL and SEAART_PASSWORD environment variables.
"""

from __future__ import annotations

import os
from types import SimpleNamespace
from typing import Any

from seaart import SyncClient
from seaart._transport_sse import SSEEvent


# ---------------------------------------------------------------------------
# GET request — fetch raw data from an endpoint
# ---------------------------------------------------------------------------


def get_request() -> None:
    """Fetch data from an uncovered endpoint with a GET request."""
    with SyncClient() as client:
        client.auth.login(
            email=os.environ["SEAART_EMAIL"],
            password=os.environ["SEAART_PASSWORD"],
        )

        # .data is the raw parsed dict (or None).
        # .value is the same but raises MissingDataError if None.
        envelope = client.request("GET", "some/endpoint", params={"limit": 10})
        print(f"Status: {envelope.status.code}")
        print(f"Data: {envelope.data}")


# ---------------------------------------------------------------------------
# POST request — send a JSON body
# ---------------------------------------------------------------------------


def post_request() -> None:
    """Send a JSON payload to an uncovered endpoint."""
    with SyncClient() as client:
        client.auth.login(
            email=os.environ["SEAART_EMAIL"],
            password=os.environ["SEAART_PASSWORD"],
        )

        envelope = client.request(
            "POST",
            "some/endpoint",
            json={"key": "value", "count": 5},
        )
        print(f"Status: {envelope.status.code}")
        print(f"Data: {envelope.data}")


# ---------------------------------------------------------------------------
# SSE stream — consume server-sent events
# ---------------------------------------------------------------------------


def stream_request() -> None:
    """Stream SSE events from an uncovered endpoint.

    request_stream() requires a parser function that converts each raw
    SSE event into the type you want to yield. The built-in
    client.parse_sse_stream wraps events into a SimpleNamespace with
    .event, .data, and .headers attributes.
    """

    def parser(ev: SSEEvent, obj: dict[str, Any] | None) -> SimpleNamespace:
        return SimpleNamespace(event=ev.event, data=obj or ev.data)

    with SyncClient() as client:
        client.auth.login(
            email=os.environ["SEAART_EMAIL"],
            password=os.environ["SEAART_PASSWORD"],
        )

        for item in client.request_stream(
            "POST",
            "some/stream-endpoint",
            json={"prompt": "Hello"},
            parser=parser,
        ):
            print(f"[{item.event}] {item.data}")


# ---------------------------------------------------------------------------
# Using the built-in parser
# ---------------------------------------------------------------------------


def stream_with_builtin_parser() -> None:
    """Same as above, but using client.parse_sse_stream as the parser.

    parse_sse_stream returns a SimpleNamespace with .event, .data,
    and .headers for each SSE event — no custom parser needed.
    """
    with SyncClient() as client:
        client.auth.login(
            email=os.environ["SEAART_EMAIL"],
            password=os.environ["SEAART_PASSWORD"],
        )

        for item in client.request_stream(
            "POST",
            "some/stream-endpoint",
            json={"prompt": "Hello"},
            parser=client.parse_sse_stream,
        ):
            print(f"[{item.event}] {item.data}")


# ---------------------------------------------------------------------------
# Raw request — bypass APIEnvelope parsing
# ---------------------------------------------------------------------------


def raw_request() -> None:
    """Get a raw curl_cffi Response without APIEnvelope parsing.

    Use request_raw() when the endpoint returns HTML, binary data,
    or any format that doesn't fit the standard SeaArt API envelope.
    """
    with SyncClient() as client:
        client.auth.login(
            email=os.environ["SEAART_EMAIL"],
            password=os.environ["SEAART_PASSWORD"],
        )

        r = client.request_raw("GET", "some/page")
        print(f"Status: {r.status_code}")
        print(f"Content-Type: {r.headers.get('content-type')}")
        print(f"Body: {r.text[:200]}")


def raw_request_binary() -> None:
    """Download binary content (e.g. an image) with request_raw()."""
    with SyncClient() as client:
        client.auth.login(
            email=os.environ["SEAART_EMAIL"],
            password=os.environ["SEAART_PASSWORD"],
        )

        r = client.request_raw("GET", "some/image-endpoint")
        with open("downloaded.png", "wb") as f:
            f.write(r.content)
        print(f"Saved {len(r.content)} bytes")


if __name__ == "__main__":
    get_request()
