package service

import (
	"strings"

	roomeventsv1 "hyapp.local/api/proto/events/room/v1"
	roomv1 "hyapp.local/api/proto/room/v1"
	walletv1 "hyapp.local/api/proto/wallet/v1"
	"hyapp/services/room-service/internal/room/command"
)

func buildSendGiftBatchDisplay(cmd command.SendGift, billing *walletv1.DebitGiftResponse, targetBillings []giftTargetBilling, targetCurrentGiftValues map[int64]int64, luckyGifts []*roomv1.LuckyGiftDrawResult, roomHeat int64) *roomv1.SendGiftBatchDisplay {
	displayBilling := giftBillingForDisplay(billing, targetBillings)
	targets := make([]*roomv1.SendGiftBatchTarget, 0, len(targetBillings))
	luckyByTarget := luckyGiftResultsByTarget(luckyGifts)
	targetUserIDs := make([]int64, 0, len(targetBillings))
	for _, targetBilling := range targetBillings {
		if targetBilling.TargetUserID <= 0 || targetBilling.Billing == nil {
			continue
		}
		targetDisplayProfile := giftDisplayProfileForUser(cmd.TargetDisplayProfiles, targetBilling.TargetUserID)
		targetUserIDs = append(targetUserIDs, targetBilling.TargetUserID)
		target := &roomv1.SendGiftBatchTarget{
			TargetUserId:                targetBilling.TargetUserID,
			ReceiverNickname:            giftDisplayName(targetDisplayProfile),
			ReceiverAvatar:              strings.TrimSpace(targetDisplayProfile.Avatar),
			ReceiverDisplayUserId:       strings.TrimSpace(targetDisplayProfile.DisplayUserID),
			ReceiverPrettyDisplayUserId: strings.TrimSpace(targetDisplayProfile.PrettyDisplayUserID),
			GiftValue:                   targetBilling.Billing.GetHeatValue(),
			TargetGiftValue:             targetCurrentGiftValues[targetBilling.TargetUserID],
			CoinSpent:                   targetBilling.Billing.GetCoinSpent(),
			BillingReceiptId:            targetBilling.Billing.GetBillingReceiptId(),
			CommandId:                   targetBilling.CommandID,
			LuckyGift:                   luckyByTarget[targetBilling.TargetUserID],
		}
		targets = append(targets, target)
	}
	if len(targetUserIDs) == 0 {
		targetUserIDs = append(targetUserIDs, cmd.TargetUserIDs...)
	}
	return &roomv1.SendGiftBatchDisplay{
		SenderUserId:                    cmd.ActorUserID(),
		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),
		GiftId:                          cmd.GiftID,
		GiftCount:                       cmd.GiftCount,
		TotalGiftValue:                  sumTargetGiftValue(targetBillings),
		TotalCoinSpent:                  sumTargetCoinSpent(targetBillings, billing),
		BillingReceiptId:                firstNonEmpty(displayBilling.GetBillingReceiptId(), cmd.BillingReceiptID),
		RoomHeat:                        roomHeat,
		PoolId:                          cmd.PoolID,
		GiftTypeCode:                    displayBilling.GetGiftTypeCode(),
		CpRelationType:                  displayBilling.GetCpRelationType(),
		GiftName:                        displayBilling.GetGiftName(),
		GiftIconUrl:                     displayBilling.GetGiftIconUrl(),
		GiftAnimationUrl:                displayBilling.GetGiftAnimationUrl(),
		GiftEffectTypes:                 displayBilling.GetGiftEffectTypes(),
		TargetUserIds:                   targetUserIDs,
		Targets:                         targets,
		CommandId:                       cmd.ID(),
	}
}

func roomGiftBatchSentEventFromDisplay(display *roomv1.SendGiftBatchDisplay, visibleRegionID int64) *roomeventsv1.RoomGiftBatchSent {
	if display == nil {
		return nil
	}
	targets := make([]*roomeventsv1.RoomGiftBatchTarget, 0, len(display.GetTargets()))
	for _, target := range display.GetTargets() {
		if target == nil {
			continue
		}
		batchTarget := &roomeventsv1.RoomGiftBatchTarget{
			TargetUserId:                target.GetTargetUserId(),
			ReceiverNickname:            target.GetReceiverNickname(),
			ReceiverAvatar:              target.GetReceiverAvatar(),
			ReceiverDisplayUserId:       target.GetReceiverDisplayUserId(),
			ReceiverPrettyDisplayUserId: target.GetReceiverPrettyDisplayUserId(),
			GiftValue:                   target.GetGiftValue(),
			TargetGiftValue:             target.GetTargetGiftValue(),
			CoinSpent:                   target.GetCoinSpent(),
			BillingReceiptId:            target.GetBillingReceiptId(),
			CommandId:                   target.GetCommandId(),
			LuckyGift:                   roomGiftBatchLuckyResultFromRoom(target.GetLuckyGift()),
		}
		targets = append(targets, batchTarget)
	}
	return &roomeventsv1.RoomGiftBatchSent{
		SenderUserId:                    display.GetSenderUserId(),
		SenderName:                      display.GetSenderName(),
		SenderAvatar:                    display.GetSenderAvatar(),
		SenderDisplayUserId:             display.GetSenderDisplayUserId(),
		SenderPrettyDisplayUserId:       display.GetSenderPrettyDisplayUserId(),
		SenderVipLevel:                  display.GetSenderVipLevel(),
		SenderGiftBroadcastAnimationUrl: display.GetSenderGiftBroadcastAnimationUrl(),
		GiftId:                          display.GetGiftId(),
		GiftCount:                       display.GetGiftCount(),
		TotalGiftValue:                  display.GetTotalGiftValue(),
		TotalCoinSpent:                  display.GetTotalCoinSpent(),
		BillingReceiptId:                display.GetBillingReceiptId(),
		RoomHeat:                        display.GetRoomHeat(),
		PoolId:                          display.GetPoolId(),
		GiftTypeCode:                    display.GetGiftTypeCode(),
		CpRelationType:                  display.GetCpRelationType(),
		GiftName:                        display.GetGiftName(),
		GiftIconUrl:                     display.GetGiftIconUrl(),
		GiftAnimationUrl:                display.GetGiftAnimationUrl(),
		GiftEffectTypes:                 display.GetGiftEffectTypes(),
		TargetUserIds:                   display.GetTargetUserIds(),
		Targets:                         targets,
		CommandId:                       display.GetCommandId(),
		VisibleRegionId:                 visibleRegionID,
	}
}

func roomGiftBatchLuckyResultFromRoom(result *roomv1.LuckyGiftDrawResult) *roomeventsv1.RoomGiftBatchLuckyResult {
	if result == nil {
		return nil
	}
	return &roomeventsv1.RoomGiftBatchLuckyResult{
		Enabled:              result.GetEnabled(),
		DrawId:               result.GetDrawId(),
		CommandId:            result.GetCommandId(),
		PoolId:               result.GetPoolId(),
		GiftId:               result.GetGiftId(),
		RuleVersion:          result.GetRuleVersion(),
		ExperiencePool:       result.GetExperiencePool(),
		SelectedTierId:       result.GetSelectedTierId(),
		MultiplierPpm:        result.GetMultiplierPpm(),
		BaseRewardCoins:      result.GetBaseRewardCoins(),
		EffectiveRewardCoins: result.GetEffectiveRewardCoins(),
		RewardStatus:         result.GetRewardStatus(),
		StageFeedback:        result.GetStageFeedback(),
		HighMultiplier:       result.GetHighMultiplier(),
		CreatedAtMs:          result.GetCreatedAtMs(),
		TargetUserId:         result.GetTargetUserId(),
	}
}

func luckyGiftResultsByTarget(results []*roomv1.LuckyGiftDrawResult) map[int64]*roomv1.LuckyGiftDrawResult {
	byTarget := make(map[int64]*roomv1.LuckyGiftDrawResult, len(results))
	for _, result := range results {
		if result == nil || result.GetTargetUserId() <= 0 {
			continue
		}
		byTarget[result.GetTargetUserId()] = result
	}
	return byTarget
}

func giftBillingForDisplay(billing *walletv1.DebitGiftResponse, targetBillings []giftTargetBilling) *walletv1.DebitGiftResponse {
	if billing != nil {
		return billing
	}
	for _, targetBilling := range targetBillings {
		if targetBilling.Billing != nil {
			return targetBilling.Billing
		}
	}
	return &walletv1.DebitGiftResponse{}
}

func sumTargetGiftValue(targetBillings []giftTargetBilling) int64 {
	var total int64
	for _, targetBilling := range targetBillings {
		if targetBilling.Billing != nil {
			total += targetBilling.Billing.GetHeatValue()
		}
	}
	return total
}

func sumTargetCoinSpent(targetBillings []giftTargetBilling, billing *walletv1.DebitGiftResponse) int64 {
	var total int64
	for _, targetBilling := range targetBillings {
		if targetBilling.Billing != nil {
			total += targetBilling.Billing.GetCoinSpent()
		}
	}
	if total > 0 {
		return total
	}
	if billing == nil {
		return 0
	}
	return billing.GetCoinSpent()
}

func roomGiftLeaderboardValue(billing *walletv1.DebitGiftResponse) int64 {
	if billing == nil {
		return 0
	}
	// 房间贡献榜跟房间热度、房间内贡献人保持同一口径，使用 wallet 已按全局默认比例折算后的 heat_value。
	if billing.GetHeatValue() > 0 {
		return billing.GetHeatValue()
	}
	return 0
}
