package service

import (
	"context"
	"time"

	"hyapp/services/room-service/internal/room/outbox"
	"hyapp/services/room-service/internal/room/rank"
	"hyapp/services/room-service/internal/room/state"

	roomv1 "hyapp.local/api/proto/room/v1"
)

// SendGift 先同步调用 wallet，再在 Room Cell 内完成热度、榜单和房间事件落地。
func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*roomv1.SendGiftResponse, error) {
	return s.sendGift(ctx, req, giftSendOptions{})
}

// SendGiftBatch 是多人送礼展示入口；它复用送礼账务、幸运礼物和 Room Cell 提交流程，
// 但只在 batch 分支生成 RoomGiftBatchSent 展示消息，避免普通 SendGift 被 display_mode 隐式改变行为。
func (s *Service) SendGiftBatch(ctx context.Context, req *roomv1.SendGiftRequest) (*roomv1.SendGiftResponse, error) {
	return s.sendGiftBatch(ctx, req)
}

func (s *Service) sendGiftBatch(ctx context.Context, req *roomv1.SendGiftRequest) (*roomv1.SendGiftResponse, error) {
	return s.sendGift(ctx, req, giftSendOptions{BatchDisplay: true})
}

type giftSendOptions struct {
	Robot        robotGiftOptions
	BatchDisplay bool
}

func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, options giftSendOptions) (*roomv1.SendGiftResponse, error) {
	ctx = contextFromMeta(ctx, req.GetMeta())
	flow := newGiftFlow(s, ctx, req, options)

	result, err := s.mutateRoom(ctx, flow.cmd, true, func(now time.Time, current *state.RoomState, localRank *rank.LocalRank) (mutationResult, []outbox.Record, error) {
		// 阶段顺序保持原 sendGift 同步主链路：先校验房间态，再取房间事实，再扣费/抽奖，最后提交 Room Cell 状态和构造事件。
		if err := flow.validateBeforeDebit(current); err != nil {
			return mutationResult{}, nil, err
		}
		if err := flow.prepareRoomFacts(); err != nil {
			return mutationResult{}, nil, err
		}
		if err := flow.debitAndSettle(now); err != nil {
			return mutationResult{}, nil, err
		}
		if err := flow.applyRoomState(now, current, localRank); err != nil {
			return mutationResult{}, nil, err
		}
		return flow.buildMutationResult(now, current)
	})
	if err != nil {
		return nil, err
	}

	return &roomv1.SendGiftResponse{
		Result:                 commandResult(result.applied, result.snapshot.GetVersion(), s.clock.Now()),
		BillingReceiptId:       result.billingReceiptID,
		RoomHeat:               result.roomHeat,
		GiftRank:               result.giftRank,
		Room:                   result.snapshot,
		Rocket:                 result.snapshot.GetRocket(),
		LuckyGift:              result.luckyGift,
		LuckyGifts:             result.luckyGifts,
		CoinBalanceAfter:       result.coinBalanceAfter,
		GiftIncomeBalanceAfter: result.giftIncomeBalanceAfter,
		BatchDisplay:           result.batchDisplay,
	}, nil
}
