SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;


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

USE hyapp_activity;

CREATE TABLE IF NOT EXISTS activities (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  activity_id VARCHAR(96) NOT NULL COMMENT '活动 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, activity_id),
  KEY idx_activities_status (app_code, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动实例表';

CREATE TABLE IF NOT EXISTS activity_event_consumption (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  event_id VARCHAR(96) NOT NULL COMMENT '事件幂等 ID',
  event_type VARCHAR(96) NOT NULL COMMENT '事件类型',
  source VARCHAR(64) NOT NULL COMMENT '来源',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  failure_reason VARCHAR(255) NULL COMMENT '失败原因',
  consumed_at_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, event_id),
  KEY idx_activity_event_consumption_status (app_code, status),
  KEY idx_activity_event_consumption_updated_at (app_code, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动事件消费位点表';

CREATE TABLE IF NOT EXISTS activity_outbox (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  outbox_id VARCHAR(96) NOT NULL COMMENT '发件箱 ID',
  event_type VARCHAR(96) NOT NULL COMMENT '事件类型',
  payload BLOB NOT NULL COMMENT '业务负载快照',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
  next_retry_at_ms BIGINT NOT NULL COMMENT '下一次重试时间，UTC epoch ms',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前锁定 worker',
  lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁过期时间，UTC epoch ms',
  last_error VARCHAR(512) NOT NULL DEFAULT '' 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, outbox_id),
  KEY idx_activity_outbox_status_retry (app_code, status, next_retry_at_ms),
  KEY idx_activity_outbox_event_retry (app_code, event_type, status, next_retry_at_ms, created_at_ms, outbox_id),
  KEY idx_activity_outbox_event_lock (app_code, event_type, status, lock_until_ms, created_at_ms, outbox_id),
  KEY idx_activity_outbox_retention (app_code, status, updated_at_ms, outbox_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动事件 outbox 表';

CREATE TABLE IF NOT EXISTS wheel_rule_versions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  rule_version BIGINT NOT NULL COMMENT '不可变规则版本',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用',
  draw_price_coins BIGINT NOT NULL COMMENT '单抽价格，金币',
  target_rtp_ppm BIGINT NOT NULL COMMENT '金币和礼物 RTP 目标，ppm',
  pool_rate_ppm BIGINT NOT NULL COMMENT '每笔消耗进入转盘基础奖池比例，ppm',
  settlement_window_draws BIGINT NOT NULL COMMENT 'RTP 观察窗口抽数',
  initial_pool_coins BIGINT NOT NULL DEFAULT 0 COMMENT '初始奖池水位',
  pool_reserve_coins BIGINT NOT NULL DEFAULT 0 COMMENT '奖池安全水位',
  max_single_rtp_payout BIGINT NOT NULL DEFAULT 0 COMMENT '单次计入 RTP 的最大返奖',
  effective_from_ms BIGINT NOT NULL COMMENT '生效时间，UTC epoch ms',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '发布人',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, wheel_id, rule_version),
  KEY idx_wheel_rule_versions_latest (app_code, wheel_id, rule_version),
  KEY idx_wheel_rule_versions_enabled (app_code, enabled, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘规则版本表';

CREATE TABLE IF NOT EXISTS wheel_prize_tiers (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  rule_version BIGINT NOT NULL COMMENT '规则版本',
  tier_id VARCHAR(96) NOT NULL COMMENT '奖档 ID',
  display_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '展示名称快照',
  reward_type VARCHAR(32) NOT NULL COMMENT 'coin/gift/prop/dress',
  reward_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '礼物或道具资源 ID',
  reward_count BIGINT NOT NULL DEFAULT 1 COMMENT '奖励数量',
  reward_coins BIGINT NOT NULL DEFAULT 0 COMMENT '金币奖励金额',
  rtp_value_coins BIGINT NOT NULL DEFAULT 0 COMMENT '计入 RTP 的奖励价值；道具装扮强制为 0',
  weight_ppm BIGINT NOT NULL COMMENT '随机权重，ppm 口径',
  enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
  metadata_json JSON NOT NULL COMMENT '奖品展示和发放扩展快照',
  PRIMARY KEY (app_code, wheel_id, rule_version, tier_id),
  KEY idx_wheel_prize_tiers_rule (app_code, wheel_id, rule_version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘奖档表';

CREATE TABLE IF NOT EXISTS wheel_rtp_windows (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  window_index BIGINT NOT NULL COMMENT 'RTP 窗口序号',
  target_rtp_ppm BIGINT NOT NULL COMMENT '窗口目标 RTP',
  control_window_draws BIGINT NOT NULL COMMENT '窗口抽数',
  paid_draws BIGINT NOT NULL DEFAULT 0 COMMENT '已抽次数',
  wager_coins BIGINT NOT NULL DEFAULT 0 COMMENT '消耗金币',
  target_payout_coins BIGINT NOT NULL DEFAULT 0 COMMENT '目标返奖',
  actual_rtp_value_coins BIGINT NOT NULL DEFAULT 0 COMMENT '实际计入 RTP 的返奖',
  carry_ppm BIGINT NOT NULL DEFAULT 0 COMMENT '整数除法余数',
  status VARCHAR(32) NOT NULL DEFAULT 'open' COMMENT 'open/closed',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, wheel_id, window_index),
  KEY idx_wheel_rtp_windows_open (app_code, wheel_id, status, window_index)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘 RTP 观察窗口';

CREATE TABLE IF NOT EXISTS wheel_pools (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  balance BIGINT NOT NULL DEFAULT 0 COMMENT '当前可用水位',
  reserve_floor BIGINT NOT NULL DEFAULT 0 COMMENT '安全水位',
  total_in BIGINT NOT NULL DEFAULT 0 COMMENT '累计入池',
  total_out BIGINT NOT NULL DEFAULT 0 COMMENT '累计 RTP 价值支出',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, wheel_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘基础奖池';

CREATE TABLE IF NOT EXISTS wheel_draw_records (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  draw_id VARCHAR(128) NOT NULL COMMENT '抽奖 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '幂等命令 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  device_id VARCHAR(128) NOT NULL COMMENT '设备 ID',
  visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '可见区域 ID',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  coin_spent BIGINT NOT NULL COMMENT '消耗金币',
  rule_version BIGINT NOT NULL COMMENT '规则版本',
  rtp_window_index BIGINT NOT NULL COMMENT 'RTP 窗口',
  selected_tier_id VARCHAR(96) NOT NULL COMMENT '命中奖档',
  reward_type VARCHAR(32) NOT NULL COMMENT 'coin/gift/prop/dress',
  reward_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '礼物或道具资源 ID',
  reward_count BIGINT NOT NULL DEFAULT 0 COMMENT '奖励数量',
  reward_coins BIGINT NOT NULL DEFAULT 0 COMMENT '金币奖励金额',
  rtp_value_coins BIGINT NOT NULL DEFAULT 0 COMMENT '计入 RTP 的奖励价值',
  candidate_tiers_json JSON NOT NULL COMMENT '候选过滤快照',
  rtp_snapshot_json JSON NOT NULL COMMENT 'RTP 快照',
  prize_metadata_json JSON NOT NULL COMMENT '奖品扩展快照',
  reward_status VARCHAR(32) NOT NULL COMMENT 'pending/granted/failed',
  reward_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包或资产发放交易 ID',
  reward_failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '发放失败原因',
  paid_at_ms BIGINT NOT 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, draw_id),
  UNIQUE KEY uk_wheel_draw_command (app_code, command_id),
  KEY idx_wheel_draw_wheel (app_code, wheel_id, created_at_ms),
  KEY idx_wheel_draw_user (app_code, user_id, created_at_ms),
  KEY idx_wheel_draw_status (app_code, reward_status, updated_at_ms),
  KEY idx_wheel_draw_created (app_code, created_at_ms, draw_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘抽奖事实';

CREATE TABLE IF NOT EXISTS wheel_draw_stats (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  total_draws BIGINT NOT NULL DEFAULT 0 COMMENT '抽奖次数',
  unique_users BIGINT NOT NULL DEFAULT 0 COMMENT '参与用户数',
  total_spent_coins BIGINT NOT NULL DEFAULT 0 COMMENT '消耗金币',
  total_rtp_value_coins BIGINT NOT NULL DEFAULT 0 COMMENT '计入 RTP 的返奖价值',
  pending_draws BIGINT NOT NULL DEFAULT 0 COMMENT '待发放数量',
  granted_draws BIGINT NOT NULL DEFAULT 0 COMMENT '已发放数量',
  failed_draws BIGINT NOT NULL DEFAULT 0 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, wheel_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘后台汇总统计';

CREATE TABLE IF NOT EXISTS wheel_draw_stat_users (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  wheel_id VARCHAR(96) NOT NULL COMMENT '转盘 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, wheel_id, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转盘统计用户去重';

CREATE TABLE IF NOT EXISTS im_broadcast_outbox (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
  scope VARCHAR(32) NOT NULL COMMENT '范围',
  group_id VARCHAR(64) NOT NULL COMMENT '分组 ID',
  broadcast_type VARCHAR(64) NOT NULL COMMENT '广播类型',
  payload_json JSON NOT NULL COMMENT '业务负载 JSON 快照',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次重试时间，UTC epoch ms',
  last_error VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最后一次失败原因',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前锁定 worker',
  locked_until_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, event_id),
  KEY idx_im_broadcast_outbox_pending (app_code, status, next_retry_at_ms, created_at_ms, event_id),
  KEY idx_im_broadcast_outbox_lock (app_code, status, locked_until_ms, created_at_ms, event_id),
  KEY idx_im_broadcast_outbox_retention (app_code, status, updated_at_ms, event_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='IM 广播发件箱表';

CREATE TABLE IF NOT EXISTS game_win_broadcast_configs (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否发送游戏中奖飘屏',
  min_win_coins BIGINT NOT NULL COMMENT '单次返奖达到该金币数才发送飘屏',
  updated_by_admin_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)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游戏中奖飘屏配置';

CREATE TABLE IF NOT EXISTS task_definitions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  task_id VARCHAR(96) NOT NULL COMMENT '任务 ID',
  task_type VARCHAR(32) NOT NULL COMMENT '任务类型',
  category VARCHAR(32) NOT NULL COMMENT '分类',
  metric_type VARCHAR(64) NOT NULL COMMENT '指标类型',
  title VARCHAR(160) NOT NULL COMMENT '标题',
  description VARCHAR(512) NOT NULL DEFAULT '' COMMENT '描述信息',
  audience_type VARCHAR(32) NOT NULL DEFAULT 'all' COMMENT '适用人群：all/newbie',
  icon_key VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'App 任务图标键',
  icon_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'App 任务图标 URL',
  action_type VARCHAR(64) NOT NULL DEFAULT 'none' COMMENT 'App 跳转类型',
  action_param VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'App 跳转参数',
  action_payload_json JSON NULL COMMENT 'App 跳转扩展 JSON',
  dimension_filter_json JSON NULL COMMENT '任务事件维度过滤 JSON',
  target_value BIGINT NOT NULL COMMENT '目标值',
  target_unit VARCHAR(32) NOT NULL COMMENT '目标单位',
  reward_coin_amount BIGINT NOT NULL COMMENT '奖励金币数量',
  reward_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '奖励资产类型：COIN/POINT',
  reward_type VARCHAR(32) NOT NULL DEFAULT 'wallet_asset' COMMENT '奖励类型：wallet_asset/resource/resource_group',
  reward_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励 ID',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源组奖励 ID',
  reward_snapshot_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '资源组 owner 快照 ID',
  reward_snapshot_hash CHAR(64) NOT NULL DEFAULT '' COMMENT '资源组 owner 快照内容哈希',
  reward_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励数量',
  reward_duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励有效期毫秒，0 为永久',
  reward_items_json JSON NULL COMMENT '钱包资源目录解析出的奖励展示快照',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重，数值越大越靠前',
  version BIGINT NOT NULL COMMENT '版本号',
  current_task_version_id BIGINT NOT NULL DEFAULT 0 COMMENT '当前任务版本 ID',
  effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效开始时间，UTC epoch ms',
  effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效结束时间，UTC epoch ms',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  updated_by_admin_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, task_id),
  KEY idx_task_definitions_visible (app_code, task_type, status, sort_order),
  KEY idx_task_definitions_metric (app_code, metric_type, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务定义表';

CREATE TABLE IF NOT EXISTS task_definition_versions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  task_version_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '任务版本 ID',
  task_id VARCHAR(96) NOT NULL COMMENT '任务 ID',
  version BIGINT NOT NULL COMMENT '版本号',
  snapshot_json JSON NOT NULL COMMENT '配置快照 JSON',
  effective_from_cycle VARCHAR(32) NOT NULL COMMENT '生效源周期',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  UNIQUE KEY uk_task_definition_versions_version (app_code, task_id, version),
  KEY idx_task_definition_versions_task (app_code, task_id, task_version_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务定义版本表';

CREATE TABLE IF NOT EXISTS user_task_progress (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  task_id VARCHAR(96) NOT NULL COMMENT '任务 ID',
  task_version_id BIGINT NOT NULL COMMENT '任务版本 ID',
  cycle_key VARCHAR(32) NOT NULL COMMENT '周期键',
  progress_value BIGINT NOT NULL COMMENT '进度值',
  target_value BIGINT NOT NULL COMMENT '目标值',
  reward_coin_amount BIGINT NOT NULL COMMENT '奖励金币数量',
  reward_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '奖励资产类型快照：COIN/POINT',
  reward_type VARCHAR(32) NOT NULL DEFAULT 'wallet_asset' COMMENT '奖励类型快照',
  reward_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励 ID 快照',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源组奖励 ID 快照',
  reward_snapshot_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '资源组 owner 快照 ID',
  reward_snapshot_hash CHAR(64) NOT NULL DEFAULT '' COMMENT '资源组 owner 快照内容哈希',
  reward_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励数量快照',
  reward_duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励有效期快照',
  reward_items_json JSON NULL COMMENT '奖励展示快照',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  completed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '完成时间，UTC epoch ms',
  claimed_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, task_id, cycle_key),
  KEY idx_user_task_progress_user_cycle (app_code, user_id, cycle_key, status),
  KEY idx_user_task_progress_task_cycle (app_code, task_id, cycle_key, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户任务进度表';

CREATE TABLE IF NOT EXISTS task_event_consumption (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
  event_type VARCHAR(96) NOT NULL COMMENT '事件类型',
  source_service VARCHAR(64) NOT NULL COMMENT '来源服务',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  task_day VARCHAR(32) NOT NULL COMMENT '任务天',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  metric_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '任务指标类型',
  value_delta BIGINT NOT NULL DEFAULT 0 COMMENT '本次事件进度增量',
  dimensions_json JSON NULL COMMENT '事件维度快照 JSON',
  skip_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '跳过原因',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  consumed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '消费时间，UTC epoch ms',
  PRIMARY KEY (app_code, event_id),
  KEY idx_task_event_consumption_status (app_code, status, consumed_at_ms),
  KEY idx_task_event_consumption_user_day (app_code, user_id, task_day)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务事件消费位点表';

CREATE TABLE IF NOT EXISTS task_reward_claims (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  claim_id VARCHAR(96) NOT NULL COMMENT '领取 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  task_id VARCHAR(96) NOT NULL COMMENT '任务 ID',
  task_type VARCHAR(32) NOT NULL COMMENT '任务类型',
  cycle_key VARCHAR(32) NOT NULL COMMENT '周期键',
  reward_coin_amount BIGINT NOT NULL COMMENT '奖励金币数量',
  reward_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '奖励资产类型快照：COIN/POINT',
  reward_type VARCHAR(32) NOT NULL DEFAULT 'wallet_asset' COMMENT '奖励类型快照',
  reward_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励 ID 快照',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源组奖励 ID 快照',
  reward_snapshot_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '资源组 owner 快照 ID',
  reward_snapshot_hash CHAR(64) NOT NULL DEFAULT '' COMMENT '资源组 owner 快照内容哈希',
  reward_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励数量快照',
  reward_duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '单资源奖励有效期快照',
  reward_items_json JSON NULL COMMENT '奖励展示快照',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
  wallet_resource_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源赠送 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' 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, claim_id),
  UNIQUE KEY uk_task_reward_claim_command (app_code, command_id),
  UNIQUE KEY uk_task_reward_claim_once (app_code, user_id, task_id, cycle_key),
  KEY idx_task_reward_claim_status (app_code, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务奖励领取表';

CREATE TABLE IF NOT EXISTS registration_reward_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用',
  reward_type VARCHAR(32) NOT NULL DEFAULT 'coin' COMMENT '奖励类型',
  coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '金币数量',
  resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源分组 ID',
  daily_limit BIGINT NOT NULL DEFAULT 0 COMMENT '每日限制',
  updated_by_admin_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)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='注册奖励配置表';

CREATE TABLE IF NOT EXISTS registration_reward_claims (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  claim_id VARCHAR(96) NOT NULL COMMENT '领取 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  reward_day VARCHAR(32) NOT NULL COMMENT '奖励天',
  reward_type VARCHAR(32) NOT NULL COMMENT '奖励类型',
  coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '金币数量',
  resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源分组 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
  resource_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '资源发放 ID',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '失败原因',
  claimed_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, claim_id),
  UNIQUE KEY uk_registration_reward_command (app_code, command_id),
  UNIQUE KEY uk_registration_reward_user_once (app_code, user_id),
  KEY idx_registration_reward_list (app_code, created_at_ms, claim_id),
  KEY idx_registration_reward_status (app_code, status, updated_at_ms),
  KEY idx_registration_reward_day (app_code, reward_day, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='注册奖励领取表';

CREATE TABLE IF NOT EXISTS registration_reward_daily_counters (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  reward_day VARCHAR(32) NOT NULL COMMENT '奖励天',
  reserved_count BIGINT NOT NULL DEFAULT 0 COMMENT '预留数量',
  granted_count BIGINT NOT NULL DEFAULT 0 COMMENT '发放数量',
  failed_count BIGINT NOT NULL DEFAULT 0 COMMENT '失败数量',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, reward_day)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='注册奖励每日计数表';

CREATE TABLE IF NOT EXISTS first_recharge_reward_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用',
  updated_by_admin_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)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='首冲奖励配置表';

CREATE TABLE IF NOT EXISTS first_recharge_reward_tiers (
  tier_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '首冲奖励档位 ID',
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  tier_code VARCHAR(64) NOT NULL COMMENT '档位编码',
  tier_name VARCHAR(96) NOT NULL COMMENT '档位名称',
  min_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '历史字段：最小充值金币数量',
  max_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '最大充值金币数量，0 表示无上限',
  usd_minor_amount BIGINT NOT NULL DEFAULT 0 COMMENT 'Google 商品美元美分档位',
  google_product_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'Google Play 商品 ID',
  discount_percent INT NOT NULL DEFAULT 0 COMMENT '展示优惠百分比，不参与结算',
  resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重，数值越大越靠前',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  UNIQUE KEY uk_first_recharge_reward_tier_code (app_code, tier_code),
  UNIQUE KEY uk_first_recharge_reward_google_product (app_code, google_product_id),
  KEY idx_first_recharge_reward_tier_active (app_code, status, sort_order, usd_minor_amount)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='首冲奖励档位表';

CREATE TABLE IF NOT EXISTS first_recharge_reward_claims (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  claim_id VARCHAR(96) NOT NULL COMMENT '领取 ID',
  event_id VARCHAR(128) NOT NULL COMMENT 'wallet_outbox 事件 ID',
  transaction_id VARCHAR(96) NOT NULL COMMENT '充值交易 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '充值命令 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  tier_id BIGINT NOT NULL COMMENT '命中奖励档位 ID',
  tier_code VARCHAR(64) NOT NULL COMMENT '命中奖励档位编码',
  resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID',
  tier_usd_minor_amount BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位美元美分',
  google_product_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '命中 Google Play 商品 ID',
  recharge_coin_amount BIGINT NOT NULL COMMENT '充值金币数量',
  recharge_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '本次充值美元美分',
  recharge_sequence BIGINT NOT NULL COMMENT '该用户充值序号',
  recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '充值来源类型',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包发奖命令 ID',
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '失败原因',
  recharged_at_ms BIGINT NOT NULL COMMENT '充值发生时间，UTC epoch ms',
  granted_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, claim_id),
  UNIQUE KEY uk_first_recharge_reward_event (app_code, event_id),
  UNIQUE KEY uk_first_recharge_reward_transaction (app_code, transaction_id),
  UNIQUE KEY uk_first_recharge_reward_user_tier (app_code, user_id, tier_id),
  KEY idx_first_recharge_reward_list (app_code, created_at_ms, claim_id),
  KEY idx_first_recharge_reward_status (app_code, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='首冲奖励领取表';

CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用',
  updated_by_admin_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)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励配置表';

CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_tiers (
  tier_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '累充奖励档位 ID',
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  tier_code VARCHAR(64) NOT NULL COMMENT '档位编码',
  tier_name VARCHAR(96) NOT NULL COMMENT '档位名称',
  threshold_usd_minor BIGINT NOT NULL COMMENT '达标美元金额，美分',
  resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重，数值越大越靠前',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  UNIQUE KEY uk_cumulative_recharge_reward_tier_code (app_code, tier_code),
  KEY idx_cumulative_recharge_reward_tier_sort (app_code, status, sort_order, threshold_usd_minor)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励档位表';

CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_events (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  event_id VARCHAR(128) NOT NULL COMMENT 'wallet_outbox 事件 ID',
  cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  transaction_id VARCHAR(128) NOT NULL COMMENT '钱包交易 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '充值来源类型',
  recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '本次到账金币',
  qualifying_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '本次计入累充的美元美分',
  payload_json JSON NULL COMMENT 'wallet 事件 payload',
  occurred_at_ms BIGINT NOT NULL COMMENT '充值发生时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, event_id),
  KEY idx_cumulative_recharge_reward_event_user_cycle (app_code, cycle_key, user_id, occurred_at_ms),
  KEY idx_cumulative_recharge_reward_event_transaction (app_code, transaction_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励充值事件幂等表';

CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_progress (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  total_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计美元美分',
  total_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计到账金币',
  first_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '周期首笔充值时间',
  last_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '周期最近充值时间',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, cycle_key, user_id),
  KEY idx_cumulative_recharge_reward_progress_total (app_code, cycle_key, total_usd_minor)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励用户周期累计表';

CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_grants (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  grant_id VARCHAR(128) NOT NULL COMMENT '发放 ID',
  cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  event_id VARCHAR(128) NOT NULL COMMENT '触发发放的 wallet_outbox 事件 ID',
  transaction_id VARCHAR(128) NOT NULL COMMENT '触发发放的钱包交易 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '触发发放的钱包命令 ID',
  tier_id BIGINT NOT NULL COMMENT '命中奖励档位 ID',
  tier_code VARCHAR(64) NOT NULL COMMENT '命中奖励档位编码',
  threshold_usd_minor BIGINT NOT NULL COMMENT '命中档位门槛，美分',
  resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID',
  reached_usd_minor BIGINT NOT NULL COMMENT '命中时累计金额，美分',
  qualifying_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '触发事件计入金额，美分',
  recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '触发事件到账金币',
  recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '触发事件充值来源类型',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包发奖命令 ID',
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID',
  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
  granted_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, grant_id),
  UNIQUE KEY uk_cumulative_recharge_reward_user_tier (app_code, cycle_key, user_id, tier_id),
  UNIQUE KEY uk_cumulative_recharge_reward_wallet_command (app_code, wallet_command_id),
  KEY idx_cumulative_recharge_reward_grant_event (app_code, event_id, status),
  KEY idx_cumulative_recharge_reward_grant_user (app_code, cycle_key, user_id, created_at_ms),
  KEY idx_cumulative_recharge_reward_grant_status (app_code, status, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励发放表';

CREATE TABLE IF NOT EXISTS seven_day_checkin_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用',
  config_version BIGINT NOT NULL DEFAULT 0 COMMENT '配置版本',
  updated_by_admin_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)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='七日签到配置表';

CREATE TABLE IF NOT EXISTS seven_day_checkin_rewards (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  day_index INT NOT NULL COMMENT '天序号',
  config_version BIGINT NOT NULL COMMENT '配置版本',
  resource_group_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 (app_code, day_index),
  KEY idx_seven_day_checkin_rewards_version (app_code, config_version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='七日签到奖励表';

CREATE TABLE IF NOT EXISTS seven_day_checkin_config_versions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  config_version BIGINT NOT NULL COMMENT '配置版本',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用',
  snapshot_json JSON NOT NULL COMMENT '配置快照 JSON',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, config_version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='七日签到配置版本表';

CREATE TABLE IF NOT EXISTS user_seven_day_checkin_accounts (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  cycle_no BIGINT NOT NULL COMMENT '周期编号',
  cycle_start_day VARCHAR(32) NOT NULL COMMENT '周期开始天',
  last_checkin_day VARCHAR(32) NOT NULL COMMENT '最后签到天',
  last_day_index INT NOT NULL COMMENT '最后天序号',
  config_version BIGINT NOT NULL COMMENT '配置版本',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id),
  KEY idx_user_seven_day_checkin_accounts_day (app_code, last_checkin_day)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户七日签到账户表';

CREATE TABLE IF NOT EXISTS seven_day_checkin_claims (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  claim_id VARCHAR(96) NOT NULL COMMENT '领取 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  cycle_no BIGINT NOT NULL COMMENT '周期编号',
  checkin_day VARCHAR(32) NOT NULL COMMENT '签到天',
  day_index INT NOT NULL COMMENT '天序号',
  config_version BIGINT NOT NULL COMMENT '配置版本',
  resource_group_id BIGINT NOT NULL COMMENT '资源分组 ID',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '失败原因',
  signed_at_ms BIGINT NOT NULL COMMENT '签收时间，UTC epoch ms',
  granted_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, claim_id),
  UNIQUE KEY uk_seven_day_checkin_command (app_code, command_id),
  UNIQUE KEY uk_seven_day_checkin_user_day (app_code, user_id, checkin_day),
  UNIQUE KEY uk_seven_day_checkin_user_cycle_day (app_code, user_id, cycle_no, day_index),
  KEY idx_seven_day_checkin_claims_list (app_code, created_at_ms, claim_id),
  KEY idx_seven_day_checkin_claims_status (app_code, status, updated_at_ms),
  KEY idx_seven_day_checkin_claims_day (app_code, checkin_day, day_index)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='七日签到领取表';

CREATE TABLE IF NOT EXISTS growth_level_tracks (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  name VARCHAR(96) NOT NULL COMMENT '名称',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重，数值越大越靠前',
  display_config_json JSON NULL COMMENT '展示配置 JSON 配置或快照',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, track),
  KEY idx_growth_level_tracks_status_sort (app_code, status, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成长等级赛道表';

CREATE TABLE IF NOT EXISTS growth_level_rules (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  level INT NOT NULL COMMENT '等级',
  required_value BIGINT NOT NULL COMMENT '要求值',
  name VARCHAR(96) NOT NULL COMMENT '名称',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '奖励资源分组 ID',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重，数值越大越靠前',
  display_config_json JSON NULL COMMENT '展示配置 JSON 配置或快照',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  updated_by_admin_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, track, level),
  KEY idx_growth_level_rules_active (app_code, track, status, level),
  KEY idx_growth_level_rules_required (app_code, track, status, required_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成长等级规则表';

CREATE TABLE IF NOT EXISTS growth_level_tiers (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  tier_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '档位 ID',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  min_level INT NOT NULL COMMENT '最小等级',
  max_level INT NOT NULL COMMENT '最大等级',
  name VARCHAR(96) NOT NULL COMMENT '名称',
  display_avatar_frame_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '展示头像框资源 ID',
  display_badge_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '展示徽章资源 ID',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '奖励资源分组 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  display_config_json JSON NULL COMMENT '展示配置 JSON 配置或快照',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  updated_by_admin_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',
  UNIQUE KEY uk_growth_level_tiers_track_range (app_code, track, min_level, max_level),
  KEY idx_growth_level_tiers_active (app_code, track, status, min_level, max_level)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成长等级档位表';

CREATE TABLE IF NOT EXISTS user_growth_level_accounts (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  total_value BIGINT NOT NULL DEFAULT 0 COMMENT '总值',
  current_level INT NOT NULL DEFAULT 0 COMMENT '当前等级',
  current_tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '当前档位 ID',
  level_updated_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '等级更新时间，UTC epoch ms',
  tier_updated_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '档位更新时间，UTC epoch ms',
  version BIGINT NOT NULL DEFAULT 0 COMMENT '版本号',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id, track),
  KEY idx_user_growth_level_accounts_track_level (app_code, track, current_level, total_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户成长等级账户表';

CREATE TABLE IF NOT EXISTS growth_level_value_events (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  value_event_id VARCHAR(160) NOT NULL COMMENT '值事件 ID',
  source_event_id VARCHAR(128) NOT NULL COMMENT '来源事件 ID',
  source_service VARCHAR(64) NOT NULL COMMENT '来源服务',
  source_event_type VARCHAR(96) NOT NULL COMMENT '来源事件类型',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  metric_type VARCHAR(64) NOT NULL COMMENT '指标类型',
  value_delta BIGINT NOT NULL COMMENT '值变动',
  occurred_at_ms BIGINT NOT NULL COMMENT '业务发生时间，UTC epoch ms',
  dimensions_json JSON NULL COMMENT '维度 JSON 配置或快照',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, value_event_id),
  KEY idx_growth_value_user_track (app_code, user_id, track, occurred_at_ms),
  KEY idx_growth_value_source (app_code, source_service, source_event_type, source_event_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成长等级值事件表';

CREATE TABLE IF NOT EXISTS user_growth_level_history (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  history_id VARCHAR(96) NOT NULL COMMENT '历史 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  previous_level INT NOT NULL COMMENT '原等级',
  new_level INT NOT NULL COMMENT '新等级',
  previous_tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '原档位 ID',
  new_tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '新档位 ID',
  total_value BIGINT NOT NULL COMMENT '总值',
  value_event_id VARCHAR(160) NOT NULL COMMENT '值事件 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, history_id),
  KEY idx_growth_history_user_track (app_code, user_id, track, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户成长等级历史表';

CREATE TABLE IF NOT EXISTS growth_level_reward_jobs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  reward_job_id VARCHAR(96) NOT NULL COMMENT '奖励任务 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  track VARCHAR(32) NOT NULL COMMENT '赛道',
  reward_source_type VARCHAR(32) NOT NULL COMMENT '奖励来源类型',
  reward_source_id VARCHAR(96) NOT NULL COMMENT '奖励来源 ID',
  resource_group_id BIGINT NOT NULL COMMENT '资源分组 ID',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID',
  reward_origin VARCHAR(32) NOT NULL DEFAULT 'organic' COMMENT '奖励来源：organic/temporary',
  temporary_level_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '临时等级记录 ID',
  grant_generation INT NOT NULL DEFAULT 0 COMMENT '同一奖励来源的发放代次',
  reward_level INT NOT NULL DEFAULT 0 COMMENT '取得该奖励所需等级',
  is_permanent TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否已提升为永久奖励',
  temporary_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '临时奖励到期时间，UTC epoch ms',
  revoke_status VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT 'none/pending/running/revoked/failed/skipped',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次重试时间，UTC epoch ms',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前锁定 worker',
  locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁定截止时间，UTC epoch ms',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' 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, reward_job_id),
  UNIQUE KEY uk_growth_level_reward_generation (app_code, user_id, track, reward_source_type, reward_source_id, reward_origin, grant_generation),
  KEY idx_growth_level_reward_pending (app_code, status, next_retry_at_ms, created_at_ms),
  KEY idx_growth_level_reward_user (app_code, user_id, track, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成长等级奖励任务表';

CREATE TABLE IF NOT EXISTS growth_level_reward_wallet_grants (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  reward_job_id VARCHAR(96) NOT NULL COMMENT '奖励任务 ID',
  grant_kind VARCHAR(32) NOT NULL COMMENT 'resource_group/avatar_frame/short_badge',
  wallet_grant_id VARCHAR(96) NOT NULL COMMENT '钱包发放 ID',
  revoke_status VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT 'none/pending/running/revoked/failed/skipped',
  revoke_attempt_count INT NOT NULL DEFAULT 0 COMMENT '撤回尝试次数',
  revoke_next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤回重试时间',
  revoke_locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '撤回 worker',
  revoke_locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤回锁截止',
  revoke_failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '撤回失败原因',
  revoked_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤回完成时间',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间',
  PRIMARY KEY (app_code, reward_job_id, wallet_grant_id),
  KEY idx_growth_reward_grant_revoke (app_code, revoke_status, revoke_next_retry_at_ms, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='等级奖励钱包发放明细';

CREATE TABLE IF NOT EXISTS growth_temporary_level_commands (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  command_id VARCHAR(128) NOT NULL COMMENT '整批调整幂等键',
  request_hash VARCHAR(64) NOT NULL COMMENT '规范化请求 SHA256',
  user_id BIGINT NOT NULL COMMENT '目标用户',
  operator_admin_id BIGINT NOT NULL COMMENT '操作管理员',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间',
  PRIMARY KEY (app_code, command_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='临时等级批量命令幂等表';

CREATE TABLE IF NOT EXISTS growth_temporary_levels (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  temporary_level_id VARCHAR(96) NOT NULL COMMENT '临时等级 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '批量命令 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  track VARCHAR(32) NOT NULL COMMENT 'wealth/charm',
  target_level INT NOT NULL COMMENT '临时目标等级',
  target_required_value BIGINT NOT NULL COMMENT '目标等级起始阈值快照',
  baseline_total_value BIGINT NOT NULL COMMENT '调整时真实累计值快照',
  started_at_ms BIGINT NOT NULL COMMENT '有效期开始，包含',
  expires_at_ms BIGINT NOT NULL COMMENT '有效期结束，不包含',
  status VARCHAR(32) NOT NULL COMMENT 'active/superseded/expired',
  generation INT NOT NULL COMMENT '用户轨道临时发放代次',
  operator_admin_id BIGINT NOT NULL COMMENT '操作管理员',
  reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '操作原因',
  final_level INT NOT NULL DEFAULT 0 COMMENT '按基线和有效期经验计算的恢复等级',
  activation_notice_status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '下发通知状态',
  expiry_notice_status VARCHAR(32) NOT NULL DEFAULT 'skipped' COMMENT '到期通知状态',
  attempt_count INT NOT NULL DEFAULT 0 COMMENT '副作用尝试次数',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '副作用重试时间',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前 worker',
  locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁截止时间',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '副作用失败原因',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间',
  PRIMARY KEY (app_code, temporary_level_id),
  UNIQUE KEY uk_growth_temp_command_track (app_code, command_id, track),
  KEY idx_growth_temp_user_track (app_code, user_id, track, status, expires_at_ms),
  KEY idx_growth_temp_work (app_code, status, next_retry_at_ms, expires_at_ms, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户临时成长等级 overlay';

CREATE TABLE IF NOT EXISTS user_level_display_profiles (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  wealth_level INT NOT NULL DEFAULT 0 COMMENT '财富等级',
  wealth_tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '财富档位 ID',
  wealth_avatar_frame_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '财富头像框资源 ID',
  wealth_badge_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '财富徽章资源 ID',
  wealth_badge_source_level INT NOT NULL DEFAULT 0 COMMENT '财富徽章来源等级',
  game_level INT NOT NULL DEFAULT 0 COMMENT '游戏等级',
  game_tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '游戏档位 ID',
  game_avatar_frame_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '游戏头像框资源 ID',
  game_badge_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '游戏徽章资源 ID',
  game_badge_source_level INT NOT NULL DEFAULT 0 COMMENT '游戏徽章来源等级',
  charm_level INT NOT NULL DEFAULT 0 COMMENT '魅力等级',
  charm_tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '魅力档位 ID',
  charm_avatar_frame_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '魅力头像框资源 ID',
  charm_badge_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '魅力徽章资源 ID',
  charm_badge_source_level INT NOT NULL DEFAULT 0 COMMENT '魅力徽章来源等级',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户等级展示资料表';

SET @ddl := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_level_display_profiles' AND COLUMN_NAME = 'wealth_badge_source_level') = 0,
  'ALTER TABLE user_level_display_profiles ADD COLUMN wealth_badge_source_level INT NOT NULL DEFAULT 0 COMMENT ''财富徽章来源等级'' AFTER wealth_badge_resource_id',
  'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @ddl := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_level_display_profiles' AND COLUMN_NAME = 'game_badge_source_level') = 0,
  'ALTER TABLE user_level_display_profiles ADD COLUMN game_badge_source_level INT NOT NULL DEFAULT 0 COMMENT ''游戏徽章来源等级'' AFTER game_badge_resource_id',
  'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @ddl := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_level_display_profiles' AND COLUMN_NAME = 'charm_badge_source_level') = 0,
  'ALTER TABLE user_level_display_profiles ADD COLUMN charm_badge_source_level INT NOT NULL DEFAULT 0 COMMENT ''魅力徽章来源等级'' AFTER charm_badge_resource_id',
  'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

INSERT INTO growth_level_tracks (app_code, track, name, status, sort_order, display_config_json, created_at_ms, updated_at_ms)
VALUES
  ('lalu', 'wealth', '财富等级', 'active', 10, JSON_OBJECT(), 0, 0),
  ('lalu', 'game', '游戏等级', 'active', 20, JSON_OBJECT(), 0, 0),
  ('lalu', 'charm', '魅力等级', 'active', 30, JSON_OBJECT(), 0, 0)
ON DUPLICATE KEY UPDATE
  name = VALUES(name),
  status = VALUES(status),
  sort_order = VALUES(sort_order),
  updated_at_ms = VALUES(updated_at_ms);

CREATE TABLE IF NOT EXISTS achievement_definitions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  achievement_id VARCHAR(96) NOT NULL COMMENT '成就 ID',
  collection_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '集合 ID',
  collection_type VARCHAR(32) NOT NULL COMMENT '集合类型',
  achievement_type VARCHAR(32) NOT NULL COMMENT '成就类型',
  title VARCHAR(160) NOT NULL COMMENT '标题',
  description VARCHAR(512) NOT NULL DEFAULT '' COMMENT '描述信息',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  version BIGINT NOT NULL DEFAULT 1 COMMENT '版本号',
  primary_badge_resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '主徽章资源 ID',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '奖励资源分组 ID',
  auto_pin_policy VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT '自动置顶策略',
  honor_visibility TINYINT(1) NOT NULL DEFAULT 1 COMMENT '荣誉可见性',
  effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效开始时间，UTC epoch ms',
  effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效结束时间，UTC epoch ms',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重，数值越大越靠前',
  display_config_json JSON NULL COMMENT '展示配置 JSON 配置或快照',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
  updated_by_admin_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, achievement_id),
  KEY idx_achievement_definitions_visible (app_code, collection_type, status, sort_order),
  KEY idx_achievement_definitions_effective (app_code, status, effective_from_ms, effective_to_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成就定义表';

CREATE TABLE IF NOT EXISTS achievement_conditions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  condition_id VARCHAR(96) NOT NULL COMMENT '条件 ID',
  achievement_id VARCHAR(96) NOT NULL COMMENT '成就 ID',
  version BIGINT NOT NULL COMMENT '版本号',
  metric_type VARCHAR(64) NOT NULL COMMENT '指标类型',
  target_value BIGINT NOT NULL COMMENT '目标值',
  target_unit VARCHAR(32) NOT NULL COMMENT '目标单位',
  dimension_filter_json JSON NULL COMMENT '维度过滤 JSON 配置或快照',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, condition_id),
  KEY idx_achievement_conditions_achievement (app_code, achievement_id, version),
  KEY idx_achievement_conditions_metric (app_code, metric_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成就条件表';

CREATE TABLE IF NOT EXISTS user_achievement_progress (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  achievement_id VARCHAR(96) NOT NULL COMMENT '成就 ID',
  condition_id VARCHAR(96) NOT NULL COMMENT '条件 ID',
  cycle_key VARCHAR(96) NOT NULL COMMENT '周期键',
  progress_value BIGINT NOT NULL DEFAULT 0 COMMENT '进度值',
  target_value BIGINT NOT NULL COMMENT '目标值',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id, achievement_id, condition_id, cycle_key),
  KEY idx_user_achievement_progress_user (app_code, user_id, cycle_key, status),
  KEY idx_user_achievement_progress_achievement (app_code, achievement_id, cycle_key, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户成就进度表';

CREATE TABLE IF NOT EXISTS user_achievement_unlocks (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  achievement_id VARCHAR(96) NOT NULL COMMENT '成就 ID',
  cycle_key VARCHAR(96) NOT NULL COMMENT '周期键',
  version BIGINT NOT NULL COMMENT '版本号',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  unlocked_at_ms BIGINT NOT NULL COMMENT '解锁时间，UTC epoch ms',
  reward_job_id VARCHAR(96) NOT NULL DEFAULT '' 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, achievement_id, cycle_key),
  KEY idx_user_achievement_unlocks_user (app_code, user_id, unlocked_at_ms),
  KEY idx_user_achievement_unlocks_reward (app_code, reward_job_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户成就解锁表';

CREATE TABLE IF NOT EXISTS achievement_event_consumption (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
  event_type VARCHAR(96) NOT NULL COMMENT '事件类型',
  source_service VARCHAR(64) NOT NULL COMMENT '来源服务',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  metric_type VARCHAR(64) NOT NULL COMMENT '指标类型',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  skip_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '跳过原因',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  consumed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '消费时间，UTC epoch ms',
  PRIMARY KEY (app_code, event_id),
  KEY idx_achievement_event_status (app_code, status, consumed_at_ms),
  KEY idx_achievement_event_user (app_code, user_id, metric_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成就事件消费位点表';

CREATE TABLE IF NOT EXISTS achievement_reward_jobs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  reward_job_id VARCHAR(96) NOT NULL COMMENT '奖励任务 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  achievement_id VARCHAR(96) NOT NULL COMMENT '成就 ID',
  cycle_key VARCHAR(96) NOT NULL COMMENT '周期键',
  resource_group_id BIGINT NOT NULL COMMENT '资源分组 ID',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次重试时间，UTC epoch ms',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前锁定 worker',
  locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁定截止时间，UTC epoch ms',
  failure_reason VARCHAR(255) NOT NULL DEFAULT '' 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, reward_job_id),
  UNIQUE KEY uk_achievement_reward_once (app_code, user_id, achievement_id, cycle_key),
  KEY idx_achievement_reward_pending (app_code, status, next_retry_at_ms, created_at_ms),
  KEY idx_achievement_reward_user (app_code, user_id, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成就奖励任务表';

CREATE TABLE IF NOT EXISTS user_badge_display_slots (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码，用于多租户隔离',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  slot VARCHAR(32) NOT NULL COMMENT '槽位',
  position INT NOT NULL COMMENT '位置',
  badge_form VARCHAR(32) NOT NULL COMMENT '徽章形态',
  resource_id BIGINT NOT NULL COMMENT '资源 ID',
  entitlement_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '权益 ID',
  source_type VARCHAR(32) NOT NULL COMMENT '来源类型',
  source_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '来源 ID',
  pin_mode VARCHAR(32) NOT NULL DEFAULT '' COMMENT '置顶模式',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, user_id, slot, position),
  UNIQUE KEY uk_user_badge_display_resource (app_code, user_id, slot, resource_id),
  KEY idx_user_badge_display_user (app_code, user_id, slot, updated_at_ms),
  KEY idx_user_badge_display_resource (app_code, resource_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户徽章展示槽位表';

CREATE TABLE IF NOT EXISTS message_templates (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  template_id VARCHAR(96) NOT NULL COMMENT '模板 ID',
  template_version VARCHAR(64) NOT NULL COMMENT '模板版本',
  message_type VARCHAR(32) NOT NULL COMMENT '消息类型',
  locale VARCHAR(32) NOT NULL DEFAULT '' COMMENT '本地化语言',
  title VARCHAR(160) NOT NULL COMMENT '标题',
  summary VARCHAR(512) NOT NULL COMMENT '摘要',
  body VARCHAR(2048) NOT NULL DEFAULT '' COMMENT '正文',
  icon_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '图标 URL',
  image_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '图片 URL',
  action_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '操作类型',
  action_param VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '操作参数',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  created_by VARCHAR(64) NOT NULL DEFAULT '' 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, template_id, template_version),
  KEY idx_message_templates_type_status (app_code, message_type, status),
  KEY idx_message_templates_template_status (app_code, template_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='消息模板表';

CREATE TABLE IF NOT EXISTS user_inbox_messages (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  inbox_message_id VARCHAR(96) NOT NULL COMMENT '站内信消息 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  message_type VARCHAR(32) NOT NULL COMMENT '消息类型',
  producer VARCHAR(64) NOT NULL COMMENT '生产者',
  producer_event_id VARCHAR(128) NOT NULL COMMENT '生产者事件 ID',
  producer_event_type VARCHAR(96) NOT NULL DEFAULT '' COMMENT '生产者事件类型',
  aggregate_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '聚合类型',
  aggregate_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '聚合 ID',
  template_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '模板 ID',
  template_version VARCHAR(64) NOT NULL DEFAULT '' COMMENT '模板版本',
  title VARCHAR(160) NOT NULL COMMENT '标题',
  summary VARCHAR(512) NOT NULL COMMENT '摘要',
  body VARCHAR(2048) NOT NULL DEFAULT '' COMMENT '正文',
  icon_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '图标 URL',
  image_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '图片 URL',
  action_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '操作类型',
  action_param VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '操作参数',
  priority INT NOT NULL DEFAULT 0 COMMENT '优先级',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  read_at_ms BIGINT NULL COMMENT '读取时间，UTC epoch ms',
  deleted_at_ms BIGINT NULL COMMENT '删除时间，UTC epoch ms',
  sent_at_ms BIGINT NOT NULL COMMENT '发送时间，UTC epoch ms',
  expire_at_ms BIGINT NULL COMMENT '过期时间，UTC epoch ms',
  metadata_json JSON NULL COMMENT '扩展元数据 JSON',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, inbox_message_id),
  UNIQUE KEY uk_user_inbox_producer_event (app_code, user_id, producer, producer_event_id),
  KEY idx_user_inbox_list (app_code, user_id, message_type, deleted_at_ms, status, sent_at_ms, inbox_message_id),
  KEY idx_user_inbox_unread (app_code, user_id, message_type, read_at_ms, deleted_at_ms, status, expire_at_ms),
  KEY idx_user_inbox_aggregate (app_code, user_id, aggregate_type, aggregate_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户站内信消息表';

CREATE TABLE IF NOT EXISTS message_fanout_jobs (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
  job_id VARCHAR(96) NOT NULL COMMENT '任务 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
  message_type VARCHAR(32) NOT NULL COMMENT '消息类型',
  target_scope VARCHAR(64) NOT NULL COMMENT '目标范围',
  target_filter_json JSON NOT NULL COMMENT '目标过滤 JSON 配置或快照',
  template_snapshot_json JSON NOT NULL COMMENT '模板快照 JSON 配置或快照',
  status VARCHAR(32) NOT NULL COMMENT '业务状态',
  attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数',
  cursor_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '游标用户 ID',
  total_count BIGINT NOT NULL DEFAULT 0 COMMENT '总数量',
  success_count BIGINT NOT NULL DEFAULT 0 COMMENT '成功数量',
  failure_count BIGINT NOT NULL DEFAULT 0 COMMENT '失败数量',
  batch_size INT NOT NULL DEFAULT 500 COMMENT '批次大小',
  next_run_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一个运行时间，UTC epoch ms',
  locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '当前锁定 worker',
  locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁定截止时间，UTC epoch ms',
  error_message VARCHAR(512) NOT NULL DEFAULT '' COMMENT '错误消息',
  created_by VARCHAR(64) 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, job_id),
  UNIQUE KEY uk_message_fanout_command (app_code, command_id),
  KEY idx_message_fanout_status (app_code, status, next_run_at_ms, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='消息分发任务表';

CREATE TABLE IF NOT EXISTS message_action_confirms (
  app_code VARCHAR(32) NOT NULL COMMENT 'App 租户编码',
  confirm_id VARCHAR(96) NOT NULL COMMENT 'App 操作确认 ID',
  source_name VARCHAR(64) NOT NULL COMMENT '来源事实名，例如 user_outbox',
  source_event_id VARCHAR(128) NOT NULL COMMENT '来源 outbox event_id',
  business_type VARCHAR(64) NOT NULL COMMENT '业务类型，例如 role_invitation',
  business_subtype VARCHAR(64) NOT NULL COMMENT '业务子类型，例如 host/agency/bd',
  business_id VARCHAR(128) NOT NULL COMMENT '业务 owner 的事实 ID',
  sender_user_id BIGINT NOT NULL COMMENT 'IM 发送方用户 ID',
  receiver_user_id BIGINT NOT NULL COMMENT 'IM 接收方用户 ID',
  message_text VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'IM 展示文案快照',
  status VARCHAR(32) NOT NULL COMMENT 'pending/processing/accepted/rejected/expired/canceled/failed',
  action VARCHAR(32) NOT NULL DEFAULT '' COMMENT '终态动作 accept/reject',
  command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '处理动作 command_id',
  processed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '处理完成 UTC epoch ms',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'processing 锁持有者',
  lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'processing 锁过期 UTC epoch ms',
  error_message VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最后一次处理失败原因',
  metadata_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, confirm_id),
  UNIQUE KEY uk_message_action_source (app_code, source_name, source_event_id),
  KEY idx_message_action_receiver_status (app_code, receiver_user_id, status, created_at_ms, confirm_id),
  KEY idx_message_action_conversation (app_code, receiver_user_id, sender_user_id, created_at_ms, confirm_id),
  KEY idx_message_action_lock (app_code, status, lock_until_ms, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='App IM 操作确认消息状态';

CREATE TABLE IF NOT EXISTS message_action_outbox (
  app_code VARCHAR(32) NOT NULL COMMENT 'App 租户编码',
  event_id VARCHAR(128) NOT NULL COMMENT '确认消息 outbox 事件 ID',
  confirm_id VARCHAR(96) NOT NULL COMMENT '关联 confirm_id',
  event_type VARCHAR(96) NOT NULL COMMENT '事件类型，例如 ConfirmMessageCreated',
  status VARCHAR(32) NOT NULL COMMENT 'pending/running/retryable/delivered/failed',
  worker_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'MQ 投递 worker ID',
  lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'MQ 投递锁过期 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 VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最后一次投递失败原因',
  payload_json JSON NOT NULL COMMENT '投递给 notice-service 的确认 IM 快照',
  created_at_ms BIGINT NOT NULL COMMENT '创建 UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新 UTC epoch ms',
  PRIMARY KEY (app_code, event_id),
  UNIQUE KEY uk_message_action_outbox_confirm (app_code, confirm_id, event_type),
  KEY idx_message_action_outbox_status_created (app_code, status, next_retry_at_ms, created_at_ms, event_id),
  KEY idx_message_action_outbox_lock (app_code, status, lock_until_ms, created_at_ms, event_id),
  KEY idx_message_action_outbox_retention (app_code, status, updated_at_ms, event_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='确认消息 IM 投递 outbox';

CREATE TABLE IF NOT EXISTS room_turnover_reward_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '配置区域 ID；0 表示全区域默认配置',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用',
  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 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, region_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励配置表';

CREATE TABLE IF NOT EXISTS room_turnover_reward_tiers (
  tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '档位 ID',
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '配置区域 ID；0 表示全区域默认配置',
  tier_code VARCHAR(64) NOT NULL COMMENT '档位编码',
  tier_name VARCHAR(128) NOT NULL COMMENT '档位名称',
  threshold_coin_spent BIGINT NOT NULL COMMENT '命中该档需要的房间送礼金币流水',
  reward_coin_amount BIGINT NOT NULL COMMENT '奖励房主金币数',
  status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'active/inactive',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (tier_id),
  UNIQUE KEY uk_room_turnover_reward_tier_code (app_code, region_id, tier_code),
  KEY idx_room_turnover_reward_tiers_match (app_code, region_id, status, threshold_coin_spent)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励档位表';

CREATE TABLE IF NOT EXISTS room_turnover_reward_event_consumption (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id',
  event_type VARCHAR(96) NOT NULL COMMENT '事件类型',
  room_id VARCHAR(96) NOT NULL COMMENT '房间 ID',
  period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始',
  coin_spent BIGINT NOT NULL COMMENT '本事件送礼金币消耗',
  status VARCHAR(32) NOT NULL COMMENT '消费状态',
  consumed_at_ms BIGINT NOT 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',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '事件发生时房间区域 ID',
  PRIMARY KEY (app_code, event_id),
  KEY idx_room_turnover_reward_event_period (app_code, period_start_ms, room_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励事件消费幂等表';

CREATE TABLE IF NOT EXISTS room_turnover_reward_progress (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '事件发生时房间区域 ID；0 表示全区域可见',
  room_id VARCHAR(96) NOT NULL COMMENT '房间 ID',
  period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始',
  period_end_ms BIGINT NOT NULL COMMENT 'UTC 周期结束',
  coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '本周期房间送礼金币流水',
  last_event_at_ms BIGINT NOT NULL DEFAULT 0 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, region_id, room_id, period_start_ms),
  KEY idx_room_turnover_reward_progress_period (app_code, period_start_ms, coin_spent)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励周期聚合表';

CREATE TABLE IF NOT EXISTS room_turnover_reward_settlements (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '结算对应房间区域 ID；0 表示全区域可见',
  settlement_id VARCHAR(96) NOT NULL COMMENT '结算 ID',
  room_id VARCHAR(96) NOT NULL COMMENT '房间 ID',
  owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '结算收款房主',
  period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始',
  period_end_ms BIGINT NOT NULL COMMENT 'UTC 周期结束',
  coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '周期房间流水',
  tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位 ID',
  tier_code VARCHAR(64) NOT NULL DEFAULT '' COMMENT '命中档位编码',
  threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位阈值',
  reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '发放金币',
  status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT 'pending/granted/failed',
  wallet_command_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT 'wallet-service 幂等命令 ID',
  wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
  settled_at_ms BIGINT NOT NULL DEFAULT 0 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, settlement_id),
  UNIQUE KEY uk_room_turnover_reward_settlement_room_period (app_code, region_id, room_id, period_start_ms),
  KEY idx_room_turnover_reward_settlement_region (app_code, region_id, period_start_ms, created_at_ms),
  KEY idx_room_turnover_reward_settlement_status (app_code, status, period_start_ms, created_at_ms),
  KEY idx_room_turnover_reward_settlement_owner (app_code, owner_user_id, period_start_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励每周结算表';

CREATE TABLE IF NOT EXISTS weekly_star_cycles (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID',
  activity_code VARCHAR(64) NOT NULL DEFAULT 'weekly_star' COMMENT '活动编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域 ID，0 表示默认配置',
  title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '周期标题',
  status VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '状态',
  start_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 生效开始，包含',
  end_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 生效结束，不包含',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员',
  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新管理员',
  settled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '结算完成时间',
  locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '结算 worker 锁',
  lock_until_ms BIGINT NOT NULL DEFAULT 0 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, cycle_id),
  KEY idx_weekly_star_cycle_current (app_code, activity_code, status, region_id, start_ms, end_ms),
  KEY idx_weekly_star_cycle_due (app_code, activity_code, status, end_ms, lock_until_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星指定礼物积分周期';

CREATE TABLE IF NOT EXISTS weekly_star_cycle_gifts (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID',
  gift_id VARCHAR(96) NOT NULL COMMENT '参与计分礼物 ID',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '展示顺序',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, cycle_id, gift_id),
  KEY idx_weekly_star_gift_match (app_code, gift_id, cycle_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星周期指定礼物';

CREATE TABLE IF NOT EXISTS weekly_star_cycle_rewards (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID',
  rank_no INT NOT NULL COMMENT '排名，1/2/3',
  resource_group_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 (app_code, cycle_id, rank_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星周期 Top 奖励';

CREATE TABLE IF NOT EXISTS weekly_star_user_scores (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  score BIGINT NOT NULL DEFAULT 0 COMMENT '累计积分，等于活动礼物消耗金币',
  first_scored_at_ms BIGINT NOT NULL COMMENT '首次得分时间',
  last_scored_at_ms 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, cycle_id, user_id),
  KEY idx_weekly_star_score_rank (app_code, cycle_id, score, first_scored_at_ms, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星用户积分榜';

CREATE TABLE IF NOT EXISTS weekly_star_score_events (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  source_event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id',
  cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID',
  user_id BIGINT NOT NULL COMMENT '送礼用户 ID',
  gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID',
  score_delta BIGINT NOT NULL COMMENT '本次增加积分',
  occurred_at_ms BIGINT NOT NULL COMMENT '事件发生时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, source_event_id),
  KEY idx_weekly_star_score_event_cycle (app_code, cycle_id, user_id, occurred_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星送礼积分事件幂等表';

CREATE TABLE IF NOT EXISTS weekly_star_settlements (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  settlement_id VARCHAR(96) NOT NULL COMMENT '周星结算 ID',
  cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID',
  rank_no INT NOT NULL COMMENT '排名，1/2/3',
  user_id BIGINT NOT NULL COMMENT '获奖用户 ID',
  score BIGINT NOT NULL DEFAULT 0 COMMENT '结算积分',
  resource_group_id BIGINT NOT NULL COMMENT '奖励资源组 ID',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT 'wallet 幂等命令',
  wallet_grant_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'wallet grant ID',
  status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '发放状态',
  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
  attempt_count INT NOT NULL DEFAULT 0 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, settlement_id),
  UNIQUE KEY uk_weekly_star_settlement_rank (app_code, cycle_id, rank_no),
  UNIQUE KEY uk_weekly_star_wallet_command (app_code, wallet_command_id),
  KEY idx_weekly_star_settlement_cycle (app_code, cycle_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星 Top 奖励结算';

CREATE TABLE IF NOT EXISTS cp_weekly_rank_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  activity_code VARCHAR(64) NOT NULL DEFAULT 'cp_weekly_rank' COMMENT '活动编码',
  enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
  relation_type VARCHAR(32) NOT NULL DEFAULT 'cp' COMMENT '关系类型，当前固定 cp',
  top_count INT NOT NULL DEFAULT 3 COMMENT '结算 Top 数量',
  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 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='CP 周榜配置表';

CREATE TABLE IF NOT EXISTS cp_weekly_rank_rewards (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  rank_no INT NOT NULL COMMENT '名次',
  resource_group_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 (app_code, rank_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='CP 周榜名次奖励资源组表';

CREATE TABLE IF NOT EXISTS cp_weekly_rank_settlements (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  settlement_id VARCHAR(96) NOT NULL COMMENT '发奖记录 ID',
  period_start_ms BIGINT NOT NULL COMMENT '周周期开始，UTC epoch ms',
  period_end_ms BIGINT NOT NULL COMMENT '周周期结束，UTC epoch ms',
  rank_no INT NOT NULL COMMENT '名次',
  relationship_id VARCHAR(128) NOT NULL COMMENT '获奖 CP 关系 ID',
  user_id BIGINT NOT NULL COMMENT '获奖用户 ID',
  score BIGINT NOT NULL DEFAULT 0 COMMENT '关系周榜分数',
  resource_group_id BIGINT NOT NULL COMMENT '发放资源组 ID',
  wallet_command_id VARCHAR(192) NOT NULL COMMENT 'wallet 发奖幂等键',
  wallet_grant_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'wallet grant ID',
  status VARCHAR(32) NOT NULL COMMENT 'pending/running/granted/failed',
  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
  attempt_count INT NOT NULL DEFAULT 0 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, settlement_id),
  UNIQUE KEY uk_cp_weekly_rank_period_user (app_code, period_start_ms, rank_no, relationship_id, user_id),
  UNIQUE KEY uk_cp_weekly_rank_wallet_command (app_code, wallet_command_id),
  KEY idx_cp_weekly_rank_pending (app_code, period_start_ms, period_end_ms, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='CP 周榜发奖事实表';

CREATE TABLE IF NOT EXISTS agency_opening_cycles (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '配置区域 ID；0 表示全区域默认活动',
  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
  activity_code VARCHAR(64) NOT NULL DEFAULT 'agency_opening' COMMENT '活动编码',
  title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '周期标题',
  status VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT 'draft/active/disabled/settling/settled',
  start_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 开始，包含',
  end_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 结束，不包含',
  min_host_count INT NOT NULL DEFAULT 10 COMMENT '申请要求的有效主播数',
  max_agency_age_days INT NOT NULL DEFAULT 7 COMMENT '代理创建后允许申请的最大天数，0 表示不限制',
  created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员',
  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新管理员',
  settled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '结算完成时间',
  locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '结算 worker 锁',
  lock_until_ms BIGINT NOT NULL DEFAULT 0 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, cycle_id),
  KEY idx_agency_opening_cycle_current (app_code, region_id, activity_code, status, start_ms, end_ms),
  KEY idx_agency_opening_cycle_due (app_code, activity_code, status, end_ms, lock_until_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业活动周期';

CREATE TABLE IF NOT EXISTS agency_opening_cycle_rewards (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
  rank_no INT NOT NULL COMMENT '档位序号',
  threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '命中该档需要的代理房间流水金币',
  reward_coin_amount BIGINT NOT NULL DEFAULT 0 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, cycle_id, rank_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业流水奖励档位';

CREATE TABLE IF NOT EXISTS agency_opening_applications (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '申请时代理实际区域 ID',
  application_id VARCHAR(96) NOT NULL COMMENT '申请 ID',
  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
  agency_id BIGINT NOT NULL COMMENT '代理 ID',
  agency_owner_user_id BIGINT NOT NULL COMMENT '代理 owner 用户 ID',
  agency_name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '代理名称快照',
  host_count INT NOT NULL DEFAULT 0 COMMENT '申请时有效主播数快照',
  agency_created_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '代理创建时间快照',
  status VARCHAR(32) NOT NULL DEFAULT 'applied' COMMENT 'applied/approved/pending/granted/failed/expired',
  score_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '周期内开业流水金币',
  reward_rank_no INT NOT NULL DEFAULT 0 COMMENT '结算榜单名次',
  reward_threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '结算命中的流水阈值',
  reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '结算奖励金币',
  wallet_command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包幂等命令',
  wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
  applied_at_ms BIGINT NOT NULL COMMENT '申请时间',
  approved_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '后台同意时间',
  score_start_ms BIGINT NOT NULL DEFAULT 0 COMMENT '计分开始时间',
  score_end_ms BIGINT NOT NULL DEFAULT 0 COMMENT '计分截止时间',
  reviewed_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '审核管理员',
  granted_at_ms BIGINT NOT NULL DEFAULT 0 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, application_id),
  UNIQUE KEY uk_agency_opening_owner_once (app_code, agency_owner_user_id),
  KEY idx_agency_opening_wallet_command (app_code, wallet_command_id),
  KEY idx_agency_opening_application_owner (app_code, agency_owner_user_id, applied_at_ms),
  KEY idx_agency_opening_agency_cycle (app_code, cycle_id, agency_id),
  KEY idx_agency_opening_application_rank (app_code, cycle_id, score_coin_amount, applied_at_ms, agency_id),
  KEY idx_agency_opening_application_status (app_code, cycle_id, status, updated_at_ms),
  KEY idx_agency_opening_application_region (app_code, region_id, updated_at_ms, application_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业申请和结算事实';

CREATE TABLE IF NOT EXISTS agency_opening_score_events (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  source_event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id',
  cycle_id VARCHAR(96) NOT NULL COMMENT '代理开业周期 ID',
  application_id VARCHAR(96) NOT NULL COMMENT '命中的申请 ID',
  agency_id BIGINT NOT NULL COMMENT '代理 ID',
  target_user_id BIGINT NOT NULL COMMENT '收礼主播用户 ID',
  score_delta BIGINT NOT NULL COMMENT '本次流水金币',
  occurred_at_ms BIGINT NOT NULL COMMENT '事件发生时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  region_id BIGINT NOT NULL DEFAULT 0 COMMENT '事件发生时房间区域 ID',
  PRIMARY KEY (app_code, source_event_id),
  KEY idx_agency_opening_score_event_application (app_code, application_id, occurred_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='代理开业流水事件幂等表';

CREATE TABLE IF NOT EXISTS invite_activity_reward_configs (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否启用邀请活动',
  per_invite_inviter_reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '每邀请一人邀请人即时奖励金币',
  per_invite_invitee_reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '每邀请一人被邀请人即时奖励金币',
  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 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 invite_activity_reward_tiers (
  tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '档位自增 ID',
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  reward_type VARCHAR(32) NOT NULL COMMENT 'recharge/valid_invite',
  tier_code VARCHAR(64) NOT NULL COMMENT '档位编码',
  tier_name VARCHAR(128) NOT NULL COMMENT '档位展示名称',
  threshold_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值金币门槛',
  threshold_valid_invite_count BIGINT NOT NULL DEFAULT 0 COMMENT '有效邀请人数门槛',
  reward_coin_amount BIGINT NOT NULL COMMENT '奖励金币数量',
  status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'active/inactive',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '展示排序',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (tier_id),
  UNIQUE KEY uk_invite_activity_reward_tier_code (app_code, tier_code),
  KEY idx_invite_activity_reward_tier_sort (app_code, reward_type, status, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='邀请活动奖励档位';

CREATE TABLE IF NOT EXISTS invite_activity_reward_events (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  event_id VARCHAR(128) NOT NULL COMMENT '上游 outbox event_id',
  event_type VARCHAR(64) NOT NULL COMMENT 'WalletRechargeRecorded/UserInvited/UserInviteBecameValid',
  cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然月，如 2026-06',
  invited_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '被邀请人用户 ID',
  inviter_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '邀请人用户 ID',
  transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '充值钱包交易 ID',
  command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '充值钱包命令 ID',
  recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '充值来源',
  recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '本次充值金币',
  status VARCHAR(32) NOT NULL DEFAULT 'consumed' COMMENT 'consumed/skipped',
  skip_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '跳过原因',
  payload_json JSON NULL COMMENT '原始上游 payload',
  occurred_at_ms BIGINT NOT NULL COMMENT '事件发生时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, event_id),
  KEY idx_invite_activity_reward_event_inviter (app_code, cycle_key, inviter_user_id, occurred_at_ms),
  KEY idx_invite_activity_reward_event_invited (app_code, invited_user_id, occurred_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='邀请活动事件幂等表';

CREATE TABLE IF NOT EXISTS invite_activity_reward_progress (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然月，如 2026-06',
  user_id BIGINT NOT NULL COMMENT '邀请人用户 ID',
  total_recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '本月邀请用户累计充值金币',
  valid_invite_count BIGINT NOT NULL DEFAULT 0 COMMENT '本月新增有效邀请人数',
  claimed_reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '本月已领取奖励金币',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, cycle_key, user_id),
  KEY idx_invite_activity_reward_progress_recharge (app_code, cycle_key, total_recharge_coin_amount),
  KEY idx_invite_activity_reward_progress_valid (app_code, cycle_key, valid_invite_count)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='邀请活动用户月度进度';

CREATE TABLE IF NOT EXISTS invite_activity_reward_claims (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  claim_id VARCHAR(128) NOT NULL COMMENT '领取 ID',
  cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然月，如 2026-06',
  user_id BIGINT NOT NULL COMMENT '邀请人用户 ID',
  reward_type VARCHAR(32) NOT NULL COMMENT 'recharge/valid_invite/invite_inviter/invite_invitee',
  command_id VARCHAR(128) NOT NULL COMMENT 'H5 领取或系统即时发奖命令 ID',
  tier_id BIGINT NOT NULL COMMENT '领取档位 ID；即时邀请奖励使用对方用户 ID 做幂等维度',
  tier_code VARCHAR(64) NOT NULL COMMENT '领取档位编码或即时奖励类型',
  tier_name VARCHAR(128) NOT NULL COMMENT '领取档位名称或即时奖励名称',
  threshold_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值金币门槛',
  threshold_valid_invite_count BIGINT NOT NULL DEFAULT 0 COMMENT '有效邀请人数门槛',
  reached_value BIGINT NOT NULL DEFAULT 0 COMMENT '领取时已达成值',
  reward_coin_amount BIGINT NOT NULL COMMENT '本次实际发放金币',
  status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT 'pending/granted/failed',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包发奖命令 ID',
  wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
  failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
  granted_at_ms BIGINT NOT NULL DEFAULT 0 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, claim_id),
  UNIQUE KEY uk_invite_activity_reward_user_tier (app_code, cycle_key, user_id, reward_type, tier_id),
  UNIQUE KEY uk_invite_activity_reward_wallet_command (app_code, wallet_command_id),
  KEY idx_invite_activity_reward_claim_user (app_code, cycle_key, user_id, created_at_ms),
  KEY idx_invite_activity_reward_claim_status (app_code, status, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='邀请活动金币领取记录';

-- 活动模版配置和发布版本由 activity-service 统一持久化；admin-server 只能通过 AdminActivityTemplateService 访问。
CREATE TABLE IF NOT EXISTS activity_templates (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  template_code VARCHAR(64) NOT NULL COMMENT 'App 内唯一业务编码',
  name VARCHAR(128) NOT NULL COMMENT '后台内部名称',
  activity_type VARCHAR(32) NOT NULL DEFAULT 'gift_challenge' COMMENT '活动类型',
  status VARCHAR(24) NOT NULL DEFAULT 'draft' COMMENT 'draft/published/disabled/archived',
  start_ms BIGINT NOT NULL DEFAULT 0 COMMENT '活动开始，UTC epoch ms，包含',
  end_ms BIGINT NOT NULL DEFAULT 0 COMMENT '活动结束，UTC epoch ms，不包含',
  all_regions BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否覆盖全部区域',
  daily_leaderboard_size INT NOT NULL DEFAULT 100 COMMENT '日榜最多展示人数',
  total_leaderboard_size INT NOT NULL DEFAULT 100 COMMENT '总榜最多展示人数',
  display_config_json JSON NOT NULL COMMENT '客户端布局和样式配置',
  revision BIGINT NOT NULL DEFAULT 1 COMMENT '后台编辑乐观锁版本',
  published_version BIGINT NOT NULL DEFAULT 0 COMMENT '最近发布快照版本',
  created_by_admin_id BIGINT NOT NULL COMMENT '创建管理员',
  updated_by_admin_id BIGINT NOT NULL COMMENT '最后更新管理员',
  published_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '最近发布管理员',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  published_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最近发布时间，UTC epoch ms',
  archived_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '软归档时间，UTC epoch ms',
  PRIMARY KEY (app_code, template_id),
  UNIQUE KEY uk_activity_template_code (app_code, template_code),
  KEY idx_activity_template_list (app_code, status, updated_at_ms, template_id),
  KEY idx_activity_template_period (app_code, status, start_ms, end_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='可排期运营活动模版实例';

-- 发布互斥行按 App 串行化“检查重叠 + 写入 published”。仅锁候选活动行会出现两个草稿并发发布时互相不可见的写偏差。
CREATE TABLE IF NOT EXISTS activity_template_publish_locks (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  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 activity_template_regions (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  region_id BIGINT NOT NULL COMMENT '投放区域 ID',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  PRIMARY KEY (app_code, template_id, region_id),
  KEY idx_activity_template_region_match (app_code, region_id, template_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版投放区域';

CREATE TABLE IF NOT EXISTS activity_template_locales (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  locale VARCHAR(24) NOT NULL COMMENT 'BCP-47 基础语言码',
  title VARCHAR(160) NOT NULL DEFAULT '' COMMENT '客户端活动标题',
  rules MEDIUMTEXT 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, template_id, locale)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版多语言文案';

CREATE TABLE IF NOT EXISTS activity_template_gifts (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  gift_id VARCHAR(96) NOT NULL COMMENT 'wallet 礼物 ID',
  sort_order INT NOT NULL DEFAULT 0 COMMENT '展示顺序',
  name VARCHAR(128) NOT NULL DEFAULT '' COMMENT '发布展示名称快照',
  icon_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '发布展示图标快照',
  coin_price BIGINT NOT NULL DEFAULT 0 COMMENT '发布时金币价格快照，仅供展示',
  price_version VARCHAR(64) NOT NULL DEFAULT '' 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, template_id, gift_id),
  KEY idx_activity_template_gift_match (app_code, gift_id, template_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版指定礼物和展示快照';

CREATE TABLE IF NOT EXISTS activity_template_tasks (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  task_key VARCHAR(64) NOT NULL COMMENT '模版内稳定任务键',
  task_type VARCHAR(32) NOT NULL COMMENT 'daily_visit/gift_count/gift_coin_amount',
  target_value BIGINT NOT NULL DEFAULT 0 COMMENT '任务达成阈值',
  reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT 'wallet 奖励资源组 ID',
  sort_order INT NOT NULL DEFAULT 0 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, template_id, task_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版每日任务配置';

CREATE TABLE IF NOT EXISTS activity_template_rank_rewards (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  board_type VARCHAR(16) NOT NULL COMMENT 'daily/total',
  rank_from INT NOT NULL COMMENT '奖励起始名次，闭区间',
  rank_to INT NOT NULL COMMENT '奖励结束名次，闭区间',
  resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT 'wallet 奖励资源组 ID',
  sort_order INT NOT NULL DEFAULT 0 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, template_id, board_type, rank_from, rank_to)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版日榜和总榜名次奖励';

CREATE TABLE IF NOT EXISTS activity_template_assets (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  asset_key VARCHAR(64) NOT NULL COMMENT '素材位键',
  locale VARCHAR(24) NOT NULL DEFAULT '*' COMMENT '* 表示共享素材，否则为语言码',
  url VARCHAR(1024) NOT NULL COMMENT 'COS/CDN 素材地址',
  media_type VARCHAR(16) NOT NULL COMMENT 'image/webp/svga/pag',
  sort_order INT NOT NULL DEFAULT 0 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, template_id, asset_key, locale)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版客户端素材';

CREATE TABLE IF NOT EXISTS activity_template_versions (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  template_id VARCHAR(96) NOT NULL COMMENT '活动模版 ID',
  version_no BIGINT NOT NULL COMMENT '单模版递增发布版本',
  snapshot_json JSON NOT NULL COMMENT '发布时完整不可变配置快照',
  published_by_admin_id BIGINT NOT NULL COMMENT '发布管理员',
  published_at_ms BIGINT NOT NULL COMMENT '发布时间，UTC epoch ms',
  PRIMARY KEY (app_code, template_id, version_no),
  KEY idx_activity_template_version_list (app_code, template_id, published_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版不可变发布版本';

-- 活动模版真实运行时、任务、榜单结算及统计事实 outbox。
-- Activity-template runtime facts are version-bound. Configuration edits never rewrite these tables.
CREATE TABLE IF NOT EXISTS activity_template_runtime_versions (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  start_ms BIGINT NOT NULL,
  end_ms BIGINT NOT NULL,
  all_regions BOOLEAN NOT NULL DEFAULT FALSE,
  runtime_from_ms BIGINT NOT NULL,
  runtime_to_ms BIGINT NOT NULL DEFAULT 0,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no),
  KEY idx_activity_template_runtime_current (app_code, template_code, start_ms, end_ms, runtime_from_ms, runtime_to_ms),
  KEY idx_activity_template_runtime_due (app_code, end_ms, runtime_to_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版不可变运行版本启停窗口';

CREATE TABLE IF NOT EXISTS activity_template_runtime_regions (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  version_no BIGINT NOT NULL,
  region_id BIGINT NOT NULL,
  created_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, region_id),
  KEY idx_activity_template_runtime_region (app_code, region_id, template_id, version_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版运行版本区域快照';

CREATE TABLE IF NOT EXISTS activity_template_event_consumption (
  app_code VARCHAR(32) NOT NULL,
  source_event_id VARCHAR(128) NOT NULL,
  event_type VARCHAR(64) NOT NULL,
  template_id VARCHAR(96) NOT NULL DEFAULT '',
  template_code VARCHAR(64) NOT NULL DEFAULT '',
  version_no BIGINT NOT NULL DEFAULT 0,
  user_id BIGINT NOT NULL DEFAULT 0,
  region_id BIGINT NOT NULL DEFAULT 0,
  task_day VARCHAR(10) NOT NULL DEFAULT '',
  status VARCHAR(24) NOT NULL,
  skip_reason VARCHAR(128) NOT NULL DEFAULT '',
  occurred_at_ms BIGINT NOT NULL,
  consumed_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, source_event_id),
  KEY idx_activity_template_event_template (app_code, template_id, version_no, occurred_at_ms),
  KEY idx_activity_template_event_status (app_code, status, consumed_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版运行事件幂等事实';

CREATE TABLE IF NOT EXISTS activity_template_user_day_scores (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  task_day VARCHAR(10) NOT NULL,
  day_start_ms BIGINT NOT NULL,
  day_end_ms BIGINT NOT NULL,
  user_id BIGINT NOT NULL,
  score BIGINT NOT NULL DEFAULT 0,
  gift_count BIGINT NOT NULL DEFAULT 0,
  coin_amount BIGINT NOT NULL DEFAULT 0,
  first_scored_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, task_day, user_id),
  KEY idx_activity_template_day_rank (app_code, template_id, version_no, task_day, score DESC, first_scored_at_ms, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版 UTC 日榜实时分数';

CREATE TABLE IF NOT EXISTS activity_template_user_total_scores (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  user_id BIGINT NOT NULL,
  score BIGINT NOT NULL DEFAULT 0,
  gift_count BIGINT NOT NULL DEFAULT 0,
  coin_amount BIGINT NOT NULL DEFAULT 0,
  first_scored_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, user_id),
  KEY idx_activity_template_total_rank (app_code, template_id, version_no, score DESC, first_scored_at_ms, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版活动总榜实时分数';

CREATE TABLE IF NOT EXISTS activity_template_daily_visits (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  task_day VARCHAR(10) NOT NULL,
  user_id BIGINT NOT NULL,
  region_id BIGINT NOT NULL DEFAULT 0,
  command_id VARCHAR(128) NOT NULL,
  visited_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, task_day, user_id),
  UNIQUE KEY uk_activity_template_visit_command (app_code, command_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版 daily_visit 自然幂等事实';

CREATE TABLE IF NOT EXISTS activity_template_task_progress (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  task_day VARCHAR(10) NOT NULL,
  user_id BIGINT NOT NULL,
  first_region_id BIGINT NOT NULL DEFAULT 0,
  task_key VARCHAR(64) NOT NULL,
  task_type VARCHAR(32) NOT NULL,
  target_value BIGINT NOT NULL,
  progress_value BIGINT NOT NULL DEFAULT 0,
  reward_resource_group_id BIGINT NOT NULL,
  reward_snapshot_id VARCHAR(96) NOT NULL DEFAULT '',
  reward_snapshot_json JSON NULL,
  sort_order INT NOT NULL DEFAULT 0,
  status VARCHAR(24) NOT NULL,
  completed_at_ms BIGINT NOT NULL DEFAULT 0,
  earning_region_id BIGINT NOT NULL DEFAULT 0,
  attribution_at_ms BIGINT NOT NULL DEFAULT 0,
  claimed_at_ms BIGINT NOT NULL DEFAULT 0,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, task_day, user_id, task_key),
  KEY idx_activity_template_task_data (app_code, template_id, version_no, task_day, task_key, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版用户每日任务进度';

CREATE TABLE IF NOT EXISTS activity_template_task_claims (
  app_code VARCHAR(32) NOT NULL,
  claim_id VARCHAR(96) NOT NULL,
  command_id VARCHAR(128) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  task_day VARCHAR(10) NOT NULL,
  task_key VARCHAR(64) NOT NULL,
  user_id BIGINT NOT NULL,
  earning_region_id BIGINT NOT NULL DEFAULT 0,
  attribution_at_ms BIGINT NOT NULL DEFAULT 0,
  reward_resource_group_id BIGINT NOT NULL,
  reward_snapshot_id VARCHAR(96) NOT NULL DEFAULT '',
  reward_snapshot_json JSON NULL,
  wallet_command_id VARCHAR(160) NOT NULL,
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '',
  status VARCHAR(24) NOT NULL,
  failure_reason VARCHAR(512) NOT NULL DEFAULT '',
  attempt_count INT NOT NULL DEFAULT 0,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  granted_at_ms BIGINT NOT NULL DEFAULT 0,
  PRIMARY KEY (app_code, claim_id),
  UNIQUE KEY uk_activity_template_claim_command (app_code, command_id),
  UNIQUE KEY uk_activity_template_claim_task (app_code, template_id, version_no, task_day, user_id, task_key),
  UNIQUE KEY uk_activity_template_claim_wallet (app_code, wallet_command_id),
  KEY idx_activity_template_claim_status (app_code, status, updated_at_ms),
  KEY idx_activity_template_claim_admin (app_code, template_id, version_no, task_day, task_key, user_id, status, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版任务资源组领奖事实';

CREATE TABLE IF NOT EXISTS activity_template_rank_periods (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  board_type VARCHAR(16) NOT NULL,
  period_key VARCHAR(24) NOT NULL,
  period_start_ms BIGINT NOT NULL,
  period_end_ms BIGINT NOT NULL,
  settle_after_ms BIGINT NOT NULL COMMENT '结算水位：周期结束加允许迟到窗口，UTC epoch ms',
  leaderboard_size INT NOT NULL,
  status VARCHAR(24) NOT NULL,
  locked_by VARCHAR(128) NOT NULL DEFAULT '',
  lock_until_ms BIGINT NOT NULL DEFAULT 0,
  settled_at_ms BIGINT NOT NULL DEFAULT 0,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, board_type, period_key),
  KEY idx_activity_template_period_settle_due (app_code, status, settle_after_ms, lock_until_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版榜单结算周期';

CREATE TABLE IF NOT EXISTS activity_template_rank_snapshots (
  app_code VARCHAR(32) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  board_type VARCHAR(16) NOT NULL,
  period_key VARCHAR(24) NOT NULL,
  rank_no INT NOT NULL,
  user_id BIGINT NOT NULL,
  score BIGINT NOT NULL,
  gift_count BIGINT NOT NULL,
  coin_amount BIGINT NOT NULL,
  first_scored_at_ms BIGINT NOT NULL,
  snapshot_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, template_id, version_no, board_type, period_key, rank_no),
  UNIQUE KEY uk_activity_template_rank_user (app_code, template_id, version_no, board_type, period_key, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版冻结榜单快照';

CREATE TABLE IF NOT EXISTS activity_template_reward_jobs (
  app_code VARCHAR(32) NOT NULL,
  reward_job_id VARCHAR(96) NOT NULL,
  template_id VARCHAR(96) NOT NULL,
  template_code VARCHAR(64) NOT NULL,
  version_no BIGINT NOT NULL,
  board_type VARCHAR(16) NOT NULL,
  period_key VARCHAR(24) NOT NULL,
  rank_no INT NOT NULL,
  user_id BIGINT NOT NULL,
  score BIGINT NOT NULL,
  resource_group_id BIGINT NOT NULL,
  reward_snapshot_id VARCHAR(96) NOT NULL DEFAULT '',
  reward_snapshot_json JSON NULL,
  wallet_command_id VARCHAR(192) NOT NULL,
  wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '',
  status VARCHAR(24) NOT NULL,
  failure_reason VARCHAR(512) NOT NULL DEFAULT '',
  attempt_count INT NOT NULL DEFAULT 0,
  max_attempts INT NOT NULL DEFAULT 8 COMMENT '自动投递总尝试上限；dead 手工复活时只扩一轮预算',
  next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次可领取时间，UTC epoch ms',
  locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前 job lease owner',
  lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'job lease 过期时间，UTC epoch ms',
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  granted_at_ms BIGINT NOT NULL DEFAULT 0,
  PRIMARY KEY (app_code, reward_job_id),
  UNIQUE KEY uk_activity_template_reward_rank (app_code, template_id, version_no, board_type, period_key, rank_no),
  UNIQUE KEY uk_activity_template_reward_wallet (app_code, wallet_command_id),
  KEY idx_activity_template_reward_query (app_code, template_id, version_no, board_type, period_key, status),
  KEY idx_activity_template_reward_retry (app_code, status, updated_at_ms),
  KEY idx_activity_template_reward_claim (app_code, status, next_retry_at_ms, lock_until_ms, created_at_ms, reward_job_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版榜单奖励发放任务';

CREATE TABLE IF NOT EXISTS activity_template_stats_outbox (
  outbox_id VARCHAR(96) NOT NULL,
  app_code VARCHAR(32) NOT NULL,
  event_type VARCHAR(64) NOT NULL,
  payload BLOB NOT NULL,
  status VARCHAR(24) NOT NULL,
  retry_count INT NOT NULL DEFAULT 0,
  next_retry_at_ms BIGINT NOT NULL,
  locked_by VARCHAR(128) NOT NULL DEFAULT '',
  lock_until_ms BIGINT NOT NULL DEFAULT 0,
  last_error VARCHAR(512) NOT NULL DEFAULT '',
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (outbox_id),
  KEY idx_activity_template_stats_outbox_claim (status, next_retry_at_ms, lock_until_ms, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动模版统计事实 RocketMQ transactional outbox';
