package ledger

import (
	"strings"
)

// DebitGiftCommand 是 room-service 送礼扣费的账务命令。
type DebitGiftCommand struct {
	AppCode      string
	CommandID    string
	RoomID       string
	SenderUserID int64
	TargetUserID int64
	GiftID       string
	GiftCount    int32
	PriceVersion string
	RegionID     int64
	// SenderRegionID 是送礼用户所属区域快照；保留给用户归属相关的账务审计和风控语义。
	SenderRegionID int64
	// TargetIsHost 只能由 gateway 根据 user-service active host profile 注入，客户端输入不可信。
	TargetIsHost bool
	// TargetHostRegionID 是主播身份所属区域；主播周期钻石比例和工资政策均按该区域匹配，不能用房间可见区域替代。
	TargetHostRegionID int64
	// TargetAgencyOwnerUserID 是送礼瞬间主播上级代理的收款用户快照；结算按快照发放，避免月底组织变化错账。
	TargetAgencyOwnerUserID int64
	// RobotGift 表示本次扣费只服务机器人房间展示：扣 ROBOT_COIN，不给主播钻石，不进入真实礼物墙投影。
	RobotGift bool
	// DirectGift 表示本次扣费来自私聊送礼：没有 Room Cell 命令和房间 outbox，但仍复用真实扣费、返币、礼物墙和主播周期结算。
	DirectGift bool
	// EntitlementID 非空表示本次送礼来自用户背包礼物权益，账务只扣库存但仍按礼物价格计算房间贡献。
	EntitlementID string
	// ChargeSource 区分 coin/bag；为空按 coin 兼容旧链路。
	ChargeSource string
}

// DebitGiftTargetCommand 是批量送礼中单个接收方的账务语义。
type DebitGiftTargetCommand struct {
	// CommandID 是单个目标交易的幂等键；同一批量送礼必须为每个目标派生独立值。
	CommandID string
	// TargetUserID 是本次收礼用户；GIFT_POINT 已下线，新送礼不会再给目标用户积分入账。
	TargetUserID int64
	// TargetIsHost 只能由 gateway 注入，批量目标之间不能共享该身份快照。
	TargetIsHost bool
	// TargetHostRegionID 是该目标主播身份所属区域；批量结算必须按每个目标自己的区域解析周期钻石比例。
	TargetHostRegionID int64
	// TargetAgencyOwnerUserID 是该目标主播当前代理 owner 收款快照。
	TargetAgencyOwnerUserID int64
}

// BatchDebitGiftCommand 在一个钱包事务中结算同一 sender 对多个 target 的同款礼物。
type BatchDebitGiftCommand struct {
	AppCode        string
	CommandID      string
	RoomID         string
	SenderUserID   int64
	GiftID         string
	GiftCount      int32
	PriceVersion   string
	RegionID       int64
	SenderRegionID int64
	Targets        []DebitGiftTargetCommand
	EntitlementID  string
	ChargeSource   string
}

// Receipt 是账务命令落账后的稳定回执。
type Receipt struct {
	BillingReceiptID string
	TransactionID    string
	CoinSpent        int64
	ChargeAssetType  string
	ChargeAmount     int64
	// GiftPointAdded 是历史回执字段，新送礼固定为 0；房间贡献和主播周期钻石只按真实扣费金额计算。
	GiftPointAdded int64
	HeatValue      int64
	GiftTypeCode   string
	// CPRelationType 只在 CP 礼物类型上有值，room-service 会把它写入 RoomGiftSent 供 user-service 建关系申请。
	CPRelationType string
	// 礼物展示字段是扣费时的资源快照，避免异步消费者再查礼物配置导致历史 IM 展示被后续配置修改影响。
	GiftName         string
	GiftIconURL      string
	GiftAnimationURL string
	GiftEffectTypes  []string
	PriceVersion     string
	BalanceAfter     int64
	// BalanceVersion 是 sender 被扣费资产在本次送礼全部账务分录完成后的版本；幂等重放必须返回首次版本。
	BalanceVersion int64
	// HostPeriodDiamondAdded 是本次送礼写入主播工资周期账户的钻石数；非主播恒为 0。
	HostPeriodDiamondAdded int64
	// HostIncomePolicyType 与以下 canonical split 字段共同描述本次 Host/Agency 收益。
	HostIncomePolicyType   string
	HostIncomeBalanceAfter int64
	// Income split fields preserve the exact policy snapshot used by Room/Lucky and financial audit.
	IncomeAssetType          string
	HostBaseAmount           int64
	AgencyAmount             int64
	AgencyOwnerUserID        int64
	AgencyIncomeBalanceAfter int64
	HostIncomePolicyID       uint64
	HostIncomePolicyVersion  uint64
	HostPolicyCoefficient    string
	AgencyPointShareBPS      int32
	// HostPeriodCycleKey 是工资周期键，当前按 UTC 月生成，后续结算按此键定位周期账户。
	HostPeriodCycleKey string
	// HostPointAdded 是旧送礼命令的回执兼容字段；新送礼不入 POINT，始终为 0。
	HostPointAdded int64
	// HostPointBalanceAfter 只供旧命令幂等重放；新送礼始终为 0。
	HostPointBalanceAfter int64
	// HostPointPolicyInstanceCode 只保留旧命令已固化的快照；新送礼不读取收益政策。
	HostPointPolicyInstanceCode string
	// HostPointTemplateCode/Version 同样只是旧命令回执快照，新送礼为空。
	HostPointTemplateCode    string
	HostPointTemplateVersion string
	// HostPointAssetType 只供旧命令回执重放，新送礼为空。
	HostPointAssetType string
	EntitlementID      string
	ChargeSource       string
	// GiftIncomeCoinAmount 是收礼人按区域/礼物类型返还的 COIN，用于私聊送礼回执和客户端展示同步。
	GiftIncomeCoinAmount int64
	// GiftIncomeBalanceAfter 是收礼人 COIN 入账后的余额；没有返币时为 0。
	GiftIncomeBalanceAfter int64
	// Recharge* 是扣费事务固化的 sender 充值画像。它们跟随 gift transaction metadata 幂等重放，
	// 防止 lucky-gift 因重试时间不同进入另一概率层或丢失“充值后五分钟”加成。
	RechargeSevenDayCoins  int64
	RechargeThirtyDayCoins int64
	LastRechargedAtMS      int64
	// PaidAtMS 是 wallet owner 创建成功交易行的 UTC epoch ms。它跟 transaction_id 一起构成不可变扣费事实，
	// room 恢复和 lucky 重放必须复用它，不能改用 saga 创建时间或恢复执行时间。
	PaidAtMS int64
}

// BatchGiftTargetReceipt 保留批量送礼里每个目标的独立交易回执。
type BatchGiftTargetReceipt struct {
	TargetUserID int64
	CommandID    string
	Receipt      Receipt
}

// BatchGiftReceipt 同时返回聚合展示值和逐目标事实回执。
type BatchGiftReceipt struct {
	Aggregate Receipt
	Targets   []BatchGiftTargetReceipt
}

func NormalizeGiftChargeAssetType(assetType string) string {
	if strings.ToUpper(strings.TrimSpace(assetType)) == AssetBagGift {
		return AssetBagGift
	}
	return AssetCoin
}

func ValidGiftChargeAssetType(assetType string) bool {
	switch strings.ToUpper(strings.TrimSpace(assetType)) {
	case AssetCoin:
		return true
	default:
		return false
	}
}
