from __future__ import annotations

from dataclasses import dataclass
from typing import AsyncIterator, Iterator

import httpx


@dataclass
class SSEEvent:
    """A parsed Server-Sent Event."""

    event: str = "message"
    data: str = ""
    id: str | None = None


class SSEDecoder:
    """Decode Server-Sent Events from an httpx streaming response.

    Handles standard SSE format:
    - `event: <type>` sets event type (default: "message")
    - `data: <payload>` sets event data (multiple data lines are joined with \\n)
    - `id: <id>` sets event ID
    - Empty line delimits events
    - Lines starting with `:` are comments (ignored)
    """

    def iter_events(self, response: httpx.Response) -> Iterator[SSEEvent]:
        """Synchronous iteration over SSE events."""
        event_type = "message"
        data_lines: list[str] = []
        event_id: str | None = None

        for line in response.iter_lines():
            if not line:
                # Empty line = event boundary
                if data_lines:
                    yield SSEEvent(
                        event=event_type,
                        data="\n".join(data_lines),
                        id=event_id,
                    )
                event_type = "message"
                data_lines = []
                event_id = None
                continue

            if line.startswith(":"):
                # Comment — ignore
                continue

            if line.startswith("event:"):
                event_type = line[6:].strip()
            elif line.startswith("data:"):
                data_lines.append(line[5:].strip())
            elif line.startswith("id:"):
                event_id = line[3:].strip()

        # Flush any remaining event
        if data_lines:
            yield SSEEvent(
                event=event_type,
                data="\n".join(data_lines),
                id=event_id,
            )

    async def aiter_events(self, response: httpx.Response) -> AsyncIterator[SSEEvent]:
        """Async iteration over SSE events."""
        event_type = "message"
        data_lines: list[str] = []
        event_id: str | None = None

        async for line in response.aiter_lines():
            if not line:
                if data_lines:
                    yield SSEEvent(
                        event=event_type,
                        data="\n".join(data_lines),
                        id=event_id,
                    )
                event_type = "message"
                data_lines = []
                event_id = None
                continue

            if line.startswith(":"):
                continue

            if line.startswith("event:"):
                event_type = line[6:].strip()
            elif line.startswith("data:"):
                data_lines.append(line[5:].strip())
            elif line.startswith("id:"):
                event_id = line[3:].strip()

        if data_lines:
            yield SSEEvent(
                event=event_type,
                data="\n".join(data_lines),
                id=event_id,
            )
