package auth

import (
	"context"
	"sync"
	"time"
)

type Denylist interface {
	Revoke(ctx context.Context, jti string, ttl time.Duration) error
	Revoked(ctx context.Context, jti string) (bool, error)
}

type MemoryDenylist struct {
	mu      sync.Mutex
	entries map[string]time.Time
}

func NewMemoryDenylist() *MemoryDenylist {
	return &MemoryDenylist{entries: map[string]time.Time{}}
}

func (d *MemoryDenylist) Revoke(_ context.Context, jti string, ttl time.Duration) error {
	d.mu.Lock()
	defer d.mu.Unlock()
	d.entries[jti] = time.Now().Add(ttl)
	d.sweep()
	return nil
}

func (d *MemoryDenylist) Revoked(_ context.Context, jti string) (bool, error) {
	d.mu.Lock()
	defer d.mu.Unlock()
	expiry, ok := d.entries[jti]
	if !ok {
		return false, nil
	}
	if time.Now().After(expiry) {
		delete(d.entries, jti)
		return false, nil
	}
	return true, nil
}

func (d *MemoryDenylist) sweep() {
	now := time.Now()
	for k, v := range d.entries {
		if now.After(v) {
			delete(d.entries, k)
		}
	}
}
