package repository

import (
	"context"
	"errors"
	"time"

	redislib "gateway/internal/library/redis"
	domrepo "gateway/internal/model/notification/domain/repository"

	"github.com/zeromicro/go-zero/core/stores/redis"
)

// RedisIdempotencyCache implements IdempotencyCache with the shared go-zero Redis client.
type RedisIdempotencyCache struct {
	client *redis.Redis
}

func NewRedisIdempotencyCache(client *redislib.Client) domrepo.IdempotencyCache {
	if client == nil || client.Zero() == nil {
		panic("notification: redis client is required")
	}
	return &RedisIdempotencyCache{client: client.Zero()}
}

func (c *RedisIdempotencyCache) Get(ctx context.Context, key string) ([]byte, error) {
	val, err := c.client.GetCtx(ctx, key)
	if errors.Is(err, redis.Nil) {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return []byte(val), nil
}

func (c *RedisIdempotencyCache) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error {
	seconds := int(ttl.Seconds())
	if seconds < 1 {
		seconds = 1
	}
	return c.client.SetexCtx(ctx, key, string(value), seconds)
}

// RedisQuotaCounter implements QuotaCounter with the shared go-zero Redis client.
type RedisQuotaCounter struct {
	client *redis.Redis
}

func NewRedisQuotaCounter(client *redislib.Client) domrepo.QuotaCounter {
	if client == nil || client.Zero() == nil {
		panic("notification: redis client is required")
	}
	return &RedisQuotaCounter{client: client.Zero()}
}

func (c *RedisQuotaCounter) Incr(ctx context.Context, key string, ttl time.Duration) (int64, error) {
	count, err := c.client.IncrCtx(ctx, key)
	if err != nil {
		return 0, err
	}
	seconds := int(ttl.Seconds())
	if seconds < 1 {
		seconds = 1
	}
	if err := c.client.ExpireCtx(ctx, key, seconds); err != nil {
		return count, err
	}
	return count, nil
}
