syntax = "proto3";

package hyapp.events.room.v1;

option go_package = "hyapp.local/api/proto/events/room/v1;roomeventsv1";

// EventEnvelope 是 room-service outbox 的统一事件外壳。
// body 保存具体事件消息序列化后的二进制，event_type 负责告诉消费者如何解码。
message EventEnvelope {
  string event_id = 1;
  string room_id = 2;
  string event_type = 3;
  int64 room_version = 4;
  int64 occurred_at_ms = 5;
  bytes body = 6;
  string app_code = 7;
}

// RoomCreated 表达房间第一次建立成功。
message RoomCreated {
  int64 owner_user_id = 1;
  int32 seat_count = 3;
  string mode = 4;
  // room_name/room_avatar/room_description 是创建时确定的展示资料快照，消费者不需要反查 room-service。
  string room_name = 5;
  string room_avatar = 6;
  string room_description = 7;
}

// RoomProfileUpdated 表达房间展示资料或麦位数量变更。
message RoomProfileUpdated {
  int64 actor_user_id = 1;
  string room_name = 2;
  string room_avatar = 3;
  string room_description = 4;
  int32 seat_count = 5;
  string room_background_url = 6;
}

// RoomBackgroundChanged 表达房主切换当前房间背景图。
message RoomBackgroundChanged {
  int64 actor_user_id = 1;
  int64 background_id = 2;
  string room_background_url = 3;
  RoomMediaSnapshot media = 4;
}

// RoomMediaSnapshot 固化已通过 gateway 文件头检测和 room-service 权限校验的媒体事实。
message RoomMediaSnapshot {
  string url = 1;
  string object_key = 2;
  string content_type = 3;
  string format = 4;
  int64 size_bytes = 5;
  int32 width = 6;
  int32 height = 7;
  bool animated = 8;
  int32 frame_count = 9;
  int64 duration_ms = 10;
  string poster_url = 11;
  string thumbnail_url = 12;
  string sha256 = 13;
}

// RoomDecorationChanged 表达房间级边框或彩色房名最终样式发生变化。
message RoomDecorationChanged {
  int64 actor_user_id = 1;
  string decoration_type = 2;
  int64 resource_id = 3;
  string resource_code = 4;
  string resource_type = 5;
  string name = 6;
  string asset_url = 7;
  string preview_url = 8;
  string animation_url = 9;
  string format = 10;
  string metadata_json = 11;
  repeated string text_colors = 12;
  repeated double stops = 13;
  double angle_degrees = 14;
  string entitlement_id = 15;
  int64 expires_at_ms = 16;
}

// RoomImageMessageSent 是服务端权益校验后写入 outbox 的唯一房间图片消息事实。
// message_id/event_id/command_id 都保持稳定，Flutter 以 event_id 或 message_id 去重 at-least-once 投递。
message RoomImageMessageSent {
  string message_id = 1;
  string command_id = 2;
  int64 sender_user_id = 3;
  RoomMediaSnapshot image = 4;
}

// RoomUserJoined 表达用户业务态进房成功。
message RoomEntryVehicleSnapshot {
  int64 resource_id = 1;
  string resource_code = 2;
  string name = 3;
  string asset_url = 4;
  string preview_url = 5;
  string animation_url = 6;
  string metadata_json = 7;
  string entitlement_id = 8;
  int64 expires_at_ms = 9;
}

message RoomUserJoined {
  int64 user_id = 1;
  string role = 2;
  // visible_region_id 是用户进房时所在房间的国家/区域桶，统计服务不能反查 room-service。
  int64 visible_region_id = 3;
  RoomEntryVehicleSnapshot entry_vehicle = 4;
  int64 country_id = 5;
  int64 region_id = 6;
  // is_robot 标记本次进房来自房间机器人调度，统计服务必须跳过活跃用户口径。
  bool is_robot = 7;
  // nickname/avatar/display_user_id 是进房瞬间的展示资料快照，IM 补偿投递不能再临时反查 user-service。
  string nickname = 8;
  string avatar = 9;
  string display_user_id = 10;
  string pretty_display_user_id = 11;
  // VIP 字段来自同一次 GetMyVip effective state，首次进房 outbox 与重复进房 direct IM 必须保持同一语义。
  string vip_program_type = 12;
  int32 effective_vip_level = 13;
  string effective_vip_name = 14;
  bool room_entry_notice_enabled = 15;
}

// RoomUserLeft 表达用户离房成功。
message RoomUserLeft {
  int64 user_id = 1;
}

// RoomClosed 表达房间生命周期关闭完成。
message RoomClosed {
  int64 actor_user_id = 1;
  string reason = 2;
}

// RoomBanned 表达后台持久封禁完成；区别于 closed，房主进房不能自行恢复。
message RoomBanned {
  int64 actor_user_id = 1;
  string reason = 2;
}

// RoomUnbanned 表达人工解封完成；房间只回到 closed，仍需房主正常进房后恢复。
message RoomUnbanned {
  int64 actor_user_id = 1;
  string reason = 2;
}

// RoomMicChanged 表达任意上下麦和换麦位动作。
message RoomMicChanged {
  int64 actor_user_id = 1;
  int64 target_user_id = 2;
  int32 from_seat = 3;
  int32 to_seat = 4;
  string action = 5;
  // mic_session_id 用于把业务麦位事件和 RTC 发流会话绑定，客户端和 webhook 都必须透传。
  string mic_session_id = 6;
  // publish_state 透出 pending_publish/publishing/idle，避免把“占麦”和“已发流”混成一个状态。
  string publish_state = 7;
  // reason 表示系统触发的下麦原因，例如 publish_timeout。
  string reason = 8;
  int64 publish_deadline_ms = 9;
  int64 publish_event_time_ms = 10;
  bool mic_muted = 11;
  string seat_status = 12;
  int64 target_gift_value = 13;
  // target_* 是目标麦位用户的展示资料快照；它只服务 IM/UI 首帧展示，不参与权限或房态判定。
  string target_nickname = 14;
  string target_avatar = 15;
  string target_display_user_id = 16;
  string target_pretty_display_user_id = 17;
}

// RoomMicSeatLocked 表达单个麦位锁定状态变更。
message RoomMicSeatLocked {
  int64 actor_user_id = 1;
  int32 seat_no = 2;
  bool locked = 3;
}

// RoomChatEnabledChanged 表达公屏开关状态变更。
message RoomChatEnabledChanged {
  int64 actor_user_id = 1;
  bool enabled = 2;
}

// RoomPasswordChanged 表达房间入房密码状态变更，不携带明文或哈希。
message RoomPasswordChanged {
  int64 actor_user_id = 1;
  bool locked = 2;
  // visible_region_id 是房间当前可见区域，activity-service 用它把锁房变化投到区域播报群。
  int64 visible_region_id = 3;
}

// RoomAdminChanged 表达房间管理员集合变更。
message RoomAdminChanged {
  int64 actor_user_id = 1;
  int64 target_user_id = 2;
  bool enabled = 3;
}

// RoomUserMuted 表达禁言状态变更。
message RoomUserMuted {
  int64 actor_user_id = 1;
  int64 target_user_id = 2;
  bool muted = 3;
}

// RoomUserKicked 表达踢人动作。
message RoomUserKicked {
  int64 actor_user_id = 1;
  int64 target_user_id = 2;
}

// RoomUserUnbanned 表达解除房间 ban。
message RoomUserUnbanned {
  int64 actor_user_id = 1;
  int64 target_user_id = 2;
}

// RoomGiftSent 表达送礼成功且已落房间状态。
message RoomGiftSent {
  int64 sender_user_id = 1;
  int64 target_user_id = 2;
  string gift_id = 3;
  int32 gift_count = 4;
  int64 gift_value = 5;
  string billing_receipt_id = 6;
  int64 visible_region_id = 7;
  string command_id = 8;
  string pool_id = 9;
  int64 coin_spent = 10;
  int64 country_id = 11;
  int64 region_id = 12;
  string gift_type_code = 13;
  string cp_relation_type = 14;
  string gift_name = 15;
  string gift_icon_url = 16;
  string gift_animation_url = 17;
  int64 target_gift_value = 18;
  repeated string gift_effect_types = 19;
  // is_robot_gift 标记机器人房间展示用礼物事实；下游真实统计、任务和结算消费者必须跳过。
  bool is_robot_gift = 20;
  // synthetic_lucky_gift 标记幸运礼物只用于房间表现，不写真实抽奖流水、不扣真实奖池、不发真实奖励。
  bool synthetic_lucky_gift = 21;
  // real_room_robot_gift 标记真人房机器人送出的真实热度礼物，用于 Databi 单独统计机器人投放价值。
  bool real_room_robot_gift = 22;
  // sender_name 是送礼入口固化的展示昵称，只用于客户端 IM 展示兜底，不作为用户主资料事实。
  string sender_name = 23;
  string sender_avatar = 24;
  string sender_display_user_id = 25;
  string sender_pretty_display_user_id = 26;
  // receiver_nickname 是收礼目标在送礼瞬间的展示昵称；字段名匹配 Flutter 已有解析逻辑。
  string receiver_nickname = 27;
  string receiver_avatar = 28;
  string receiver_display_user_id = 29;
  string receiver_pretty_display_user_id = 30;
  // display_mode=batch 表示这条逐目标事实只给统计、activity、CP 和礼物墙消费；房间展示由同命令的 RoomGiftBatchSent 承担。
  string display_mode = 31;
  // room_locked 固化送礼命令在 Room Cell 内执行时的锁房状态，跨房飘屏点击不能依赖首页缓存猜测。
  bool room_locked = 32;
  // sender_vip_level 是送礼入口固化的发送者 effective VIP 等级；0 表示当前无有效 VIP 或展示查询已降级。
  int32 sender_vip_level = 33;
  // sender_gift_broadcast_animation_url 是送礼入口从有效 gift_tray_skin 权益固化的动效 URL；下游禁止异步回查当前 VIP 覆盖历史事实。
  string sender_gift_broadcast_animation_url = 34;
  // owner_user_id 固化送礼命令执行时的 Room Cell 房主；跨房飘屏只能用它优化密码框，JoinRoom 仍做最终权限校验。
  int64 owner_user_id = 35;
}

// RoomGiftBatchLuckyResult 是批量送礼展示事件内的逐目标幸运礼物结果快照。
// 它只进入房间 IM 展示，不作为 activity 中奖事实，也不携带送礼人余额。
message RoomGiftBatchLuckyResult {
  bool enabled = 1;
  string draw_id = 2;
  string command_id = 3;
  string pool_id = 4;
  string gift_id = 5;
  int64 rule_version = 6;
  string experience_pool = 7;
  string selected_tier_id = 8;
  int64 multiplier_ppm = 9;
  int64 base_reward_coins = 10;
  int64 effective_reward_coins = 11;
  string reward_status = 12;
  bool stage_feedback = 13;
  bool high_multiplier = 14;
  int64 created_at_ms = 15;
  int64 target_user_id = 16;
}

// RoomGiftBatchTarget 固化批量送礼中单个收礼目标的展示和结算快照。
// 目标资料来自 gateway 入站时的 user-service 快照，避免 IM bridge 再回查高频用户服务。
message RoomGiftBatchTarget {
  int64 target_user_id = 1;
  string receiver_nickname = 2;
  string receiver_avatar = 3;
  string receiver_display_user_id = 4;
  string receiver_pretty_display_user_id = 5;
  int64 gift_value = 6;
  int64 target_gift_value = 7;
  int64 coin_spent = 8;
  string billing_receipt_id = 9;
  string command_id = 10;
  RoomGiftBatchLuckyResult lucky_gift = 11;
}

// RoomGiftBatchSent 只服务新 Flutter 的多人送礼展示。
// 逐目标 RoomGiftSent 仍然写 durable outbox 作为统计、CP、礼物墙和账务消费事实。
message RoomGiftBatchSent {
  int64 sender_user_id = 1;
  string sender_name = 2;
  string sender_avatar = 3;
  string sender_display_user_id = 4;
  string sender_pretty_display_user_id = 5;
  string gift_id = 6;
  int32 gift_count = 7;
  int64 total_gift_value = 8;
  int64 total_coin_spent = 9;
  string billing_receipt_id = 10;
  int64 room_heat = 11;
  string pool_id = 12;
  string gift_type_code = 13;
  string cp_relation_type = 14;
  string gift_name = 15;
  string gift_icon_url = 16;
  string gift_animation_url = 17;
  repeated string gift_effect_types = 18;
  repeated int64 target_user_ids = 19;
  repeated RoomGiftBatchTarget targets = 20;
  string command_id = 21;
  int64 visible_region_id = 22;
  // sender_vip_level 与同命令的逐目标 RoomGiftSent 共用一份发送者展示快照。
  int32 sender_vip_level = 23;
  // sender_gift_broadcast_animation_url 与同命令的逐目标事实共用，批量送礼不能因展示协议合并而丢失 VIP 托盘。
  string sender_gift_broadcast_animation_url = 24;
}

// RoomLuckyGiftDrawn 是 room-service 从 lucky-gift-service owner 事实派生的真人中奖展示事件。
// 它只承载腾讯云 IM 房间表现，不是 Room Cell 核心状态，不能推进 room_version、榜单或房间快照。
message RoomLuckyGiftDrawn {
  string draw_id = 1;
  string command_id = 2;
  string pool_id = 3;
  string gift_id = 4;
  int32 gift_count = 5;
  int64 sender_user_id = 6;
  int64 target_user_id = 7;
  string sender_name = 8;
  string sender_avatar = 9;
  string sender_display_user_id = 10;
  string sender_pretty_display_user_id = 11;
  int64 visible_region_id = 12;
  int64 country_id = 13;
  int64 coin_spent = 14;
  int64 rule_version = 15;
  string experience_pool = 16;
  string selected_tier_id = 17;
  int64 multiplier_ppm = 18;
  int64 base_reward_coins = 19;
  int64 effective_reward_coins = 20;
  bool stage_feedback = 21;
  bool high_multiplier = 22;
  string reward_status = 23;
  string wallet_transaction_id = 24;
  // 时间沿用 lucky owner 的 UTC Unix epoch milliseconds，不以 room-service 消费时间覆盖。
  int64 draw_created_at_ms = 25;
  int64 reward_granted_at_ms = 26;
  // room_locked 来自 lucky owner 事实中的送礼时房间快照，仅用于客户端点击飘屏前决定是否先收集密码。
  bool room_locked = 27;
  // owner_user_id 与 room_locked 来自同一次原始送礼快照，禁止用中奖人、送礼人或异步房间查询替代。
  int64 owner_user_id = 28;
}

// RoomRobotLuckyGiftDrawn 是机器人房间专用幸运礼物展示事件。
// 它复用客户端 lucky_gift_drawn 表现协议，但不代表真实奖池抽奖和钱包返奖事实。
message RoomRobotLuckyGiftDrawn {
  string draw_id = 1;
  string command_id = 2;
  int64 sender_user_id = 3;
  int64 target_user_id = 4;
  string gift_id = 5;
  int32 gift_count = 6;
  string pool_id = 7;
  int64 multiplier_ppm = 8;
  int64 base_reward_coins = 9;
  int64 effective_reward_coins = 10;
  int64 created_at_ms = 11;
  int64 visible_region_id = 12;
  bool is_robot = 13;
  bool synthetic = 14;
}

// RoomHeatChanged 表达热度变化结果。
message RoomHeatChanged {
  int64 delta = 1;
  int64 current_heat = 2;
}

// RoomRankChanged 表达本地礼物榜变化结果。
message RoomRankChanged {
  int64 user_id = 1;
  int64 score = 2;
  int64 gift_value = 3;
}

message RoomRocketRewardGrant {
  string reward_role = 1;
  int64 user_id = 2;
  string reward_item_id = 3;
  int64 resource_group_id = 4;
  string display_name = 5;
  string icon_url = 6;
  string grant_id = 7;
  string status = 8;
}

// RoomRocketFuelChanged 表达送礼扣费成功后火箭有效燃料发生变化。
message RoomRocketFuelChanged {
  string rocket_id = 1;
  int32 level = 2;
  int64 added_fuel = 3;
  int64 effective_added_fuel = 4;
  int64 overflow_fuel = 5;
  int64 current_fuel = 6;
  int64 fuel_threshold = 7;
  string status = 8;
  int64 reset_at_ms = 9;
  int64 sender_user_id = 10;
  string gift_id = 11;
  int32 gift_count = 12;
  string command_id = 13;
  int64 visible_region_id = 14;
}

// RoomRocketIgnited 表达火箭燃料满后进入倒计时，并作为区域/全局播报的事实源。
message RoomRocketIgnited {
  string rocket_id = 1;
  int32 level = 2;
  int64 current_fuel = 3;
  int64 fuel_threshold = 4;
  int64 ignited_at_ms = 5;
  int64 launch_at_ms = 6;
  string broadcast_scope = 7;
  int64 visible_region_id = 8;
  int64 top1_user_id = 9;
  int64 igniter_user_id = 10;
  string command_id = 11;
  string room_short_id = 12;
  string rocket_cover_url = 13;
  int64 reset_at_ms = 14;
  // room_locked 固化点火礼物在 Room Cell 串行执行时的锁房状态，跨房点击不能异步回查后覆盖该次展示事实。
  bool room_locked = 15;
  // owner_user_id 固化点火瞬间的 Room Cell 房主，火箭贡献者和点火人都不能替代该身份。
  int64 owner_user_id = 16;
}

// RoomRocketLaunched 表达火箭已经发射，在线用户名单按发射瞬间 Room Cell presence 结算。
message RoomRocketLaunched {
  string rocket_id = 1;
  int32 level = 2;
  int32 next_level = 3;
  int64 launched_at_ms = 4;
  int64 reset_at_ms = 5;
  int64 top1_user_id = 6;
  int64 igniter_user_id = 7;
  repeated int64 in_room_user_ids = 8;
  repeated RoomRocketRewardGrant rewards = 9;
}

// RoomRocketRewardGranted 是客户端展示发奖弹窗和私有通知的最小事实。
message RoomRocketRewardGranted {
  string rocket_id = 1;
  int32 level = 2;
  repeated RoomRocketRewardGrant rewards = 3;
}
