// Package cardtrafficlock 提供卡流量上游请求的统一 Redis 互斥。
package cardtrafficlock

import (
	"context"

	"github.com/google/uuid"
	"github.com/redis/go-redis/v9"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
)

var releaseScript = redis.NewScript(`
if redis.call('GET', KEYS[1]) == ARGV[1] then
  return redis.call('DEL', KEYS[1])
end
return 0
`)

// Lock 统一卡流量上游请求互斥，防止过期持有者误删新锁。
type Lock struct {
	redis *redis.Client
}

// New 创建卡流量请求锁。
func New(redisClient *redis.Client) *Lock {
	return &Lock{redis: redisClient}
}

// Acquire 使用随机令牌获取至少覆盖完整 Gateway 重试窗口的卡级锁。
func (l *Lock) Acquire(ctx context.Context, cardID uint) (string, bool, error) {
	if l == nil || l.redis == nil {
		return "", true, nil
	}
	token := uuid.NewString()
	acquired, err := l.redis.SetNX(ctx, constants.RedisCardTrafficSyncLockKey(cardID), token, constants.CardObservationGatewayLockTTL).Result()
	if err != nil || !acquired {
		return "", acquired, err
	}
	return token, true, nil
}

// Release 仅由仍持有相同随机令牌的调用方释放卡级锁。
func (l *Lock) Release(ctx context.Context, cardID uint, token string) error {
	if l == nil || l.redis == nil || token == "" {
		return nil
	}
	return releaseScript.Run(ctx, l.redis, []string{constants.RedisCardTrafficSyncLockKey(cardID)}, token).Err()
}
