"""Batch error handling: per-item results (003 §5) and the on_reject hook."""

import os

import httpx

from tessera import Tessera
from tessera.errors import TesseraValidationError

# --- 1. the wire contract: per-item results ----------------------------------
# One bad event never poisons the batch: the endpoint answers 207-style with
# an index, code and message per rejected item.
response = httpx.post(
    f"{os.environ['TESSERA_INGEST_BASE']}/events",
    headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
    json={
        "events": [
            {
                "entity": {"type": "user", "id": "sdk_sample_3"},
                "event_type": "cart.item_added",
                "timestamp": "2026-02-01T10:00:00Z",
                "attributes": {"sku_count": 3},
            },
            {
                "entity": {"type": "user", "id": "sdk_sample_3"},
                "event_type": "cart.item_added",
                "timestamp": "2026-02-01T10:00:01Z",
                # Nested objects are rejected — flatten upstream (002 §2).
                "attributes": {"item": {"sku": "A-1", "qty": 2}},
            },
        ]
    },
)
body = response.json()
print(f"accepted={body['accepted']} rejected={body['rejected']}")
for item in body["results"]:
    print(f"rejected index={item['index']} code={item['code']}")

# --- 2. the SDK catches shape violations before they leave the process --------
client = Tessera(
    base_url=os.environ["TESSERA_API_BASE"],
    ingest_url=os.environ["TESSERA_INGEST_BASE"],
)
try:
    client.events.track(
        {"type": "user", "id": "sdk_sample_3"},
        "cart.item_added",
        {"item": {"sku": "A-1", "qty": 2}},  # nested -> raises, nothing queued
    )
except TesseraValidationError as error:
    print(f"TesseraValidationError: {type(error).__name__} caught locally")

# Server-side rejections (and overflow drops) surface through on_reject and
# the FlushResult counters — see the guide for the callback signature.
client.close()
