# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-happens-when-an-instance-acknowledges-an-sse-event-id-it-has-not-yet-durably-committed-resumability-gaps-in-mcp-http-native-transport-with-stream.md
# Remnant Warrant:    https://corpusfetch.com/c/what-happens-when-an-instance-acknowledges-an-sse-event-id-it-has-not-yet-durably-committed-resumability-gaps-in-mcp-http-native-transport-with-stream.warrant.json
# Markdown SHA-256:   77869db3797f008d7c40d2d0cb73703ef9ad41d50e446e086312cc7be39cde4d
# Code AST SHA-256:   86ac94071570886154f521aeb0d57218cf8db3758626b9ddf65f1c801b3302fe
# Verified Classes:   ResumabilityViolation, ResumeCheck
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from __future__ import annotations

from dataclasses import dataclass


class ResumabilityViolation(RuntimeError):
    """Raised when an SSE resume cursor is not backed by durable state."""


@dataclass(frozen=True)
class ResumeCheck:
    session_id: str
    last_event_id: int
    durable_head: int


def validate_resume(check: ResumeCheck) -> int:
    """
    Enforce the invariant: Last-Event-ID must be <= durable head.
    Returns the offset to resume from (exclusive of last_event_id).
    """
    if check.last_event_id > check.durable_head:
        # The client acknowledged an ID the server never durably committed.
        # This is a resumability violation, not a client error to be 400'd.
        raise ResumabilityViolation(
            f"session={check.session_id} cursor={check.last_event_id} "
            f"exceeds durable head={check.durable_head}; "
            "client must re-sync from head, not abandon session"
        )
    if check.last_event_id < 0:
        raise ResumabilityViolation(
            f"session={check.session_id} negative cursor={check.last_event_id}"
        )
    return check.last_event_id


def assign_event_id(durable_offset: int, emitted: bool) -> int:
    """
    Commit-then-emit: the SSE id MUST be the durable offset.
    Guards against emitting an id before the write succeeded.
    """
    if not emitted and durable_offset is None:
        raise ResumabilityViolation(
            "attempted to emit id before durable commit"
        )
    return durable_offset


def resume_or_resync(check: ResumeCheck) -> tuple[int, bool]:
    """Return (resume_offset, needs_resync)."""
    try:
        return validate_resume(check), False
    except ResumabilityViolation:
        # Fall back to replaying from durable head with an explicit gap marker.
        return check.durable_head, True
