package service

import (
	"context"
	"testing"
	"time"

	"hyapp/pkg/appcode"
)

func TestWithLuckyGiftSendLockWrapsLuckyPath(t *testing.T) {
	locker := &fakeLuckyGiftSendLocker{}
	svc := &Service{luckyGiftSendLocker: locker, luckyGiftSendLockTTL: 3 * time.Second}
	called := false

	err := svc.withLuckyGiftSendLock(appcode.WithContext(context.Background(), "lalu"), true, 42, func() error {
		if !locker.acquired || locker.released {
			t.Fatalf("lock must be held while lucky gift send runs: %+v", locker)
		}
		called = true
		return nil
	})
	if err != nil {
		t.Fatalf("withLuckyGiftSendLock failed: %v", err)
	}
	if !called || !locker.acquired || !locker.released || locker.appCode != "lalu" || locker.userID != 42 || locker.ttl != 3*time.Second {
		t.Fatalf("lock lifecycle mismatch: called=%v locker=%+v", called, locker)
	}
}

func TestWithLuckyGiftSendLockBypassesNormalGift(t *testing.T) {
	locker := &fakeLuckyGiftSendLocker{}
	svc := &Service{luckyGiftSendLocker: locker, luckyGiftSendLockTTL: 3 * time.Second}

	if err := svc.withLuckyGiftSendLock(context.Background(), false, 42, func() error { return nil }); err != nil {
		t.Fatalf("normal gift path should bypass lock: %v", err)
	}
	if locker.acquired {
		t.Fatalf("normal gift path must not acquire lucky gift lock")
	}
}

type fakeLuckyGiftSendLocker struct {
	acquired bool
	released bool
	appCode  string
	userID   int64
	ttl      time.Duration
}

func (l *fakeLuckyGiftSendLocker) AcquireLuckyGiftSendLock(_ context.Context, appCode string, userID int64, ttl time.Duration) (func(context.Context), error) {
	l.acquired = true
	l.appCode = appCode
	l.userID = userID
	l.ttl = ttl
	return func(context.Context) {
		l.released = true
	}, nil
}
