package service

import (
	"strings"
	"time"

	roomeventsv1 "hyapp.local/api/proto/events/room/v1"
	"hyapp/services/room-service/internal/room/command"
	"hyapp/services/room-service/internal/room/outbox"
	"hyapp/services/room-service/internal/room/state"
)

func buildRoomGiftSentRecords(roomID string, roomVersion int64, now time.Time, cmd command.SendGift, roomMeta RoomMeta, roomLocked bool, ownerUserID int64, targetBillings []giftTargetBilling, targetCurrentGiftValues map[int64]int64) ([]outbox.Record, error) {
	// RoomGiftSent 是统计、活动、成长任务和房间展示共同消费的送礼事实；构造时必须按目标拆分，不能用 batch 展示消息替代逐目标账务事实。
	records := make([]outbox.Record, 0, len(targetBillings))
	for _, targetBilling := range targetBillings {
		targetDisplayProfile := giftDisplayProfileForUser(cmd.TargetDisplayProfiles, targetBilling.TargetUserID)
		record, err := outbox.Build(roomID, "RoomGiftSent", roomVersion, now, &roomeventsv1.RoomGiftSent{
			SenderUserId:                    cmd.ActorUserID(),
			TargetUserId:                    targetBilling.TargetUserID,
			GiftId:                          cmd.GiftID,
			PoolId:                          cmd.PoolID,
			GiftCount:                       cmd.GiftCount,
			GiftValue:                       targetBilling.Billing.GetHeatValue(),
			CoinSpent:                       targetBilling.Billing.GetCoinSpent(),
			BillingReceiptId:                targetBilling.Billing.GetBillingReceiptId(),
			VisibleRegionId:                 roomMeta.VisibleRegionID,
			CountryId:                       cmd.SenderCountryID,
			RegionId:                        firstNonZeroInt64(cmd.SenderRegionID, roomMeta.VisibleRegionID),
			CommandId:                       targetBilling.CommandID,
			GiftTypeCode:                    targetBilling.Billing.GetGiftTypeCode(),
			CpRelationType:                  targetBilling.Billing.GetCpRelationType(),
			GiftName:                        targetBilling.Billing.GetGiftName(),
			GiftIconUrl:                     targetBilling.Billing.GetGiftIconUrl(),
			GiftAnimationUrl:                targetBilling.Billing.GetGiftAnimationUrl(),
			TargetGiftValue:                 targetCurrentGiftValues[targetBilling.TargetUserID],
			SenderName:                      giftDisplayName(cmd.SenderDisplayProfile),
			SenderAvatar:                    strings.TrimSpace(cmd.SenderDisplayProfile.Avatar),
			SenderDisplayUserId:             strings.TrimSpace(cmd.SenderDisplayProfile.DisplayUserID),
			SenderPrettyDisplayUserId:       strings.TrimSpace(cmd.SenderDisplayProfile.PrettyDisplayUserID),
			SenderVipLevel:                  cmd.SenderDisplayProfile.EffectiveVIPLevel,
			SenderGiftBroadcastAnimationUrl: strings.TrimSpace(cmd.SenderDisplayProfile.GiftBroadcastAnimationURL),
			ReceiverNickname:                giftDisplayName(targetDisplayProfile),
			ReceiverAvatar:                  strings.TrimSpace(targetDisplayProfile.Avatar),
			ReceiverDisplayUserId:           strings.TrimSpace(targetDisplayProfile.DisplayUserID),
			ReceiverPrettyDisplayUserId:     strings.TrimSpace(targetDisplayProfile.PrettyDisplayUserID),
			// display_mode 只改变房间展示投递策略；逐目标事实仍然进入 durable outbox，保证统计、activity、CP 和礼物墙消费口径不变。
			DisplayMode: strings.TrimSpace(cmd.DisplayMode),
			// effect_types 来自 wallet-service 已锁定的礼物价格配置；room-service 只透传，避免统计和全服广播各自重新判定礼物效果。
			GiftEffectTypes:    targetBilling.Billing.GetGiftEffectTypes(),
			RoomLocked:         roomLocked,
			OwnerUserId:        ownerUserID,
			IsRobotGift:        cmd.RobotWalletGift,
			SyntheticLuckyGift: cmd.SyntheticLuckyGift,
			RealRoomRobotGift:  cmd.RobotWalletGift && !cmd.RobotGift,
		})
		if err != nil {
			return nil, err
		}
		records = append(records, record)
	}
	return records, nil
}

func buildRoomHeatChangedRecord(roomID string, roomVersion int64, now time.Time, heatDelta int64, currentHeat int64) (outbox.Record, error) {
	// 热度事件只服务房间 UI 展示；当前值仍以 Room Cell 快照为准，客户端丢消息后可通过 snapshot 修复。
	return outbox.Build(roomID, "RoomHeatChanged", roomVersion, now, &roomeventsv1.RoomHeatChanged{
		Delta:       heatDelta,
		CurrentHeat: currentHeat,
	})
}

func buildRoomRankChangedRecord(roomID string, roomVersion int64, now time.Time, rankItem state.RankItem) (outbox.Record, error) {
	// 榜单事件表达本次送礼后 sender 在本地礼物榜中的新分值；完整榜单仍由快照和榜单读模型兜底。
	return outbox.Build(roomID, "RoomRankChanged", roomVersion, now, &roomeventsv1.RoomRankChanged{
		UserId:    rankItem.UserID,
		Score:     rankItem.Score,
		GiftValue: rankItem.GiftValue,
	})
}
