SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;


-- 使用 utf8mb4 连接字符集，保证中文注释、中文名称和 emoji 在导入时不被降级。
CREATE DATABASE IF NOT EXISTS hyapp_room
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

USE hyapp_room;

CREATE TABLE IF NOT EXISTS rooms (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  room_short_id VARCHAR(32) NOT NULL DEFAULT '' COMMENT '房间短号 ID',
  owner_user_id BIGINT NOT NULL COMMENT '房主用户 ID',
  seat_count INT NOT NULL COMMENT '麦位数量',
  mode VARCHAR(64) NOT NULL COMMENT '业务模式',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  room_password_hash VARCHAR(128) NOT NULL DEFAULT '' COMMENT '房间密码哈希值',
  close_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '关闭原因',
  closed_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '关闭操作管理员 ID',
  closed_by_admin_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '关闭操作管理员名称',
  closed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '关闭时间，UTC epoch ms',
  visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '可见区域 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id),
  UNIQUE KEY uk_rooms_room_id (room_id),
  UNIQUE KEY uk_rooms_short_id (app_code, room_short_id),
  UNIQUE KEY uk_rooms_owner_user (app_code, owner_user_id),
  KEY idx_rooms_region_status (app_code, visible_region_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间核心状态持久表';

CREATE TABLE IF NOT EXISTS room_list_entries (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  room_short_id VARCHAR(32) NOT NULL DEFAULT '' COMMENT '房间短号 ID',
  visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '可见区域 ID',
  owner_country_code VARCHAR(3) NOT NULL DEFAULT '' COMMENT '房主国家码',
  owner_user_id BIGINT NOT NULL COMMENT '房主用户 ID',
  owner_vip_level INT NOT NULL DEFAULT 0 COMMENT '房主当前 effective VIP 等级异步投影',
  owner_vip_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '房主当前 effective VIP 到期时间，UTC epoch ms',
  owner_vip_fallback_level INT NOT NULL DEFAULT 0 COMMENT '体验卡到期后 wallet paid VIP 回落等级',
  owner_vip_fallback_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '回落 paid VIP 到期时间，UTC epoch ms',
  title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '标题',
  cover_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '封面 URL',
  mode VARCHAR(64) NOT NULL COMMENT '业务模式',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  locked BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否锁定',
  close_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '关闭原因',
  closed_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '关闭操作管理员 ID',
  closed_by_admin_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '关闭操作管理员名称',
  closed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '关闭时间，UTC epoch ms',
  heat BIGINT NOT NULL DEFAULT 0 COMMENT '热度值',
  weekly_contribution BIGINT NOT NULL DEFAULT 0 COMMENT '当前贡献周期房间贡献，周一 01:00 UTC 自动切新周期',
  contribution_week_start_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'weekly_contribution 所属 UTC 周一 01:00 毫秒',
  online_count INT NOT NULL DEFAULT 0 COMMENT '在线数量',
  seat_count INT NOT NULL DEFAULT 0 COMMENT '麦位数量',
  occupied_seat_count INT NOT NULL DEFAULT 0 COMMENT '占用麦位数量',
  sort_score BIGINT NOT NULL DEFAULT 0 COMMENT '排序分值',
  rocket_near_completion BOOLEAN NOT NULL DEFAULT FALSE COMMENT '当前档火箭剩余燃料不超过 20%',
  has_active_red_packet BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'wallet MQ 派生的房间有效红包聚合',
  active_red_packet_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '仍有余量红包的最晚到期时间，UTC epoch ms',
  room_border_json JSON NULL COMMENT '当前未过期房间边框资源快照',
  room_name_style_json JSON NULL COMMENT '当前未过期彩色房名资源快照',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id),
  KEY idx_room_list_short_id (app_code, room_short_id),
  KEY idx_room_list_region_hot (app_code, visible_region_id, status, sort_score DESC, room_id),
  KEY idx_room_list_region_new (app_code, visible_region_id, status, created_at_ms DESC, room_id),
  KEY idx_room_list_region_country_hot (app_code, visible_region_id, owner_country_code, status, sort_score DESC, room_id),
  KEY idx_room_list_region_country_new (app_code, visible_region_id, owner_country_code, status, created_at_ms DESC, room_id),
  KEY idx_room_list_weekly_contribution (app_code, status, visible_region_id, weekly_contribution DESC, created_at_ms DESC, room_id),
  KEY idx_room_list_owner (app_code, owner_user_id, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间列表项表';

CREATE TABLE IF NOT EXISTS room_user_presence (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  role VARCHAR(32) NOT NULL COMMENT '角色',
  publish_state VARCHAR(32) NOT NULL DEFAULT '' COMMENT '推流状态',
  mic_session_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '麦位会话 ID',
  room_version BIGINT NOT NULL COMMENT 'Room Cell 状态版本',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  joined_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '进房时间，UTC epoch ms',
  last_seen_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后活跃时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id),
  KEY idx_room_user_presence_room (app_code, room_id, status),
  KEY idx_room_user_presence_updated (app_code, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间用户在线状态表';

CREATE TABLE IF NOT EXISTS room_user_gift_stats (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  user_id BIGINT NOT NULL COMMENT '送礼用户 ID',
  gift_value BIGINT NOT NULL DEFAULT 0 COMMENT '当前房间生命周期内累计送礼价值',
  last_gift_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最近一次送礼时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id, user_id),
  KEY idx_room_user_gift_stats_room_value (app_code, room_id, gift_value DESC, last_gift_at_ms DESC, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间用户送礼价值统计表';

CREATE TABLE IF NOT EXISTS room_user_contribution_period_stats (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  period VARCHAR(16) NOT NULL COMMENT '周期类型：day/week/month',
  period_start_ms BIGINT NOT NULL COMMENT '周期开始时间，UTC epoch ms，包含',
  period_end_ms BIGINT NOT NULL COMMENT '周期结束时间，UTC epoch ms，不包含',
  user_id BIGINT NOT NULL COMMENT '送礼用户 ID',
  gift_value BIGINT NOT NULL DEFAULT 0 COMMENT '当前周期内累计送礼贡献值',
  last_gift_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '当前周期最近一次送礼时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id, period, period_start_ms, user_id),
  KEY idx_room_contribution_period_rank (app_code, room_id, period, period_start_ms, gift_value DESC, last_gift_at_ms DESC, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间用户周期贡献榜统计表';

CREATE TABLE IF NOT EXISTS room_background_images (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  background_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '背景图 ID',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  image_url VARCHAR(1024) NOT NULL COMMENT '背景图 URL',
  -- utf8mb4 的 1024 字符 URL 无法直接进入 InnoDB 3072 字节唯一键；生成列保留完整 URL 唯一性，避免前缀索引误判。
  image_url_sha256 BINARY(32) GENERATED ALWAYS AS (UNHEX(SHA2(image_url, 256))) STORED COMMENT '背景图 URL 唯一性哈希',
  command_id VARCHAR(128) NULL COMMENT '新版素材保存幂等键；历史行保持 NULL',
  object_key VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'COS 对象 key',
  content_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '服务端嗅探 MIME',
  media_format VARCHAR(16) NOT NULL DEFAULT '' COMMENT 'jpeg/png/gif/webp',
  size_bytes BIGINT NOT NULL DEFAULT 0 COMMENT '文件字节数',
  width INT NOT NULL DEFAULT 0 COMMENT '像素宽度',
  height INT NOT NULL DEFAULT 0 COMMENT '像素高度',
  animated BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否动图',
  frame_count INT NOT NULL DEFAULT 0 COMMENT '帧数',
  duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '动图总时长',
  poster_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '可选首帧 URL',
  thumbnail_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '可选缩略图 URL',
  sha256 CHAR(64) NOT NULL DEFAULT '' COMMENT '原文件 SHA-256',
  media_status VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'active 表示已通过专用上传入口',
  created_by_user_id BIGINT NOT NULL COMMENT '保存背景图的用户 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (background_id),
  UNIQUE KEY uk_room_background_url (app_code, room_id, image_url_sha256),
  UNIQUE KEY uk_room_background_command (app_code, room_id, command_id),
  KEY idx_room_background_list (app_code, room_id, created_at_ms DESC, background_id DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间背景图素材表';

CREATE TABLE IF NOT EXISTS room_media_upload_registrations (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  room_id VARCHAR(64) NOT NULL COMMENT '目标房间 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '专用上传强幂等键',
  actor_user_id BIGINT NOT NULL COMMENT '首次授权用户 ID',
  purpose VARCHAR(32) NOT NULL COMMENT 'room_background/room_image/room_cover',
  media_payload_sha256 CHAR(64) NOT NULL COMMENT '首次服务端解析媒体事实哈希',
  expected_object_key VARCHAR(512) NOT NULL COMMENT 'room owner 确定的 COS key',
  object_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT 'PutObject 成功后的访问 URL',
  status VARCHAR(32) NOT NULL DEFAULT 'authorized' COMMENT 'authorized/active/consumed',
  content_type VARCHAR(64) NOT NULL COMMENT '服务端嗅探 MIME',
  media_format VARCHAR(16) NOT NULL COMMENT 'jpeg/png/gif/webp',
  size_bytes BIGINT NOT NULL COMMENT '原文件字节数',
  width INT NOT NULL COMMENT '像素宽度',
  height INT NOT NULL COMMENT '像素高度',
  animated BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否动图',
  frame_count INT NOT NULL COMMENT '帧数',
  duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '动图总时长',
  sha256 CHAR(64) NOT NULL COMMENT '原文件 SHA-256',
  authorized_room_version BIGINT NOT NULL COMMENT '首次授权看到的房间版本',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id, command_id),
  UNIQUE KEY uk_room_media_upload_object (app_code, expected_object_key),
  KEY idx_room_media_upload_status_created (app_code, status, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间专用媒体上传授权与完成事实';

CREATE TABLE IF NOT EXISTS room_decoration_assignments (
  app_code VARCHAR(32) NOT NULL,
  room_id VARCHAR(64) NOT NULL,
  decoration_type VARCHAR(32) NOT NULL,
  owner_user_id BIGINT NOT NULL,
  benefit_code VARCHAR(64) NOT NULL,
  resource_id BIGINT NOT NULL,
  entitlement_id VARCHAR(128) NOT NULL DEFAULT '',
  expires_at_ms BIGINT NOT NULL DEFAULT 0,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, room_id, decoration_type),
  KEY idx_room_decoration_resource (app_code, resource_id, room_id, decoration_type),
  KEY idx_room_decoration_owner (app_code, owner_user_id, room_id, decoration_type),
  KEY idx_room_decoration_expiry (app_code, expires_at_ms, room_id, decoration_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间当前 VIP 装扮反向索引';

CREATE TABLE IF NOT EXISTS room_wallet_event_consumption (
  app_code VARCHAR(32) NOT NULL,
  event_id VARCHAR(128) NOT NULL,
  event_type VARCHAR(64) NOT NULL,
  consumed_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, event_id),
  KEY idx_room_wallet_event_consumed (app_code, consumed_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='room-service 消费 wallet 投影事实的本地幂等表';

CREATE TABLE IF NOT EXISTS room_red_packet_projections (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，多租户隔离',
  packet_id VARCHAR(128) NOT NULL COMMENT 'wallet 红包 ID',
  room_id VARCHAR(64) NOT NULL COMMENT '红包所属房间',
  status VARCHAR(32) NOT NULL COMMENT 'wallet 红包状态快照',
  remaining_amount BIGINT NOT NULL DEFAULT 0 COMMENT '事件携带的剩余金额',
  remaining_count INT NOT NULL DEFAULT 0 COMMENT '事件携带的剩余份数',
  expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '红包到期时间，UTC epoch ms',
  event_rank INT NOT NULL DEFAULT 0 COMMENT 'created/claimed/refunded 单调状态级别',
  event_occurred_at_ms BIGINT NOT NULL COMMENT 'wallet 事实发生时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '投影更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, packet_id),
  KEY idx_room_red_packet_active (app_code, room_id, status, expires_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包房间列表异步投影，不承载资金事实';

CREATE TABLE IF NOT EXISTS room_snapshots (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  room_version BIGINT NOT NULL COMMENT 'Room Cell 状态版本',
  payload LONGBLOB NOT NULL COMMENT '业务负载快照',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id),
  INDEX idx_room_snapshots_version (app_code, room_id, room_version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Room Cell 快照恢复表';

CREATE TABLE IF NOT EXISTS room_command_log (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键 ID',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  room_version BIGINT NOT NULL COMMENT 'Room Cell 状态版本',
  command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
  command_type VARCHAR(64) NOT NULL COMMENT '命令类型',
  owner_node_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '房主节点 ID',
  lease_token VARCHAR(128) NOT NULL DEFAULT '' COMMENT '租约令牌',
  payload LONGBLOB NOT NULL COMMENT '业务负载快照',
  result_payload LONGBLOB NULL COMMENT '首次提交的 typed 结果，用于幂等原样重放',
  replayable BOOLEAN NOT NULL COMMENT '是否可重放',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  UNIQUE KEY uk_room_command (app_code, room_id, command_id),
  KEY idx_room_command_replay (app_code, room_id, room_version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Room Cell 命令日志表';

CREATE TABLE IF NOT EXISTS room_gift_operations (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '送礼全链路幂等 ID',
  actor_user_id BIGINT NOT NULL COMMENT '送礼用户 ID',
  command_payload LONGBLOB NOT NULL COMMENT '规范化 Room 命令，供载荷冲突校验',
  request_payload LONGBLOB NOT NULL COMMENT '原始 SendGiftRequest protobuf，供服务端恢复',
  status VARCHAR(32) NOT NULL COMMENT 'pending/debited/drawn/committed/compensated',
  billing_payload LONGBLOB NULL COMMENT '钱包稳定回执 protobuf',
  lucky_payload LONGBLOB NULL COMMENT '幸运礼物聚合结果 protobuf',
  result_payload LONGBLOB NULL COMMENT '首次提交的 SendGiftResultV2 protobuf',
  last_error TEXT NULL COMMENT '最近一次恢复错误',
  retry_count INT NOT NULL DEFAULT 0 COMMENT '服务端恢复次数',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下次允许恢复时间，UTC epoch ms',
  worker_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前恢复 worker',
  lock_until_ms BIGINT NULL COMMENT '恢复租约截止时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id, command_id),
  KEY idx_room_gift_operation_recovery (status, next_retry_at_ms, lock_until_ms, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='送礼跨钱包抽奖和房间提交 Saga';

CREATE TABLE IF NOT EXISTS room_outbox (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
  event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  worker_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'worker ID',
  lock_until_ms BIGINT NULL COMMENT '锁定过期时间，UTC epoch ms',
  envelope LONGBLOB NOT NULL COMMENT '事件信封',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次重试时间，UTC epoch ms',
  last_error TEXT NULL COMMENT '最后一次失败原因',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, event_id),
  KEY idx_room_outbox_pending (app_code, status, next_retry_at_ms, created_at_ms, event_id),
  KEY idx_room_outbox_claim (app_code, status, lock_until_ms, created_at_ms, event_id),
  KEY idx_room_outbox_event_created (app_code, event_type, created_at_ms, event_id),
  KEY idx_room_outbox_retention (app_code, status, updated_at_ms, event_id),
  KEY idx_room_outbox_room_event (app_code, room_id, event_type, created_at_ms, event_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间事件 outbox 表';

CREATE TABLE IF NOT EXISTS room_user_feed_entries (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  feed_type VARCHAR(32) NOT NULL COMMENT '动态类型',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id, feed_type, room_id),
  KEY idx_room_user_feed_list (app_code, user_id, feed_type, updated_at_ms DESC, room_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间用户动态项表';

CREATE TABLE IF NOT EXISTS room_follows (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  followed_at_ms BIGINT NOT NULL COMMENT '关注时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id, room_id),
  KEY idx_room_follows_user_list (app_code, user_id, status, followed_at_ms DESC, room_id),
  KEY idx_room_follows_room (app_code, room_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间关注表';

CREATE TABLE IF NOT EXISTS room_region_pins (
  id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  visible_region_id BIGINT NOT NULL COMMENT '可见区域 ID',
  pin_type VARCHAR(32) NOT NULL DEFAULT 'region' COMMENT '置顶类型：region 区域置顶，country 国家置顶，global 历史全区置顶',
  room_id VARCHAR(64) NOT NULL COMMENT '房间 ID',
  weight BIGINT NOT NULL DEFAULT 0 COMMENT '权重',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  pinned_at_ms BIGINT NOT NULL COMMENT '置顶时间，UTC epoch ms',
  expires_at_ms BIGINT NOT NULL COMMENT '过期时间，UTC epoch ms',
  cancelled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '取消时间，UTC epoch ms',
  created_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  cancelled_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '取消操作管理员 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (id),
  UNIQUE KEY uk_room_region_pins_scope (app_code, pin_type, visible_region_id, room_id),
  KEY idx_room_region_pins_active_scope (app_code, pin_type, visible_region_id, status, pinned_at_ms, expires_at_ms, weight DESC, room_id),
  KEY idx_room_region_pins_room (app_code, room_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间置顶表';

CREATE TABLE IF NOT EXISTS room_seat_configs (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  allowed_seat_counts VARCHAR(128) NOT NULL COMMENT '允许麦位数量',
  default_seat_count INT NOT NULL COMMENT '默认麦位数量',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间麦位配置表';

CREATE TABLE IF NOT EXISTS room_rocket_configs (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用房间火箭',
  config_version BIGINT NOT NULL DEFAULT 1 COMMENT '配置版本，后台每次保存递增',
  fuel_source VARCHAR(32) NOT NULL COMMENT '燃料来源，默认按送礼价值累计',
  launch_delay_ms BIGINT NOT NULL COMMENT '燃料满后发射倒计时，UTC 毫秒时长',
  broadcast_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '倒计时开始后是否广播',
  broadcast_scope VARCHAR(32) NOT NULL COMMENT '广播范围：none/region/global',
  broadcast_delay_ms BIGINT NOT NULL DEFAULT 0 COMMENT '广播后到发射的延迟，UTC 毫秒时长',
  reward_stack_policy VARCHAR(32) NOT NULL COMMENT '同一用户多角色命中奖励时的叠加策略',
  levels_json JSON NOT NULL COMMENT '5 级火箭物料、阈值和奖励池配置',
  gift_fuel_rules_json JSON NOT NULL COMMENT '礼物燃料倍率、固定燃料和排除规则',
  updated_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code),
  KEY idx_room_rocket_enabled (app_code, enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='语音房火箭后台配置表';

CREATE TABLE IF NOT EXISTS room_robot_rooms (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  room_id VARCHAR(64) NOT NULL COMMENT '机器人房间 ID',
  room_short_id VARCHAR(32) NOT NULL DEFAULT '' COMMENT '房间短 ID',
  title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '房间名称',
  cover_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '房间头像',
  visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '可见区域 ID',
  status VARCHAR(32) NOT NULL COMMENT '运行状态：active/stopped',
  owner_robot_user_id BIGINT NOT NULL COMMENT '房主机器人用户 ID',
  robot_user_ids_json JSON NOT NULL COMMENT '本房间占用的机器人用户 ID 集合',
  active_robot_count INT NOT NULL DEFAULT 0 COMMENT '房间内同时保持的活跃机器人数量，0 表示兼容旧配置全量在线',
  seat_count INT NOT NULL DEFAULT 10 COMMENT '机器人房间麦位数：10/15/20',
  gift_ids_json JSON NOT NULL COMMENT '普通礼物 ID 集合',
  lucky_gift_ids_json JSON NOT NULL COMMENT '幸运礼物 ID 集合',
  normal_gift_interval_ms BIGINT NOT NULL COMMENT '普通礼物间隔毫秒',
  lucky_combo_min BIGINT NOT NULL COMMENT '幸运礼物最小连击次数',
  lucky_combo_max BIGINT NOT NULL COMMENT '幸运礼物最大连击次数',
  lucky_pause_min_ms BIGINT NOT NULL COMMENT '幸运礼物连击后最小暂停毫秒',
  lucky_pause_max_ms BIGINT NOT NULL COMMENT '幸运礼物连击后最大暂停毫秒',
  robot_stay_min_ms BIGINT NOT NULL DEFAULT 180000 COMMENT '机器人单次最短停留毫秒',
  robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000 COMMENT '机器人单次最长停留毫秒',
  robot_replace_min_ms BIGINT NOT NULL DEFAULT 0 COMMENT '机器人离开后最短补位延迟毫秒',
  robot_replace_max_ms BIGINT NOT NULL DEFAULT 60000 COMMENT '机器人离开后最长补位延迟毫秒',
  max_gift_senders BIGINT NOT NULL DEFAULT 1 COMMENT '同一时间最多允许送礼的机器人数量',
  created_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id),
  KEY idx_room_robot_rooms_status (app_code, status, updated_at_ms, room_id),
  KEY idx_room_robot_rooms_owner (app_code, owner_robot_user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='机器人房间后台配置表';

CREATE TABLE IF NOT EXISTS room_human_robot_configs (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否启用真人房间机器人行为',
  candidate_room_max_online INT NOT NULL DEFAULT 5 COMMENT '低于该在线人数的同国家真人房可进入机器人',
  room_full_stop_online INT NOT NULL DEFAULT 10 COMMENT '房间达到该在线人数后停止补机器人',
  room_target_min_online INT NOT NULL DEFAULT 8 COMMENT '房间随机目标总人数下限',
  room_target_max_online INT NOT NULL DEFAULT 10 COMMENT '房间随机目标总人数上限',
  robot_stay_min_ms BIGINT NOT NULL DEFAULT 60000 COMMENT '机器人单次最短停留毫秒',
  robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000 COMMENT '机器人单次最长停留毫秒',
  robot_replace_min_ms BIGINT NOT NULL DEFAULT 60000 COMMENT '机器人离开后最短补位延迟毫秒',
  robot_replace_max_ms BIGINT NOT NULL DEFAULT 180000 COMMENT '机器人离开后最长补位延迟毫秒',
  normal_gift_interval_ms BIGINT NOT NULL DEFAULT 10000 COMMENT '普通礼物间隔毫秒',
  normal_gift_interval_min_ms BIGINT NOT NULL DEFAULT 1000 COMMENT '普通礼物最短随机间隔毫秒',
  normal_gift_interval_max_ms BIGINT NOT NULL DEFAULT 20000 COMMENT '普通礼物最长随机间隔毫秒',
  gift_ids_json JSON NOT NULL COMMENT '普通礼物 ID 集合',
  lucky_gift_ids_json JSON NOT NULL COMMENT '幸运礼物 ID 集合',
  super_lucky_gift_ids_json JSON NOT NULL COMMENT '超级幸运礼物 ID 集合',
  lucky_combo_min BIGINT NOT NULL DEFAULT 1 COMMENT '幸运礼物最小连击次数',
  lucky_combo_max BIGINT NOT NULL DEFAULT 3 COMMENT '幸运礼物最大连击次数',
  lucky_pause_min_ms BIGINT NOT NULL DEFAULT 5000 COMMENT '幸运礼物连击后最小暂停毫秒',
  lucky_pause_max_ms BIGINT NOT NULL DEFAULT 20000 COMMENT '幸运礼物连击后最大暂停毫秒',
  max_gift_senders BIGINT NOT NULL DEFAULT 1 COMMENT '同一时间最多送礼机器人数量',
  country_pools_json JSON NOT NULL COMMENT '国家机器人池配置',
  allowed_owner_ids_json JSON NOT NULL COMMENT '限定进入的房主展示短号/内部用户 ID，空数组表示所有真人房',
  country_limit_enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否启用国家进房上限配置',
  country_rules_json JSON NOT NULL COMMENT '每个国家最多同时进几个真人房的配置',
  updated_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code),
  KEY idx_room_human_robot_enabled (app_code, enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='真人房间机器人行为配置表';

INSERT IGNORE INTO room_seat_configs (
  app_code,
  allowed_seat_counts,
  default_seat_count,
  created_at_ms,
  updated_at_ms
) VALUES (
  'lalu',
  '[10,15,20,25,30]',
  15,
  0,
  0
);

ALTER TABLE room_rocket_configs
  MODIFY COLUMN levels_json JSON NOT NULL COMMENT '5 级火箭物料、阈值和奖励池配置';

INSERT IGNORE INTO room_rocket_configs (
  app_code,
  enabled,
  config_version,
  fuel_source,
  launch_delay_ms,
  broadcast_enabled,
  broadcast_scope,
  broadcast_delay_ms,
  reward_stack_policy,
  levels_json,
  gift_fuel_rules_json,
  updated_by_admin_id,
  created_at_ms,
  updated_at_ms
) VALUES (
  'lalu',
  0,
  1,
  'heat_value',
  30000,
  1,
  'region',
  0,
  'allow_stack',
  JSON_ARRAY(
    JSON_OBJECT('level', 1, 'fuelThreshold', 1000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()),
    JSON_OBJECT('level', 2, 'fuelThreshold', 3000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()),
    JSON_OBJECT('level', 3, 'fuelThreshold', 6000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()),
    JSON_OBJECT('level', 4, 'fuelThreshold', 10000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()),
    JSON_OBJECT('level', 5, 'fuelThreshold', 15000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY())
  ),
  JSON_ARRAY(),
  0,
  0,
  0
);
