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)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动事件 outbox 表';

CREATE TABLE IF NOT EXISTS lucky_gift_rules (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  gift_id VARCHAR(96) NOT NULL COMMENT '奖池 ID；当前列名沿用旧内部作用域名',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用',
  rule_version BIGINT NOT NULL COMMENT '规则版本',
  gift_price BIGINT NOT NULL COMMENT '单次抽奖消耗金币',
  target_rtp_ppm INT NOT NULL COMMENT '基础 RTP 目标，ppm',
  pool_rate_ppm INT NOT NULL COMMENT '基础奖池入池比例，ppm',
  global_window_draws BIGINT NOT NULL COMMENT '全站 RTP 窗口抽数',
  gift_window_draws BIGINT NOT NULL COMMENT '礼物 RTP 子窗口抽数',
  novice_draw_limit BIGINT NOT NULL COMMENT '新手池截止抽数',
  intermediate_draw_limit BIGINT NOT NULL COMMENT '中级池截止抽数',
  high_multiplier BIGINT NOT NULL COMMENT '高倍判定倍率',
  high_water_pool_multiple BIGINT NOT NULL COMMENT '高倍开启所需奖池水位倍数',
  platform_pool_weight_ppm INT NOT NULL COMMENT '平台池基础返奖责任权重',
  room_pool_weight_ppm INT NOT NULL COMMENT '房间池基础返奖责任权重',
  gift_pool_weight_ppm INT NOT NULL COMMENT '礼物池基础返奖责任权重',
  initial_platform_pool BIGINT NOT NULL COMMENT '平台池初始水位',
  initial_gift_pool BIGINT NOT NULL COMMENT '礼物池初始水位',
  initial_room_pool BIGINT NOT NULL COMMENT '房间池初始水位',
  platform_reserve BIGINT NOT NULL COMMENT '平台池安全水位',
  gift_reserve BIGINT NOT NULL COMMENT '礼物池安全水位',
  room_reserve BIGINT NOT NULL COMMENT '房间池安全水位',
  max_single_payout BIGINT NOT NULL COMMENT '单次最大奖励',
  user_hourly_payout_cap BIGINT NOT NULL COMMENT '用户小时奖励上限',
  user_daily_payout_cap BIGINT NOT NULL COMMENT '用户日奖励上限',
  device_daily_payout_cap BIGINT NOT NULL COMMENT '设备日奖励上限',
  room_hourly_payout_cap BIGINT NOT NULL COMMENT '房间小时奖励上限',
  anchor_daily_payout_cap BIGINT NOT NULL COMMENT '主播关联日奖励上限',
  room_atmosphere_rate_ppm INT NOT NULL COMMENT '房间气氛池入池比例',
  room_atmosphere_initial BIGINT NOT NULL COMMENT '房间气氛池初始预算',
  room_atmosphere_reserve BIGINT NOT NULL COMMENT '房间气氛池安全水位',
  activity_budget BIGINT NOT NULL COMMENT '活动补贴预算',
  activity_daily_limit BIGINT NOT NULL COMMENT '活动补贴日上限',
  large_tier_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否开启高倍奖档',
  tiers_json JSON NOT NULL COMMENT '倍率生成奖档快照；权重由 RTP 窗口运行时生成',
  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, gift_id),
  KEY idx_lucky_gift_rules_enabled (app_code, enabled, updated_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物规则表';

CREATE TABLE IF NOT EXISTS lucky_gift_rule_versions (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID',
  rule_version BIGINT NOT NULL COMMENT '不可变规则版本',
  enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用',
  target_rtp_ppm BIGINT NOT NULL COMMENT '基础返奖目标，ppm',
  pool_rate_ppm BIGINT NOT NULL COMMENT '每笔扣费进入基础奖池比例，ppm',
  settlement_window_wager BIGINT NOT NULL COMMENT 'RTP 结算窗口流水，单位金币',
  control_band_ppm BIGINT NOT NULL COMMENT '正常波动带，ppm',
  gift_price_reference BIGINT NOT NULL COMMENT '配置参考礼物价格',
  novice_max_equivalent_draws BIGINT NOT NULL DEFAULT 2000 COMMENT '新手阶段截止等价抽数，按累计金币/参考价格折算',
  normal_max_equivalent_draws BIGINT NOT NULL DEFAULT 20000 COMMENT '正常阶段截止等价抽数，超过后进入高阶阶段',
  max_single_payout BIGINT NOT NULL DEFAULT 50000 COMMENT '单次基础返奖上限，按参考价格配置',
  user_hourly_payout_cap BIGINT NOT NULL DEFAULT 34200 COMMENT '单用户每小时基础返奖上限，按参考价格配置',
  user_daily_payout_cap BIGINT NOT NULL DEFAULT 615600 COMMENT '单用户每日基础返奖上限，按参考价格配置',
  device_daily_payout_cap BIGINT NOT NULL DEFAULT 1026000 COMMENT '单设备每日基础返奖上限，按参考价格配置',
  room_hourly_payout_cap BIGINT NOT NULL DEFAULT 684000 COMMENT '单房间每小时基础返奖上限，按参考价格配置',
  anchor_daily_payout_cap BIGINT NOT NULL DEFAULT 12312000 COMMENT '单主播每日基础返奖上限，按参考价格配置',
  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, pool_id, rule_version),
  KEY idx_lucky_gift_rule_versions_latest (app_code, pool_id, rule_version),
  KEY idx_lucky_gift_rule_versions_enabled (app_code, enabled, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物 v2 规则版本表';

CREATE TABLE IF NOT EXISTS lucky_gift_stage_tiers (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID',
  rule_version BIGINT NOT NULL COMMENT '规则版本',
  stage VARCHAR(32) NOT NULL COMMENT 'novice/normal/advanced',
  tier_id VARCHAR(96) NOT NULL COMMENT '奖档 ID',
  multiplier_ppm BIGINT NOT NULL COMMENT '倍率，1x = 1000000',
  base_weight_ppm BIGINT NOT NULL COMMENT '正常模式基础概率，ppm',
  reward_source VARCHAR(32) NOT NULL COMMENT 'base_rtp/activity_subsidy/presentation_only',
  high_water_only TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否高水位才开放',
  broadcast_level VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT 'none/room/region/global',
  enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
  PRIMARY KEY (app_code, pool_id, rule_version, stage, tier_id),
  KEY idx_lucky_gift_stage_tiers_stage (app_code, pool_id, rule_version, stage)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物 v2 阶段奖档表';

CREATE TABLE IF NOT EXISTS lucky_rtp_windows (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  scope_type VARCHAR(32) NOT NULL COMMENT 'global 或 gift',
  scope_id VARCHAR(96) NOT NULL COMMENT 'global 或规则作用域',
  window_index BIGINT NOT NULL COMMENT 'RTP 窗口序号',
  target_rtp_ppm INT 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 COMMENT '窗口目标基础返奖',
  actual_base_payout_coins BIGINT NOT NULL DEFAULT 0 COMMENT '窗口实际基础返奖',
  carry_ppm BIGINT NOT NULL DEFAULT 0 COMMENT '整数除法余数',
  status VARCHAR(32) NOT NULL DEFAULT 'open' COMMENT 'open/closed/underpaid',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, scope_type, scope_id, window_index),
  KEY idx_lucky_rtp_windows_open (app_code, scope_type, scope_id, status, window_index)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物 RTP 控制窗口';

CREATE TABLE IF NOT EXISTS lucky_pools (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  scope_type VARCHAR(32) NOT NULL COMMENT 'platform/room/gift',
  scope_id VARCHAR(96) NOT NULL COMMENT 'global/room_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 '累计基础返奖支出',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, scope_type, scope_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物三层基础奖池';

CREATE TABLE IF NOT EXISTS lucky_room_atmosphere_pools (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  room_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 '累计气氛支出',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物房间气氛池';

CREATE TABLE IF NOT EXISTS lucky_activity_budgets (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  gift_id VARCHAR(96) NOT NULL COMMENT '奖池 ID；当前列名沿用旧内部作用域名',
  budget_day VARCHAR(32) NOT NULL COMMENT 'UTC 预算日；__total__ 表示活动总预算',
  budget_coins BIGINT NOT NULL DEFAULT 0 COMMENT '总补贴预算',
  spent_coins BIGINT NOT NULL DEFAULT 0 COMMENT '已支出补贴',
  daily_limit BIGINT NOT NULL DEFAULT 0 COMMENT '日支出上限',
  daily_spent_coins BIGINT NOT NULL DEFAULT 0 COMMENT '当日已支出',
  status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'active/paused/exhausted',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, gift_id, budget_day)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物活动补贴预算';

CREATE TABLE IF NOT EXISTS lucky_user_states (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  user_id BIGINT NOT NULL COMMENT '用户 ID',
  gift_id VARCHAR(96) NOT NULL COMMENT '奖池 ID；当前列名沿用旧内部作用域名',
  paid_draws BIGINT NOT NULL DEFAULT 0 COMMENT '该用户幸运礼物累计付费抽数',
  cumulative_wager_coins BIGINT NOT NULL DEFAULT 0 COMMENT '该用户在当前奖池累计消耗金币',
  equivalent_draws BIGINT NOT NULL DEFAULT 0 COMMENT '累计金币按规则参考价格折算后的等价抽数',
  loss_streak 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, user_id, gift_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物用户体验池状态';

CREATE TABLE IF NOT EXISTS lucky_risk_counters (
  app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码',
  scope_type VARCHAR(32) NOT NULL COMMENT 'user/device/room/anchor',
  scope_id VARCHAR(128) NOT NULL COMMENT '风控主体 ID',
  window_type VARCHAR(32) NOT NULL COMMENT 'hour/day',
  bucket_key VARCHAR(32) NOT NULL COMMENT 'UTC 窗口键',
  payout_coins 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, scope_type, scope_id, window_type, bucket_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物风控窗口计数';

CREATE TABLE IF NOT EXISTS lucky_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',
  room_id VARCHAR(96) NOT NULL COMMENT '房间 ID',
  anchor_id VARCHAR(96) NOT NULL COMMENT '主播关联 ID',
  pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID',
  gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID',
  coin_spent BIGINT NOT NULL COMMENT '消耗金币',
  rule_version BIGINT NOT NULL COMMENT '规则版本',
  experience_pool VARCHAR(32) NOT NULL COMMENT '体验池',
  rtp_window_index BIGINT NOT NULL COMMENT '全站 RTP 窗口',
  gift_rtp_window_index BIGINT NOT NULL COMMENT '礼物 RTP 窗口',
  selected_tier_id VARCHAR(96) NOT NULL COMMENT '命中奖档',
  base_reward_coins BIGINT NOT NULL DEFAULT 0 COMMENT '基础 RTP 返奖',
  room_atmosphere_reward_coins BIGINT NOT NULL DEFAULT 0 COMMENT '房间气氛支出',
  activity_subsidy_coins BIGINT NOT NULL DEFAULT 0 COMMENT '活动补贴支出',
  effective_reward_coins BIGINT NOT NULL DEFAULT 0 COMMENT '用户可见总奖励',
  budget_sources_json JSON NOT NULL COMMENT '预算来源',
  stage_feedback TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否阶段反馈',
  high_multiplier TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否高倍命中',
  candidate_tiers_json JSON NOT NULL COMMENT '候选过滤快照',
  pool_snapshot_json JSON NOT NULL COMMENT '奖池快照',
  rtp_snapshot_json JSON NOT NULL COMMENT 'RTP 快照',
  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_lucky_draw_command (app_code, command_id),
  KEY idx_lucky_draw_pool (app_code, pool_id, created_at_ms),
  KEY idx_lucky_draw_user (app_code, user_id, created_at_ms),
  KEY idx_lucky_draw_gift (app_code, gift_id, created_at_ms),
  KEY idx_lucky_draw_room (app_code, room_id, created_at_ms),
  KEY idx_lucky_draw_status (app_code, reward_status, updated_at_ms)
) 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),
  KEY idx_im_broadcast_outbox_lock (app_code, status, locked_until_ms, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='IM 广播发件箱表';

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 '描述信息',
  target_value BIGINT NOT NULL COMMENT '目标值',
  target_unit VARCHAR(32) NOT NULL COMMENT '目标单位',
  reward_coin_amount BIGINT NOT 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 '奖励金币数量',
  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 '业务状态',
  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 '奖励金币数量',
  wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID',
  wallet_transaction_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 COMMENT '最小充值金币数量',
  max_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '最大充值金币数量，0 表示无上限',
  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),
  KEY idx_first_recharge_reward_tier_active (app_code, status, sort_order, min_coin_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',
  recharge_coin_amount BIGINT NOT NULL 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_once (app_code, user_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 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',
  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_once (app_code, user_id, track, reward_source_type, reward_source_id),
  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 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',
  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',
  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',
  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='用户等级展示资料表';

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='消息分发任务表';

-- 本地开发必须开箱即可验证幸运礼物链路；INSERT IGNORE 只补缺省奖池，不覆盖后台已发布规则。
SET @lucky_seed_now_ms := 1779259000000;
SET @lucky_seed_tiers := JSON_ARRAY(
  JSON_OBJECT('pool', 'novice', 'tier_id', 'novice_none', 'reward_coins', 0, 'multiplier_ppm', 0, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'novice', 'tier_id', 'novice_1x', 'reward_coins', 100, 'multiplier_ppm', 1000000, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'novice', 'tier_id', 'novice_2x', 'reward_coins', 200, 'multiplier_ppm', 2000000, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'intermediate', 'tier_id', 'intermediate_none', 'reward_coins', 0, 'multiplier_ppm', 0, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'intermediate', 'tier_id', 'intermediate_1x', 'reward_coins', 100, 'multiplier_ppm', 1000000, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'intermediate', 'tier_id', 'intermediate_2x', 'reward_coins', 200, 'multiplier_ppm', 2000000, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'advanced', 'tier_id', 'advanced_none', 'reward_coins', 0, 'multiplier_ppm', 0, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'advanced', 'tier_id', 'advanced_1x', 'reward_coins', 100, 'multiplier_ppm', 1000000, 'weight', 0, 'high_water_only', false, 'enabled', true),
  JSON_OBJECT('pool', 'advanced', 'tier_id', 'advanced_2x', 'reward_coins', 200, 'multiplier_ppm', 2000000, 'weight', 0, 'high_water_only', false, 'enabled', true)
);
INSERT IGNORE INTO lucky_gift_rules (
  app_code, gift_id, enabled, rule_version, gift_price, target_rtp_ppm, pool_rate_ppm,
  global_window_draws, gift_window_draws, novice_draw_limit, intermediate_draw_limit,
  high_multiplier, high_water_pool_multiple, platform_pool_weight_ppm, room_pool_weight_ppm,
  gift_pool_weight_ppm, initial_platform_pool, initial_gift_pool, initial_room_pool,
  platform_reserve, gift_reserve, room_reserve, max_single_payout, user_hourly_payout_cap,
  user_daily_payout_cap, device_daily_payout_cap, room_hourly_payout_cap, anchor_daily_payout_cap,
  room_atmosphere_rate_ppm, room_atmosphere_initial, room_atmosphere_reserve,
  activity_budget, activity_daily_limit, large_tier_enabled, tiers_json,
  updated_by_admin_id, created_at_ms, updated_at_ms
) VALUES
  ('lalu', 'lucky', true, 1, 100, 950000, 950000, 100000, 100000, 2000, 20000, 100, 2, 200000, 300000, 500000, 9500000, 23750000, 5000000, 1000000, 1000000, 100000, 50000, 3420000, 61560000, 102600000, 68400000, 1231200000, 10000, 100000, 10000, 0, 0, true, @lucky_seed_tiers, 0, @lucky_seed_now_ms, @lucky_seed_now_ms),
  ('lalu', 'super_lucky', true, 1, 100, 950000, 950000, 100000, 100000, 2000, 20000, 100, 2, 200000, 300000, 500000, 9500000, 23750000, 5000000, 1000000, 1000000, 100000, 50000, 3420000, 61560000, 102600000, 68400000, 1231200000, 10000, 100000, 10000, 0, 0, true, @lucky_seed_tiers, 0, @lucky_seed_now_ms, @lucky_seed_now_ms);
