package luckygift

const (
	DefaultPoolID = "default"

	StatusDraft   = "draft"
	StatusActive  = "active"
	StatusPaused  = "paused"
	StatusClosed  = "closed"
	StatusPending = "pending"
	StatusGranted = "granted"
	StatusFailed  = "failed"

	PoolNovice       = "novice"
	PoolIntermediate = "intermediate"
	PoolAdvanced     = "advanced"

	StageNovice   = "novice"
	StageNormal   = "normal"
	StageAdvanced = "advanced"

	// StrategyFixedV2 保留现网不可变规则的原始语义；只有显式发布 StrategyDynamicV3 才启用动态水位、充值加权和多维风控。
	StrategyFixedV2   = "fixed_v2"
	StrategyDynamicV3 = "dynamic_v3"

	PoolAdjustmentIn  = "in"
	PoolAdjustmentOut = "out"

	EventTypeLuckyGiftDrawn            = "LuckyGiftDrawn"
	EventTypeLuckyGiftRewardSettlement = "LuckyGiftRewardSettlement"
	EventTypeExternalLuckyGiftDrawn    = "ExternalLuckyGiftDrawn"
)

// Tier 是单个体验池里的候选奖档；权重只塑造体验节奏，基础成本仍由 RTP 窗口兜住。
type Tier struct {
	Pool          string `json:"pool"`
	TierID        string `json:"tier_id"`
	RewardCoins   int64  `json:"reward_coins"`
	MultiplierPPM int64  `json:"multiplier_ppm"`
	Weight        int64  `json:"weight"`
	HighWaterOnly bool   `json:"high_water_only"`
	Enabled       bool   `json:"enabled"`
}

// Config 是幸运礼物线上规则快照。金额均为整数金币，比例均为 ppm。
type Config struct {
	AppCode         string `json:"app_code"`
	GiftID          string `json:"gift_id"`
	PoolID          string `json:"pool_id"`
	Enabled         bool   `json:"enabled"`
	RuleVersion     int64  `json:"rule_version"`
	StrategyVersion string `json:"strategy_version"`
	GiftPrice       int64  `json:"gift_price"`
	TargetRTPPPM    int64  `json:"target_rtp_ppm"`
	PoolRatePPM     int64  `json:"pool_rate_ppm"`
	ProfitRatePPM   int64  `json:"profit_rate_ppm"`
	AnchorRatePPM   int64  `json:"anchor_rate_ppm"`
	ControlBandPPM  int64  `json:"control_band_ppm"`
	// SettlementWindowWager 是 dynamic_v3 结算窗口的真实金币流水阈值；不能按参考礼物价格换算成抽数。
	SettlementWindowWager     int64 `json:"settlement_window_wager"`
	GlobalWindowDraws         int64 `json:"global_window_draws"`
	GiftWindowDraws           int64 `json:"gift_window_draws"`
	NoviceMaxEquivalentDraws  int64 `json:"novice_max_equivalent_draws"`
	NormalMaxEquivalentDraws  int64 `json:"normal_max_equivalent_draws"`
	HighMultiplier            int64 `json:"high_multiplier"`
	HighWaterPoolMultiple     int64 `json:"high_water_pool_multiple"`
	InitialBasePool           int64 `json:"initial_base_pool"`
	BasePoolReserve           int64 `json:"base_pool_reserve"`
	InitialPoolCoins          int64 `json:"initial_pool_coins"`
	LossStreakGuarantee       int64 `json:"loss_streak_guarantee"`
	LowWatermarkCoins         int64 `json:"low_watermark_coins"`
	LowWaterNonzeroFactorPPM  int64 `json:"low_water_nonzero_factor_ppm"`
	HighWatermarkCoins        int64 `json:"high_watermark_coins"`
	HighWaterNonzeroFactorPPM int64 `json:"high_water_nonzero_factor_ppm"`
	// V2HighWaterBoost* 只由 fixed_v2 解释：奖池水位越过阈值后，中奖返奖金额按系数加权（RTP 等比放大），
	// 滞回保持到水位跌破恢复线才退出；阈值为 0 表示关闭。dynamic_v3 有独立水位因子，不读这三个字段。
	V2HighWaterBoostThresholdCoins int64 `json:"v2_high_water_boost_threshold_coins"`
	V2HighWaterBoostFactorPPM      int64 `json:"v2_high_water_boost_factor_ppm"`
	V2HighWaterBoostRecoverCoins   int64 `json:"v2_high_water_boost_recover_coins"`
	RechargeBoostWindowMS          int64 `json:"recharge_boost_window_ms"`
	RechargeBoostFactorPPM         int64 `json:"recharge_boost_factor_ppm"`
	// User24HourRTPThresholdPPM/Factor 只调整普通非零奖档；大奖资格和保底仍由各自策略独立决定。
	User24HourRTPThresholdPPM      int64   `json:"user_24h_rtp_threshold_ppm"`
	User24HourOrdinaryWinFactorPPM int64   `json:"user_24h_ordinary_win_factor_ppm"`
	JackpotMultiplierPPMs          []int64 `json:"jackpot_multiplier_ppms"`
	JackpotGlobalRTPMaxPPM         int64   `json:"jackpot_global_rtp_max_ppm"`
	JackpotUserRoundRTPMaxPPM      int64   `json:"jackpot_user_round_rtp_max_ppm"`
	JackpotUser48hRTPMaxPPM        int64   `json:"jackpot_user_48h_rtp_max_ppm"`
	// Deprecated aliases only keep in-process callers built against the previous draft source-compatible.
	// Persistence, protobuf and runtime decisions use the round/48h fields above; these aliases never create a second rule meaning.
	JackpotUserDayRTPMaxPPM int64 `json:"-"`
	JackpotUser72hRTPMaxPPM int64 `json:"-"`
	// SettledRoundRTPEligibility marks configs received through the round/48h contract.
	// It is transport metadata only: persistence stores the two canonical limits and reconstructs this marker on read.
	SettledRoundRTPEligibility bool  `json:"-"`
	JackpotSpendThresholdCoins int64 `json:"jackpot_spend_threshold_coins"`
	MaxJackpotHitsPerUserDay   int64 `json:"max_jackpot_hits_per_user_day"`
	// JackpotRateLimitWindowMinutes/MaxJackpotHitsPerWindow 是 app+pool 全局滚动窗口；
	// 两类大奖和所有并行规则版本共享额度，防止通过切换用户、实验组或大奖机制绕过爆奖节流。
	JackpotRateLimitWindowMinutes int64   `json:"jackpot_rate_limit_window_minutes"`
	MaxJackpotHitsPerWindow       int64   `json:"max_jackpot_hits_per_window"`
	MaxSinglePayout               int64   `json:"max_single_payout"`
	UserHourlyPayoutCap           int64   `json:"user_hourly_payout_cap"`
	UserDailyPayoutCap            int64   `json:"user_daily_payout_cap"`
	DeviceDailyPayoutCap          int64   `json:"device_daily_payout_cap"`
	RoomHourlyPayoutCap           int64   `json:"room_hourly_payout_cap"`
	AnchorDailyPayoutCap          int64   `json:"anchor_daily_payout_cap"`
	MultiplierPPMs                []int64 `json:"multiplier_ppms"`
	// Stages 保留 dynamic_v3 的充值门槛；Tiers 仍是 fixed_v2 候选选择使用的扁平运行结构。
	Stages           []RuleStage `json:"stages"`
	Tiers            []Tier      `json:"tiers"`
	UpdatedByAdminID int64       `json:"updated_by_admin_id"`
	CreatedAtMS      int64       `json:"created_at_ms"`
	UpdatedAtMS      int64       `json:"updated_at_ms"`
}

// RuleTier 是 v2 配置契约里的阶段奖档。倍率和概率在服务端内部统一用 ppm 保存。
type RuleTier struct {
	Stage         string `json:"stage"`
	TierID        string `json:"tier_id"`
	MultiplierPPM int64  `json:"multiplier_ppm"`
	BaseWeightPPM int64  `json:"base_weight_ppm"`
	HighWaterOnly bool   `json:"high_water_only"`
	Enabled       bool   `json:"enabled"`
}

// RuleStage 保存某个用户阶段的完整奖档概率。每个阶段的基础概率必须合计 1000000。
type RuleStage struct {
	Stage string `json:"stage"`
	// novice 的两个 0 仅为协议/存储 sentinel；normal/advanced 才用这两个下限提档。
	MinRecharge7DCoins  int64      `json:"min_recharge_7d_coins"`
	MinRecharge30DCoins int64      `json:"min_recharge_30d_coins"`
	Tiers               []RuleTier `json:"tiers"`
}

// RuleConfig 是幸运礼物不可变配置版本快照。fixed_v2 与 dynamic_v3 共用基础 RTP 契约，动态字段只由后者解释；
// 比例和倍率统一使用 ppm，后台百分比/倍率业务单位只在发布入口转换。
type RuleConfig struct {
	AppCode                   string `json:"app_code"`
	PoolID                    string `json:"pool_id"`
	RuleVersion               int64  `json:"rule_version"`
	StrategyVersion           string `json:"strategy_version"`
	Enabled                   bool   `json:"enabled"`
	TargetRTPPPM              int64  `json:"target_rtp_ppm"`
	PoolRatePPM               int64  `json:"pool_rate_ppm"`
	ProfitRatePPM             int64  `json:"profit_rate_ppm"`
	AnchorRatePPM             int64  `json:"anchor_rate_ppm"`
	SettlementWindowWager     int64  `json:"settlement_window_wager"`
	ControlBandPPM            int64  `json:"control_band_ppm"`
	GiftPriceReference        int64  `json:"gift_price_reference"`
	NoviceMaxEquivalentDraws  int64  `json:"novice_max_equivalent_draws"`
	NormalMaxEquivalentDraws  int64  `json:"normal_max_equivalent_draws"`
	EffectiveFromMS           int64  `json:"effective_from_ms"`
	CreatedByAdminID          int64  `json:"created_by_admin_id"`
	CreatedAtMS               int64  `json:"created_at_ms"`
	InitialPoolCoins          int64  `json:"initial_pool_coins"`
	LossStreakGuarantee       int64  `json:"loss_streak_guarantee"`
	LowWatermarkCoins         int64  `json:"low_watermark_coins"`
	LowWaterNonzeroFactorPPM  int64  `json:"low_water_nonzero_factor_ppm"`
	HighWatermarkCoins        int64  `json:"high_watermark_coins"`
	HighWaterNonzeroFactorPPM int64  `json:"high_water_nonzero_factor_ppm"`
	// V2HighWaterBoost* 是 fixed_v2 专属的高水位返奖加权三元组；0/0/0 表示关闭（历史版本反序列化默认值）。
	V2HighWaterBoostThresholdCoins int64 `json:"v2_high_water_boost_threshold_coins"`
	V2HighWaterBoostFactorPPM      int64 `json:"v2_high_water_boost_factor_ppm"`
	V2HighWaterBoostRecoverCoins   int64 `json:"v2_high_water_boost_recover_coins"`
	RechargeBoostWindowMS          int64 `json:"recharge_boost_window_ms"`
	RechargeBoostFactorPPM         int64 `json:"recharge_boost_factor_ppm"`
	// 0/100% 是历史兼容 sentinel；阈值大于 0 时，factor 表示触发后保留的普通中奖权重。
	User24HourRTPThresholdPPM      int64   `json:"user_24h_rtp_threshold_ppm"`
	User24HourOrdinaryWinFactorPPM int64   `json:"user_24h_ordinary_win_factor_ppm"`
	JackpotMultiplierPPMs          []int64 `json:"jackpot_multiplier_ppms"`
	JackpotGlobalRTPMaxPPM         int64   `json:"jackpot_global_rtp_max_ppm"`
	JackpotUserRoundRTPMaxPPM      int64   `json:"jackpot_user_round_rtp_max_ppm"`
	JackpotUser48hRTPMaxPPM        int64   `json:"jackpot_user_48h_rtp_max_ppm"`
	// Deprecated aliases are normalized at service/repository boundaries and are never persisted as separate values.
	JackpotUserDayRTPMaxPPM       int64       `json:"-"`
	JackpotUser72hRTPMaxPPM       int64       `json:"-"`
	SettledRoundRTPEligibility    bool        `json:"-"`
	JackpotSpendThresholdCoins    int64       `json:"jackpot_spend_threshold_coins"`
	MaxJackpotHitsPerUserDay      int64       `json:"max_jackpot_hits_per_user_day"`
	JackpotRateLimitWindowMinutes int64       `json:"jackpot_rate_limit_window_minutes"`
	MaxJackpotHitsPerWindow       int64       `json:"max_jackpot_hits_per_window"`
	MaxSinglePayout               int64       `json:"max_single_payout"`
	UserHourlyPayoutCap           int64       `json:"user_hourly_payout_cap"`
	UserDailyPayoutCap            int64       `json:"user_daily_payout_cap"`
	DeviceDailyPayoutCap          int64       `json:"device_daily_payout_cap"`
	RoomHourlyPayoutCap           int64       `json:"room_hourly_payout_cap"`
	AnchorDailyPayoutCap          int64       `json:"anchor_daily_payout_cap"`
	Stages                        []RuleStage `json:"stages"`
}

type CheckCommand struct {
	PoolID   string
	GiftID   string
	UserID   int64
	DeviceID string
	RoomID   string
}

type DrawCommand struct {
	CommandID    string
	PoolID       string
	UserID       int64
	TargetUserID int64
	DeviceID     string
	RoomID       string
	AnchorID     string
	GiftID       string
	GiftCount    int32
	CoinSpent    int64
	PaidAtMS     int64
	// UserRegisteredAtMS is the user owner snapshot captured by gateway at the original gift request.
	// Zero is tolerated for an old recovered command but makes the 48-hour jackpot maturity gate fail closed.
	UserRegisteredAtMS int64
	VisibleRegionID    int64
	// RoomLocked 是原始送礼时的房间展示快照，只能随 owner fact 透传，不能参与中奖概率和账务语义。
	RoomLocked bool
	// OwnerUserID 与 RoomLocked 来自同一次 Room Cell 送礼快照；它只服务跨房密码框交互，不参与抽奖资格或返奖。
	OwnerUserID       int64
	CountryID         int64
	Recharge7DCoins   int64
	Recharge30DCoins  int64
	LastRechargedAtMS int64
	// HostPeriodDiamondAdded 是兼容字段名，实际承载 wallet 已落账的主播收益（POINT 或周期钻石）；
	// Agency 额外收益不进入幸运礼物资金拆分，服务也不能自行重算主播比例。
	HostPeriodDiamondAdded int64
	// Sender* 是扣费时刻的公开展示快照；owner outbox 必须携带快照，避免下游为一条飘屏同步反查 user-service。
	SenderName                string
	SenderAvatar              string
	SenderDisplayUserID       string
	SenderPrettyDisplayUserID string
}

type CheckResult struct {
	Enabled         bool
	Reason          string
	PoolID          string
	GiftID          string
	GiftPrice       int64
	RuleVersion     int64
	StrategyVersion string
	TargetRTPPPM    int64
	ExperiencePool  string
}

type DrawResult struct {
	DrawID               string
	DrawIDs              []string
	CommandID            string
	AppCode              string
	UserID               int64
	ExternalUserID       string
	PoolID               string
	GiftID               string
	RuleVersion          int64
	ExperiencePool       string
	SelectedTierID       string
	MultiplierPPM        int64
	BaseRewardCoins      int64
	EffectiveRewardCoins int64
	RewardStatus         string
	RTPWindowIndex       int64
	GiftRTPWindowIndex   int64
	GlobalBaseRTPPPM     int64
	GiftBaseRTPPPM       int64
	StageFeedback        bool
	HighMultiplier       bool
	CreatedAtMS          int64
	WalletTransactionID  string
	CoinBalanceAfter     int64
	// Hits 只保留 gift_count 批量中的中奖子抽，避免为了连击表现把所有 999 条审计记录塞进同步响应。
	Hits []DrawHit
}

type DrawHit struct {
	GiftIndex      int32
	DrawID         string
	SelectedTierID string
	MultiplierPPM  int64
	RewardCoins    int64
}

type DrawSummary struct {
	PoolID           string
	TotalDraws       int64
	UniqueUsers      int64
	UniqueRooms      int64
	TotalSpentCoins  int64
	TotalRewardCoins int64
	BaseRewardCoins  int64
	ActualRTPPPM     int64
	PendingDraws     int64
	GrantedDraws     int64
	FailedDraws      int64
}

// DailyStatsQuery 是 Databi 按日聚合的查询输入；只读 lucky_draw_pool_day_stats 读模型，
// [StartMS, EndMS) 由存储层按北京日（+08:00）换算成 stat_day 闭区间。
type DailyStatsQuery struct {
	AppCode string
	// PoolID 为空表示全部奖池。
	PoolID string
	// StrategyVersion 为空表示不按策略过滤；否则必须是 fixed_v2 / dynamic_v3。
	StrategyVersion string
	StartMS         int64
	EndMS           int64
	// RegionIDs 为空表示全部区域（含 GLOBAL=0 房间）；非空时按房间可见区域过滤。
	RegionIDs []int64
}

// DailyStat 是单个北京日的抽奖汇总；口径与 DrawSummary 一致：
// payout 用用户可见返奖（effective），不按 reward_status 过滤。
type DailyStat struct {
	StatDay        string
	DrawCount      int64
	TurnoverCoin   int64
	PayoutCoin     int64
	BaseRewardCoin int64
}

// PoolBalance 是后台看到的 app+pool_id 单池账本快照。
// materialized=false 表示该池还没有真实 lucky_pools 行，展示的是规则默认初始水位，不能当成已经入库的资金流水。
type PoolBalance struct {
	AppCode           string
	PoolID            string
	StrategyVersion   string
	Balance           int64
	ReserveFloor      int64
	AvailableBalance  int64
	TotalIn           int64
	TotalOut          int64
	ManualCreditTotal int64
	ManualDebitTotal  int64
	Materialized      bool
	UpdatedAtMS       int64
}

type PoolBalanceQuery struct {
	AppCode         string
	PoolID          string
	StrategyVersion string
}

// PoolAdjustmentCommand 是人工注资/扣资的 owner 命令。AdjustmentID 由调用方生成并在 App 内唯一，
// 同一个 ID 的重试只能复用完全相同的资金参数，避免网络重试演变成重复记账。
type PoolAdjustmentCommand struct {
	AppCode         string
	PoolID          string
	StrategyVersion string
	AdjustmentID    string
	Direction       string
	AmountCoins     int64
	Reason          string
	OperatorAdminID int64
	RequestID       string
}

type PoolAdjustment struct {
	AdjustmentID    string
	AppCode         string
	PoolID          string
	StrategyVersion string
	Direction       string
	AmountCoins     int64
	Reason          string
	OperatorAdminID int64
	BalanceBefore   int64
	BalanceAfter    int64
	CreatedAtMS     int64
}

type PoolAdjustmentResult struct {
	Adjustment       PoolAdjustment
	Pool             PoolBalance
	IdempotentReplay bool
}

type AdminConfigQuery struct {
	PoolID string
}

type DrawQuery struct {
	AppCode  string
	PoolID   string
	GiftID   string
	UserID   int64
	RoomID   string
	Status   string
	Page     int32
	PageSize int32
	// ExternalUserID 只用于外部 App 接入流水查询；内部房间抽奖不会填这个字段。
	ExternalUserID string
	ExternalOnly   bool
}

const (
	UserProfileIdentityInternal = "internal"
	UserProfileIdentityExternal = "external"

	UserProfileHitZero            = "zero"
	UserProfileHitOrdinary        = "ordinary"
	UserProfileHitRTPCompensation = "rtp_compensation"
	UserProfileHitSpendMilestone  = "spend_milestone"
)

// UserProfileQuery 只允许按已经物化的身份键分页。内部短号、长号和靓号由 admin-server
// 通过 user-service 解析成 InternalUserID；外部用户只用原始 ExternalUserID 搜索，稳定哈希绝不跨服务暴露。
type UserProfileQuery struct {
	AppCode         string
	PoolID          string
	IdentityType    string
	InternalUserID  int64
	ExternalUserID  string
	Stage           string
	Status          string
	SortBy          string
	SortDirection   string
	Cursor          string
	Page            int32
	PageSize        int32
	JackpotPage     int32
	JackpotPageSize int32
	JackpotCursor   string
}

// UserProfileWindow 是严格时间窗内的用户资金结果。NetCoins 从用户视角计算为返奖减消耗；
// RTP 分母为 0 时保持 0，并由 HasRTP 区分“真实 0%”和“没有样本”。
type UserProfileWindow struct {
	Draws       int64
	WagerCoins  int64
	PayoutCoins int64
	NetCoins    int64
	RTPPPM      int64
	HasRTP      bool
}

// UserProfile 是 app+pool+用户的运营画像，不携带外部 strategy_user_id。
// StrategyUserID 只在 lucky-gift-service 仓储层关联 current state，transport 映射时必须丢弃。
type UserProfile struct {
	AppCode                        string
	PoolID                         string
	IdentityType                   string
	IdentityKey                    string
	StrategyUserID                 int64
	InternalUserID                 int64
	ExternalUserID                 string
	RuleVersion                    int64
	StrategyVersion                string
	Stage                          string
	PaidDraws                      int64
	EquivalentDraws                int64
	LossStreak                     int64
	PendingSpendJackpotTokens      int64
	GuaranteeDrawsRemaining        int64
	DownweightActive               bool
	DownweightFactorPPM            int64
	User24HourRTPThresholdPPM      int64
	OneHour                        UserProfileWindow
	TwentyFourHour                 UserProfileWindow
	FortyEightHour                 UserProfileWindow
	Lifetime                       UserProfileWindow
	BaseRewardCoins                int64
	OrdinaryWinCount               int64
	HighMultiplierOrdinaryWinCount int64
	RTPCompensationJackpotCount    int64
	CumulativeSpendJackpotCount    int64
	GuaranteeHitCount              int64
	ZeroDrawCount                  int64
	GrantedDrawCount               int64
	PendingDrawCount               int64
	FailedDrawCount                int64
	MaxMultiplierPPM               int64
	MaxRewardCoins                 int64
	FirstDrawAtMS                  int64
	LastDrawAtMS                   int64
	AggregatedAtMS                 int64
	DataLagMS                      int64
}

type UserProfileMultiplierStat struct {
	HitType       string
	MultiplierPPM int64
	DrawCount     int64
	WagerCoins    int64
	PayoutCoins   int64
}

type UserProfileJackpotCondition struct {
	Name        string
	Numerator   int64
	Denominator int64
	RatioPPM    int64
	LimitPPM    int64
	FactorPPM   int64
	Passed      bool
	Reason      string
}

type UserProfileJackpotHit struct {
	// SourceType 只参与 owner service 的稳定 keyset 游标，不通过 protobuf/HTTP 对外展示。
	SourceType    string
	DrawID        string
	RequestID     string
	RuleVersion   int64
	Stage         string
	Mechanism     string
	ReasonCode    string
	ReasonSummary string
	TierID        string
	MultiplierPPM int64
	WagerCoins    int64
	PayoutCoins   int64
	OccurredAtMS  int64
	Conditions    []UserProfileJackpotCondition
}

type UserProfileDetail struct {
	Profile                UserProfile
	MultiplierDistribution []UserProfileMultiplierStat
	JackpotHits            []UserProfileJackpotHit
	JackpotHitTotal        int64
	JackpotPage            int32
	JackpotPageSize        int32
	NextJackpotCursor      string
	JackpotHasMore         bool
}

// ExternalDrawCommand 是外部 App “已扣费后请求抽奖”的业务事实。
// HyApp 不接管外部 App 余额，因此这里没有 target_user_id、room_id 或 wallet command_id；幂等边界固定为
// app_code + request_id，任何重试都必须返回同一条抽奖结果。
type ExternalDrawCommand struct {
	AppCode        string
	ExternalUserID string
	// DeviceID 是外部调用方在自己认证/签名边界内绑定的稳定设备标识；缺失时 dynamic_v3 仅跳过设备日限额。
	DeviceID    string
	RequestID   string
	GiftCount   int64
	UnitAmount  int64
	TotalAmount int64
	Currency    string
	PaidAtMS    int64
	// UserRegisteredAtMS is supplied by the external App's authenticated user-data boundary.
	// Missing or inconsistent facts do not block an ordinary draw, but can never mature a compensation jackpot.
	UserRegisteredAtMS int64
	MetadataJSON       string
	PoolID             string
}

// ExternalDrawResult 是返回给外部 App 的最终抽奖结果。
// reward_status=granted 表示 HyApp 已完成抽奖审计并把 reward_amount 交给调用方处理；它不代表 HyApp wallet 入账。
type ExternalDrawResult struct {
	DrawID         string
	RequestID      string
	AppCode        string
	ExternalUserID string
	GiftCount      int64
	UnitAmount     int64
	TotalAmount    int64
	RewardAmount   int64
	MultiplierPPM  int64
	RewardStatus   string
	RuleVersion    int64
	CreatedAtMS    int64
}

// DrawOutbox 是幸运礼物抽奖事务写出的异步副作用载体，worker 只消费这个持久事实。
type DrawOutbox struct {
	AppCode     string
	OutboxID    string
	EventType   string
	PayloadJSON string
	RetryCount  int
	CreatedAtMS int64
}

type DrawRewardState struct {
	AllGranted          bool
	WalletTransactionID string
	// RewardGrantedAtMS 取 granted draw 的稳定 updated_at_ms；owner MQ 重投必须保持同一事实正文不漂移。
	RewardGrantedAtMS int64
}
