"""Auto-generated SFU event dataclasses. Do not edit manually."""

# Generated by _generate_sfu_events.py
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional

from dataclasses_json import DataClassJsonMixin
from google.protobuf.json_format import MessageToDict
from getstream.video.rtc.pb.stream.video.sfu.event import events_pb2
from vision_agents.core.events.base import BaseEvent

# Note: For enum fields typed as 'int', use the corresponding enum from:
# getstream.video.rtc.pb.stream.video.sfu.models.models_pb2
# Available enums: TrackType, ConnectionQuality, ErrorCode, PeerType, etc.


def _to_dict(message) -> Dict[str, Any]:
    try:
        return MessageToDict(message, preserving_proto_field_name=True)
    except Exception:
        return {}


# ==============================================================================
# Message Type Wrappers
# These are wrappers for protobuf message types used in events
# ==============================================================================


@dataclass
class Browser(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Browser."""

    name: Optional[str] = None
    version: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Browser":
        """Create from protobuf Browser."""
        if proto_obj is None:
            return cls()
        return cls(name=proto_obj.name, version=proto_obj.version)


@dataclass
class CallGrants(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.CallGrants."""

    can_publish_audio: Optional[bool] = None
    can_publish_video: Optional[bool] = None
    can_screenshare: Optional[bool] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "CallGrants":
        """Create from protobuf CallGrants."""
        if proto_obj is None:
            return cls()
        return cls(
            can_publish_audio=proto_obj.can_publish_audio,
            can_publish_video=proto_obj.can_publish_video,
            can_screenshare=proto_obj.can_screenshare,
        )


@dataclass
class CallState(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.CallState."""

    participants: Optional[List[Participant]] = None
    started_at: Optional[Any] = None
    participant_count: Optional[ParticipantCount] = None
    pins: Optional[List[Pin]] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "CallState":
        """Create from protobuf CallState."""
        if proto_obj is None:
            return cls()
        return cls(
            participants=[
                Participant.from_proto(item) for item in proto_obj.participants
            ],
            started_at=proto_obj.started_at
            if proto_obj.HasField("started_at")
            else None,
            participant_count=ParticipantCount.from_proto(proto_obj.participant_count)
            if proto_obj.HasField("participant_count")
            else None,
            pins=[Pin.from_proto(item) for item in proto_obj.pins],
        )


@dataclass
class ClientDetails(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.ClientDetails."""

    sdk: Optional[Sdk] = None
    os: Optional[OS] = None
    browser: Optional[Browser] = None
    device: Optional[Device] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "ClientDetails":
        """Create from protobuf ClientDetails."""
        if proto_obj is None:
            return cls()
        return cls(
            sdk=Sdk.from_proto(proto_obj.sdk) if proto_obj.HasField("sdk") else None,
            os=OS.from_proto(proto_obj.os) if proto_obj.HasField("os") else None,
            browser=Browser.from_proto(proto_obj.browser)
            if proto_obj.HasField("browser")
            else None,
            device=Device.from_proto(proto_obj.device)
            if proto_obj.HasField("device")
            else None,
        )


@dataclass
class Codec(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Codec."""

    payload_type: Optional[int] = None
    name: Optional[str] = None
    clock_rate: Optional[int] = None
    encoding_parameters: Optional[str] = None
    fmtp: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Codec":
        """Create from protobuf Codec."""
        if proto_obj is None:
            return cls()
        return cls(
            payload_type=proto_obj.payload_type,
            name=proto_obj.name,
            clock_rate=proto_obj.clock_rate,
            encoding_parameters=proto_obj.encoding_parameters,
            fmtp=proto_obj.fmtp,
        )


@dataclass
class Device(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Device."""

    name: Optional[str] = None
    version: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Device":
        """Create from protobuf Device."""
        if proto_obj is None:
            return cls()
        return cls(name=proto_obj.name, version=proto_obj.version)


@dataclass
class Error(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Error.

    Enum fields (use values from models_pb2):
        - code: ErrorCode
    """

    code: Optional[int] = None
    message: Optional[str] = None
    should_retry: Optional[bool] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Error":
        """Create from protobuf Error."""
        if proto_obj is None:
            return cls()
        return cls(
            code=proto_obj.code,
            message=proto_obj.message,
            should_retry=proto_obj.should_retry,
        )


@dataclass
class ICETrickle(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.ICETrickle.

    Enum fields (use values from models_pb2):
        - peer_type: PeerType
    """

    peer_type: Optional[int] = None
    ice_candidate: Optional[str] = None
    session_id: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "ICETrickle":
        """Create from protobuf ICETrickle."""
        if proto_obj is None:
            return cls()
        return cls(
            peer_type=proto_obj.peer_type,
            ice_candidate=proto_obj.ice_candidate,
            session_id=proto_obj.session_id,
        )


@dataclass
class OS(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.OS."""

    name: Optional[str] = None
    version: Optional[str] = None
    architecture: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "OS":
        """Create from protobuf OS."""
        if proto_obj is None:
            return cls()
        return cls(
            name=proto_obj.name,
            version=proto_obj.version,
            architecture=proto_obj.architecture,
        )


@dataclass
class Participant(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Participant.

    Enum fields (use values from models_pb2):
        - published_tracks: TrackType
        - connection_quality: ConnectionQuality
    """

    user_id: Optional[str] = None
    session_id: Optional[str] = None
    published_tracks: Optional[List[int]] = None
    joined_at: Optional[Any] = None
    track_lookup_prefix: Optional[str] = None
    connection_quality: Optional[int] = None
    is_speaking: Optional[bool] = None
    is_dominant_speaker: Optional[bool] = None
    audio_level: Optional[float] = None
    name: Optional[str] = None
    image: Optional[str] = None
    custom: Optional[Any] = None
    roles: Optional[List[str]] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Participant":
        """Create from protobuf Participant."""
        if proto_obj is None:
            return cls()
        return cls(
            user_id=proto_obj.user_id,
            session_id=proto_obj.session_id,
            published_tracks=list(proto_obj.published_tracks),
            joined_at=proto_obj.joined_at if proto_obj.HasField("joined_at") else None,
            track_lookup_prefix=proto_obj.track_lookup_prefix,
            connection_quality=proto_obj.connection_quality,
            is_speaking=proto_obj.is_speaking,
            is_dominant_speaker=proto_obj.is_dominant_speaker,
            audio_level=proto_obj.audio_level,
            name=proto_obj.name,
            image=proto_obj.image,
            custom=proto_obj.custom if proto_obj.HasField("custom") else None,
            roles=list(proto_obj.roles),
        )


@dataclass
class ParticipantCount(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.ParticipantCount."""

    total: Optional[int] = None
    anonymous: Optional[int] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "ParticipantCount":
        """Create from protobuf ParticipantCount."""
        if proto_obj is None:
            return cls()
        return cls(total=proto_obj.total, anonymous=proto_obj.anonymous)


@dataclass
class Pin(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Pin."""

    user_id: Optional[str] = None
    session_id: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Pin":
        """Create from protobuf Pin."""
        if proto_obj is None:
            return cls()
        return cls(user_id=proto_obj.user_id, session_id=proto_obj.session_id)


@dataclass
class PublishOption(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.PublishOption.

    Enum fields (use values from models_pb2):
        - track_type: TrackType
    """

    track_type: Optional[int] = None
    codec: Optional[Codec] = None
    bitrate: Optional[int] = None
    fps: Optional[int] = None
    max_spatial_layers: Optional[int] = None
    max_temporal_layers: Optional[int] = None
    video_dimension: Optional[VideoDimension] = None
    id: Optional[int] = None
    use_single_layer: Optional[bool] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "PublishOption":
        """Create from protobuf PublishOption."""
        if proto_obj is None:
            return cls()
        return cls(
            track_type=proto_obj.track_type,
            codec=Codec.from_proto(proto_obj.codec)
            if proto_obj.HasField("codec")
            else None,
            bitrate=proto_obj.bitrate,
            fps=proto_obj.fps,
            max_spatial_layers=proto_obj.max_spatial_layers,
            max_temporal_layers=proto_obj.max_temporal_layers,
            video_dimension=VideoDimension.from_proto(proto_obj.video_dimension)
            if proto_obj.HasField("video_dimension")
            else None,
            id=proto_obj.id,
            use_single_layer=proto_obj.use_single_layer,
        )


@dataclass
class Sdk(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.Sdk.

    Enum fields (use values from models_pb2):
        - type: SdkType
    """

    type: Optional[int] = None
    major: Optional[str] = None
    minor: Optional[str] = None
    patch: Optional[str] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "Sdk":
        """Create from protobuf Sdk."""
        if proto_obj is None:
            return cls()
        return cls(
            type=proto_obj.type,
            major=proto_obj.major,
            minor=proto_obj.minor,
            patch=proto_obj.patch,
        )


@dataclass
class SubscribeOption(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.SubscribeOption.

    Enum fields (use values from models_pb2):
        - track_type: TrackType
    """

    track_type: Optional[int] = None
    codecs: Optional[List[Codec]] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "SubscribeOption":
        """Create from protobuf SubscribeOption."""
        if proto_obj is None:
            return cls()
        return cls(
            track_type=proto_obj.track_type,
            codecs=[Codec.from_proto(item) for item in proto_obj.codecs],
        )


@dataclass
class TrackInfo(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.TrackInfo.

    Enum fields (use values from models_pb2):
        - track_type: TrackType
    """

    track_id: Optional[str] = None
    track_type: Optional[int] = None
    layers: Optional[List[VideoLayer]] = None
    mid: Optional[str] = None
    dtx: Optional[bool] = None
    stereo: Optional[bool] = None
    red: Optional[bool] = None
    muted: Optional[bool] = None
    codec: Optional[Codec] = None
    publish_option_id: Optional[int] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "TrackInfo":
        """Create from protobuf TrackInfo."""
        if proto_obj is None:
            return cls()
        return cls(
            track_id=proto_obj.track_id,
            track_type=proto_obj.track_type,
            layers=[VideoLayer.from_proto(item) for item in proto_obj.layers],
            mid=proto_obj.mid,
            dtx=proto_obj.dtx,
            stereo=proto_obj.stereo,
            red=proto_obj.red,
            muted=proto_obj.muted,
            codec=Codec.from_proto(proto_obj.codec)
            if proto_obj.HasField("codec")
            else None,
            publish_option_id=proto_obj.publish_option_id,
        )


@dataclass
class VideoDimension(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.VideoDimension."""

    width: Optional[int] = None
    height: Optional[int] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "VideoDimension":
        """Create from protobuf VideoDimension."""
        if proto_obj is None:
            return cls()
        return cls(width=proto_obj.width, height=proto_obj.height)


@dataclass
class VideoLayer(DataClassJsonMixin):
    """Wrapper for stream.video.sfu.models.VideoLayer.

    Enum fields (use values from models_pb2):
        - quality: VideoQuality
    """

    rid: Optional[str] = None
    video_dimension: Optional[VideoDimension] = None
    bitrate: Optional[int] = None
    fps: Optional[int] = None
    quality: Optional[int] = None

    @classmethod
    def from_proto(cls, proto_obj) -> "VideoLayer":
        """Create from protobuf VideoLayer."""
        if proto_obj is None:
            return cls()
        return cls(
            rid=proto_obj.rid,
            video_dimension=VideoDimension.from_proto(proto_obj.video_dimension)
            if proto_obj.HasField("video_dimension")
            else None,
            bitrate=proto_obj.bitrate,
            fps=proto_obj.fps,
            quality=proto_obj.quality,
        )


# ==============================================================================
# Event Classes
# ==============================================================================


@dataclass
class AudioLevelEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.AudioLevel."""

    type: str = field(default="stream.video.sfu.event.AudioLevel", init=False)
    payload: Optional[events_pb2.AudioLevel] = field(default=None, repr=False)

    @property
    def user_id(self) -> Optional[str]:  # type: ignore[override]
        """Access user_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "user_id", None)

    @property
    def level(self) -> Optional[float]:
        """Access level field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "level", None)

    @property
    def is_speaking(self) -> Optional[bool]:
        """Access is_speaking field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "is_speaking", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.AudioLevel, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class AudioLevelChangedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.AudioLevelChanged."""

    type: str = field(default="stream.video.sfu.event.AudioLevelChanged", init=False)
    payload: Optional[events_pb2.AudioLevelChanged] = field(default=None, repr=False)

    @property
    def audio_levels(self) -> Optional[List[Any]]:
        """Access audio_levels field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "audio_levels", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.AudioLevelChanged, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class AudioSenderEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.AudioSender."""

    type: str = field(default="stream.video.sfu.event.AudioSender", init=False)
    payload: Optional[events_pb2.AudioSender] = field(default=None, repr=False)

    @property
    def codec(self) -> Optional[Codec]:
        """Access codec field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "codec", None)
        return Codec.from_proto(proto_val) if proto_val is not None else None

    @property
    def track_type(self) -> Optional[int]:
        """Access track_type field from the protobuf payload. Use models_pb2.TrackType enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "track_type", None)

    @property
    def publish_option_id(self) -> Optional[int]:
        """Access publish_option_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "publish_option_id", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.AudioSender, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class CallEndedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.CallEnded."""

    type: str = field(default="stream.video.sfu.event.CallEnded", init=False)
    payload: Optional[events_pb2.CallEnded] = field(default=None, repr=False)

    @property
    def reason(self) -> Optional[int]:
        """Access reason field from the protobuf payload. Use models_pb2.CallEndedReason enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reason", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.CallEnded, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class CallGrantsUpdatedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.CallGrantsUpdated."""

    type: str = field(default="stream.video.sfu.event.CallGrantsUpdated", init=False)
    payload: Optional[events_pb2.CallGrantsUpdated] = field(default=None, repr=False)

    @property
    def current_grants(self) -> Optional[CallGrants]:
        """Access current_grants field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "current_grants", None)
        return CallGrants.from_proto(proto_val) if proto_val is not None else None

    @property
    def message(self) -> Optional[str]:
        """Access message field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "message", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.CallGrantsUpdated, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ChangePublishOptionsEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ChangePublishOptions."""

    type: str = field(default="stream.video.sfu.event.ChangePublishOptions", init=False)
    payload: Optional[events_pb2.ChangePublishOptions] = field(default=None, repr=False)

    @property
    def publish_options(self) -> Optional[List[PublishOption]]:
        """Access publish_options field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "publish_options", [])
        return (
            [PublishOption.from_proto(item) for item in proto_list]
            if proto_list
            else None
        )

    @property
    def reason(self) -> Optional[str]:
        """Access reason field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reason", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ChangePublishOptions, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ChangePublishOptionsCompleteEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ChangePublishOptionsComplete."""

    type: str = field(
        default="stream.video.sfu.event.ChangePublishOptionsComplete", init=False
    )
    payload: Optional[events_pb2.ChangePublishOptionsComplete] = field(
        default=None, repr=False
    )

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ChangePublishOptionsComplete, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ChangePublishQualityEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ChangePublishQuality."""

    type: str = field(default="stream.video.sfu.event.ChangePublishQuality", init=False)
    payload: Optional[events_pb2.ChangePublishQuality] = field(default=None, repr=False)

    @property
    def audio_senders(self) -> Optional[List[Any]]:
        """Access audio_senders field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "audio_senders", None)

    @property
    def video_senders(self) -> Optional[List[Any]]:
        """Access video_senders field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "video_senders", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ChangePublishQuality, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ConnectionQualityChangedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ConnectionQualityChanged."""

    type: str = field(
        default="stream.video.sfu.event.ConnectionQualityChanged", init=False
    )
    payload: Optional[events_pb2.ConnectionQualityChanged] = field(
        default=None, repr=False
    )

    @property
    def connection_quality_updates(self) -> Optional[List[Any]]:
        """Access connection_quality_updates field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "connection_quality_updates", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ConnectionQualityChanged, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ConnectionQualityInfoEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ConnectionQualityInfo."""

    type: str = field(
        default="stream.video.sfu.event.ConnectionQualityInfo", init=False
    )
    payload: Optional[events_pb2.ConnectionQualityInfo] = field(
        default=None, repr=False
    )

    @property
    def user_id(self) -> Optional[str]:  # type: ignore[override]
        """Access user_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "user_id", None)

    @property
    def connection_quality(self) -> Optional[int]:
        """Access connection_quality field from the protobuf payload. Use models_pb2.ConnectionQuality enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "connection_quality", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ConnectionQualityInfo, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class DominantSpeakerChangedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.DominantSpeakerChanged."""

    type: str = field(
        default="stream.video.sfu.event.DominantSpeakerChanged", init=False
    )
    payload: Optional[events_pb2.DominantSpeakerChanged] = field(
        default=None, repr=False
    )

    @property
    def user_id(self) -> Optional[str]:  # type: ignore[override]
        """Access user_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "user_id", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.DominantSpeakerChanged, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ErrorEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.Error."""

    type: str = field(default="stream.video.sfu.event.Error", init=False)
    payload: Optional[events_pb2.Error] = field(default=None, repr=False)

    @property
    def error(self) -> Optional[Error]:
        """Access error field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "error", None)
        return Error.from_proto(proto_val) if proto_val is not None else None

    @property
    def reconnect_strategy(self) -> Optional[int]:
        """Access reconnect_strategy field from the protobuf payload. Use models_pb2.WebsocketReconnectStrategy enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reconnect_strategy", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.Error, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class GoAwayEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.GoAway."""

    type: str = field(default="stream.video.sfu.event.GoAway", init=False)
    payload: Optional[events_pb2.GoAway] = field(default=None, repr=False)

    @property
    def reason(self) -> Optional[int]:
        """Access reason field from the protobuf payload. Use models_pb2.GoAwayReason enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reason", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.GoAway, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class HealthCheckRequestEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.HealthCheckRequest."""

    type: str = field(default="stream.video.sfu.event.HealthCheckRequest", init=False)
    payload: Optional[events_pb2.HealthCheckRequest] = field(default=None, repr=False)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.HealthCheckRequest, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class HealthCheckResponseEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.HealthCheckResponse."""

    type: str = field(default="stream.video.sfu.event.HealthCheckResponse", init=False)
    payload: Optional[events_pb2.HealthCheckResponse] = field(default=None, repr=False)

    @property
    def participant_count(self) -> Optional[ParticipantCount]:
        """Access participant_count field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "participant_count", None)
        return ParticipantCount.from_proto(proto_val) if proto_val is not None else None

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.HealthCheckResponse, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ICERestartEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ICERestart."""

    type: str = field(default="stream.video.sfu.event.ICERestart", init=False)
    payload: Optional[events_pb2.ICERestart] = field(default=None, repr=False)

    @property
    def peer_type(self) -> Optional[int]:
        """Access peer_type field from the protobuf payload. Use models_pb2.PeerType enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "peer_type", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ICERestart, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ICETrickleEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ICETrickle."""

    type: str = field(default="stream.video.sfu.event.ICETrickle", init=False)
    payload: Optional[events_pb2.ICETrickle] = field(default=None, repr=False)

    @property
    def peer_type(self) -> Optional[int]:
        """Access peer_type field from the protobuf payload. Use models_pb2.PeerType enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "peer_type", None)

    @property
    def ice_candidate(self) -> Optional[str]:
        """Access ice_candidate field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "ice_candidate", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ICETrickle, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class InboundStateNotificationEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.InboundStateNotification."""

    type: str = field(
        default="stream.video.sfu.event.InboundStateNotification", init=False
    )
    payload: Optional[events_pb2.InboundStateNotification] = field(
        default=None, repr=False
    )

    @property
    def inbound_video_states(self) -> Optional[List[Any]]:
        """Access inbound_video_states field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "inbound_video_states", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.InboundStateNotification, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class InboundVideoStateEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.InboundVideoState."""

    type: str = field(default="stream.video.sfu.event.InboundVideoState", init=False)
    payload: Optional[events_pb2.InboundVideoState] = field(default=None, repr=False)

    @property
    def user_id(self) -> Optional[str]:  # type: ignore[override]
        """Access user_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "user_id", None)

    @property
    def track_type(self) -> Optional[int]:
        """Access track_type field from the protobuf payload. Use models_pb2.TrackType enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "track_type", None)

    @property
    def paused(self) -> Optional[bool]:
        """Access paused field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "paused", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.InboundVideoState, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class JoinRequestEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.JoinRequest."""

    type: str = field(default="stream.video.sfu.event.JoinRequest", init=False)
    payload: Optional[events_pb2.JoinRequest] = field(default=None, repr=False)

    @property
    def token(self) -> Optional[str]:
        """Access token field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "token", None)

    @property
    def subscriber_sdp(self) -> Optional[str]:
        """Access subscriber_sdp field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "subscriber_sdp", None)

    @property
    def publisher_sdp(self) -> Optional[str]:
        """Access publisher_sdp field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "publisher_sdp", None)

    @property
    def client_details(self) -> Optional[ClientDetails]:
        """Access client_details field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "client_details", None)
        return ClientDetails.from_proto(proto_val) if proto_val is not None else None

    @property
    def migration(self) -> Optional[Any]:
        """Access migration field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "migration", None)

    @property
    def fast_reconnect(self) -> Optional[bool]:
        """Access fast_reconnect field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "fast_reconnect", None)

    @property
    def reconnect_details(self) -> Optional[Any]:
        """Access reconnect_details field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reconnect_details", None)

    @property
    def preferred_publish_options(self) -> Optional[List[PublishOption]]:
        """Access preferred_publish_options field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "preferred_publish_options", [])
        return (
            [PublishOption.from_proto(item) for item in proto_list]
            if proto_list
            else None
        )

    @property
    def preferred_subscribe_options(self) -> Optional[List[SubscribeOption]]:
        """Access preferred_subscribe_options field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "preferred_subscribe_options", [])
        return (
            [SubscribeOption.from_proto(item) for item in proto_list]
            if proto_list
            else None
        )

    @property
    def capabilities(self) -> Optional[List[int]]:
        """Access capabilities field from the protobuf payload. Use models_pb2.ClientCapability enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "capabilities", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.JoinRequest, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class JoinResponseEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.JoinResponse."""

    type: str = field(default="stream.video.sfu.event.JoinResponse", init=False)
    payload: Optional[events_pb2.JoinResponse] = field(default=None, repr=False)

    @property
    def call_state(self) -> Optional[CallState]:
        """Access call_state field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "call_state", None)
        return CallState.from_proto(proto_val) if proto_val is not None else None

    @property
    def reconnected(self) -> Optional[bool]:
        """Access reconnected field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reconnected", None)

    @property
    def fast_reconnect_deadline_seconds(self) -> Optional[int]:
        """Access fast_reconnect_deadline_seconds field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "fast_reconnect_deadline_seconds", None)

    @property
    def publish_options(self) -> Optional[List[PublishOption]]:
        """Access publish_options field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "publish_options", [])
        return (
            [PublishOption.from_proto(item) for item in proto_list]
            if proto_list
            else None
        )

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.JoinResponse, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class LeaveCallRequestEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.LeaveCallRequest."""

    type: str = field(default="stream.video.sfu.event.LeaveCallRequest", init=False)
    payload: Optional[events_pb2.LeaveCallRequest] = field(default=None, repr=False)

    @property
    def reason(self) -> Optional[str]:
        """Access reason field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reason", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.LeaveCallRequest, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class MigrationEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.Migration."""

    type: str = field(default="stream.video.sfu.event.Migration", init=False)
    payload: Optional[events_pb2.Migration] = field(default=None, repr=False)

    @property
    def from_sfu_id(self) -> Optional[str]:
        """Access from_sfu_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "from_sfu_id", None)

    @property
    def announced_tracks(self) -> Optional[List[TrackInfo]]:
        """Access announced_tracks field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "announced_tracks", [])
        return (
            [TrackInfo.from_proto(item) for item in proto_list] if proto_list else None
        )

    @property
    def subscriptions(self) -> Optional[List[Any]]:
        """Access subscriptions field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "subscriptions", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.Migration, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ParticipantJoinedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ParticipantJoined."""

    type: str = field(default="stream.video.sfu.event.ParticipantJoined", init=False)
    payload: Optional[events_pb2.ParticipantJoined] = field(default=None, repr=False)
    _participant: Optional[Participant] = field(init=False, default=None, repr=False)

    @property
    def call_cid(self) -> Optional[str]:
        """Access call_cid field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "call_cid", None)

    @property  # type: ignore[misc]
    def participant(self) -> Optional[Participant]:  # type: ignore[override]
        """Access participant field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "participant", None)
        return Participant.from_proto(proto_val) if proto_val is not None else None
    
    @participant.setter  # type: ignore[misc]
    def participant(self, value: Optional[Participant]) -> None:
        """Setter for participant to satisfy dataclass __init__."""
        # Store in _participant but don't use it (payload takes precedence)
        self._participant = value

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ParticipantJoined, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ParticipantLeftEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ParticipantLeft."""

    type: str = field(default="stream.video.sfu.event.ParticipantLeft", init=False)
    payload: Optional[events_pb2.ParticipantLeft] = field(default=None, repr=False)
    _participant: Optional[Participant] = field(init=False, default=None, repr=False)

    @property
    def call_cid(self) -> Optional[str]:
        """Access call_cid field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "call_cid", None)

    @property  # type: ignore[misc]
    def participant(self) -> Optional[Participant]:  # type: ignore[override]
        """Access participant field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "participant", None)
        return Participant.from_proto(proto_val) if proto_val is not None else None
    
    @participant.setter  # type: ignore[misc]
    def participant(self, value: Optional[Participant]) -> None:
        """Setter for participant to satisfy dataclass __init__."""
        # Store in _participant but don't use it (payload takes precedence)
        self._participant = value

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ParticipantLeft, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ParticipantMigrationCompleteEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ParticipantMigrationComplete."""

    type: str = field(
        default="stream.video.sfu.event.ParticipantMigrationComplete", init=False
    )
    payload: Optional[events_pb2.ParticipantMigrationComplete] = field(
        default=None, repr=False
    )

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ParticipantMigrationComplete, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ParticipantUpdatedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ParticipantUpdated."""

    type: str = field(default="stream.video.sfu.event.ParticipantUpdated", init=False)
    payload: Optional[events_pb2.ParticipantUpdated] = field(default=None, repr=False)
    _participant: Optional[Participant] = field(init=False, default=None, repr=False)

    @property
    def call_cid(self) -> Optional[str]:
        """Access call_cid field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "call_cid", None)

    @property  # type: ignore[misc]
    def participant(self) -> Optional[Participant]:  # type: ignore[override]
        """Access participant field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "participant", None)
        return Participant.from_proto(proto_val) if proto_val is not None else None
    
    @participant.setter  # type: ignore[misc]
    def participant(self, value: Optional[Participant]) -> None:
        """Setter for participant to satisfy dataclass __init__."""
        # Store in _participant but don't use it (payload takes precedence)
        self._participant = value

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ParticipantUpdated, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class PinsChangedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.PinsChanged."""

    type: str = field(default="stream.video.sfu.event.PinsChanged", init=False)
    payload: Optional[events_pb2.PinsChanged] = field(default=None, repr=False)

    @property
    def pins(self) -> Optional[List[Pin]]:
        """Access pins field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "pins", [])
        return [Pin.from_proto(item) for item in proto_list] if proto_list else None

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.PinsChanged, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class PublisherAnswerEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.PublisherAnswer."""

    type: str = field(default="stream.video.sfu.event.PublisherAnswer", init=False)
    payload: Optional[events_pb2.PublisherAnswer] = field(default=None, repr=False)

    @property
    def sdp(self) -> Optional[str]:
        """Access sdp field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "sdp", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.PublisherAnswer, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class ReconnectDetailsEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.ReconnectDetails."""

    type: str = field(default="stream.video.sfu.event.ReconnectDetails", init=False)
    payload: Optional[events_pb2.ReconnectDetails] = field(default=None, repr=False)

    @property
    def strategy(self) -> Optional[int]:
        """Access strategy field from the protobuf payload. Use models_pb2.WebsocketReconnectStrategy enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "strategy", None)

    @property
    def announced_tracks(self) -> Optional[List[TrackInfo]]:
        """Access announced_tracks field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_list = getattr(self.payload, "announced_tracks", [])
        return (
            [TrackInfo.from_proto(item) for item in proto_list] if proto_list else None
        )

    @property
    def subscriptions(self) -> Optional[List[Any]]:
        """Access subscriptions field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "subscriptions", None)

    @property
    def reconnect_attempt(self) -> Optional[int]:
        """Access reconnect_attempt field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reconnect_attempt", None)

    @property
    def from_sfu_id(self) -> Optional[str]:
        """Access from_sfu_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "from_sfu_id", None)

    @property
    def previous_session_id(self) -> Optional[str]:
        """Access previous_session_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "previous_session_id", None)

    @property
    def reason(self) -> Optional[str]:
        """Access reason field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "reason", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.ReconnectDetails, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class SfuEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.SfuEvent."""

    type: str = field(default="stream.video.sfu.event.SfuEvent", init=False)
    payload: Optional[events_pb2.SfuEvent] = field(default=None, repr=False)

    @property
    def subscriber_offer(self) -> Optional[Any]:
        """Access subscriber_offer field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "subscriber_offer", None)

    @property
    def publisher_answer(self) -> Optional[Any]:
        """Access publisher_answer field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "publisher_answer", None)

    @property
    def connection_quality_changed(self) -> Optional[Any]:
        """Access connection_quality_changed field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "connection_quality_changed", None)

    @property
    def audio_level_changed(self) -> Optional[Any]:
        """Access audio_level_changed field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "audio_level_changed", None)

    @property
    def ice_trickle(self) -> Optional[ICETrickle]:
        """Access ice_trickle field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "ice_trickle", None)
        return ICETrickle.from_proto(proto_val) if proto_val is not None else None

    @property
    def change_publish_quality(self) -> Optional[Any]:
        """Access change_publish_quality field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "change_publish_quality", None)

    @property
    def participant_joined(self) -> Optional[Any]:
        """Access participant_joined field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "participant_joined", None)

    @property
    def participant_left(self) -> Optional[Any]:
        """Access participant_left field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "participant_left", None)

    @property
    def dominant_speaker_changed(self) -> Optional[Any]:
        """Access dominant_speaker_changed field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "dominant_speaker_changed", None)

    @property
    def join_response(self) -> Optional[Any]:
        """Access join_response field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "join_response", None)

    @property
    def health_check_response(self) -> Optional[Any]:
        """Access health_check_response field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "health_check_response", None)

    @property
    def track_published(self) -> Optional[Any]:
        """Access track_published field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "track_published", None)

    @property
    def track_unpublished(self) -> Optional[Any]:
        """Access track_unpublished field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "track_unpublished", None)

    @property
    def error(self) -> Optional[Any]:
        """Access error field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "error", None)

    @property
    def call_grants_updated(self) -> Optional[Any]:
        """Access call_grants_updated field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "call_grants_updated", None)

    @property
    def go_away(self) -> Optional[Any]:
        """Access go_away field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "go_away", None)

    @property
    def ice_restart(self) -> Optional[Any]:
        """Access ice_restart field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "ice_restart", None)

    @property
    def pins_updated(self) -> Optional[Any]:
        """Access pins_updated field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "pins_updated", None)

    @property
    def call_ended(self) -> Optional[Any]:
        """Access call_ended field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "call_ended", None)

    @property
    def participant_updated(self) -> Optional[Any]:
        """Access participant_updated field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "participant_updated", None)

    @property
    def participant_migration_complete(self) -> Optional[Any]:
        """Access participant_migration_complete field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "participant_migration_complete", None)

    @property
    def change_publish_options(self) -> Optional[Any]:
        """Access change_publish_options field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "change_publish_options", None)

    @property
    def inbound_state_notification(self) -> Optional[Any]:
        """Access inbound_state_notification field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "inbound_state_notification", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.SfuEvent, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class SfuRequestEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.SfuRequest."""

    type: str = field(default="stream.video.sfu.event.SfuRequest", init=False)
    payload: Optional[events_pb2.SfuRequest] = field(default=None, repr=False)

    @property
    def join_request(self) -> Optional[Any]:
        """Access join_request field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "join_request", None)

    @property
    def health_check_request(self) -> Optional[Any]:
        """Access health_check_request field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "health_check_request", None)

    @property
    def leave_call_request(self) -> Optional[Any]:
        """Access leave_call_request field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "leave_call_request", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.SfuRequest, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class SubscriberOfferEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.SubscriberOffer."""

    type: str = field(default="stream.video.sfu.event.SubscriberOffer", init=False)
    payload: Optional[events_pb2.SubscriberOffer] = field(default=None, repr=False)

    @property
    def ice_restart(self) -> Optional[bool]:
        """Access ice_restart field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "ice_restart", None)

    @property
    def sdp(self) -> Optional[str]:
        """Access sdp field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "sdp", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.SubscriberOffer, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class TrackPublishedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.TrackPublished."""

    type: str = field(default="stream.video.sfu.event.TrackPublished", init=False)
    payload: Optional[events_pb2.TrackPublished] = field(default=None, repr=False)
    _participant: Optional[Participant] = field(init=False, default=None, repr=False)

    @property
    def user_id(self) -> Optional[str]:  # type: ignore[override]
        """Access user_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "user_id", None)

    @property  # type: ignore[misc]
    def participant(self) -> Optional[Participant]:  # type: ignore[override]
        """Access participant field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "participant", None)
        return Participant.from_proto(proto_val) if proto_val is not None else None
    
    @participant.setter  # type: ignore[misc]
    def participant(self, value: Optional[Participant]) -> None:
        """Setter for participant to satisfy dataclass __init__."""
        # Store in _participant but don't use it (payload takes precedence)
        self._participant = value

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.TrackPublished, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class TrackUnpublishedEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.TrackUnpublished."""

    type: str = field(default="stream.video.sfu.event.TrackUnpublished", init=False)
    payload: Optional[events_pb2.TrackUnpublished] = field(default=None, repr=False)
    _participant: Optional[Participant] = field(init=False, default=None, repr=False)

    @property
    def user_id(self) -> Optional[str]:  # type: ignore[override]
        """Access user_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "user_id", None)

    @property
    def cause(self) -> Optional[int]:
        """Access cause field from the protobuf payload. Use models_pb2.TrackUnpublishReason enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "cause", None)

    @property  # type: ignore[misc]
    def participant(self) -> Optional[Participant]:  # type: ignore[override]
        """Access participant field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "participant", None)
        return Participant.from_proto(proto_val) if proto_val is not None else None
    
    @participant.setter  # type: ignore[misc]
    def participant(self, value: Optional[Participant]) -> None:
        """Setter for participant to satisfy dataclass __init__."""
        # Store in _participant but don't use it (payload takes precedence)
        self._participant = value

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.TrackUnpublished, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class VideoLayerSettingEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.VideoLayerSetting."""

    type: str = field(default="stream.video.sfu.event.VideoLayerSetting", init=False)
    payload: Optional[events_pb2.VideoLayerSetting] = field(default=None, repr=False)

    @property
    def name(self) -> Optional[str]:
        """Access name field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "name", None)

    @property
    def active(self) -> Optional[bool]:
        """Access active field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "active", None)

    @property
    def max_bitrate(self) -> Optional[int]:
        """Access max_bitrate field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "max_bitrate", None)

    @property
    def scale_resolution_down_by(self) -> Optional[float]:
        """Access scale_resolution_down_by field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "scale_resolution_down_by", None)

    @property
    def codec(self) -> Optional[Codec]:
        """Access codec field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "codec", None)
        return Codec.from_proto(proto_val) if proto_val is not None else None

    @property
    def max_framerate(self) -> Optional[int]:
        """Access max_framerate field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "max_framerate", None)

    @property
    def scalability_mode(self) -> Optional[str]:
        """Access scalability_mode field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "scalability_mode", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.VideoLayerSetting, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


@dataclass
class VideoSenderEvent(BaseEvent):
    """Dataclass event for video.sfu.event.events_pb2.VideoSender."""

    type: str = field(default="stream.video.sfu.event.VideoSender", init=False)
    payload: Optional[events_pb2.VideoSender] = field(default=None, repr=False)

    @property
    def codec(self) -> Optional[Codec]:
        """Access codec field from the protobuf payload."""
        if self.payload is None:
            return None
        proto_val = getattr(self.payload, "codec", None)
        return Codec.from_proto(proto_val) if proto_val is not None else None

    @property
    def layers(self) -> Optional[List[Any]]:
        """Access layers field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "layers", None)

    @property
    def track_type(self) -> Optional[int]:
        """Access track_type field from the protobuf payload. Use models_pb2.TrackType enum."""
        if self.payload is None:
            return None
        return getattr(self.payload, "track_type", None)

    @property
    def publish_option_id(self) -> Optional[int]:
        """Access publish_option_id field from the protobuf payload."""
        if self.payload is None:
            return None
        return getattr(self.payload, "publish_option_id", None)

    @classmethod
    def from_proto(cls, proto_obj: events_pb2.VideoSender, **extra):
        """Create event instance from protobuf message."""
        return cls(payload=proto_obj, **extra)

    def as_dict(self) -> Dict[str, Any]:
        """Convert protobuf payload to dictionary."""
        if self.payload is None:
            return {}
        return _to_dict(self.payload)

    def __getattr__(self, item: str):
        """Delegate attribute access to protobuf payload."""
        if self.payload is not None:
            return getattr(self.payload, item)
        raise AttributeError(
            f"'{self.__class__.__name__}' object has no attribute '{item}'"
        )


__all__ = (
    "AudioLevelEvent",
    "AudioLevelChangedEvent",
    "AudioSenderEvent",
    "CallEndedEvent",
    "CallGrantsUpdatedEvent",
    "ChangePublishOptionsEvent",
    "ChangePublishOptionsCompleteEvent",
    "ChangePublishQualityEvent",
    "ConnectionQualityChangedEvent",
    "ConnectionQualityInfoEvent",
    "DominantSpeakerChangedEvent",
    "ErrorEvent",
    "GoAwayEvent",
    "HealthCheckRequestEvent",
    "HealthCheckResponseEvent",
    "ICERestartEvent",
    "ICETrickleEvent",
    "InboundStateNotificationEvent",
    "InboundVideoStateEvent",
    "JoinRequestEvent",
    "JoinResponseEvent",
    "LeaveCallRequestEvent",
    "MigrationEvent",
    "ParticipantJoinedEvent",
    "ParticipantLeftEvent",
    "ParticipantMigrationCompleteEvent",
    "ParticipantUpdatedEvent",
    "PinsChangedEvent",
    "PublisherAnswerEvent",
    "ReconnectDetailsEvent",
    "SfuEvent",
    "SfuRequestEvent",
    "SubscriberOfferEvent",
    "TrackPublishedEvent",
    "TrackUnpublishedEvent",
    "VideoLayerSettingEvent",
    "VideoSenderEvent",
)
