package middleware

import (
	"context"
	"log/slog"
	"sync"
	"time"

	"security-center-backend/internal/repository"
)

const (
	// touchLastUsedInterval 是同一 key 两次 last_used_at 写入的最小间隔。
	touchLastUsedInterval = 60 * time.Second
	// touchLastUsedTimeout 是异步写库的超时时间。
	touchLastUsedTimeout = 5 * time.Second
)

// now 做成包级变量以便测试注入假时钟。
var now = time.Now

var (
	touchLastUsedMu sync.Mutex
	// touchLastUsedSeen 记录每 key 最近一次成功投递时间。
	touchLastUsedSeen = make(map[uint64]time.Time)
)

// touchLastUsedAsync 异步更新 API key 的 last_used_at:
// goroutine 投递, 不阻塞认证热路径; 进程内按 key 降频, 同一 key 60s 内至多写一次。
func touchLastUsedAsync(repo repository.APIKeyRepository, id uint64) {
	if repo == nil {
		return
	}

	touchLastUsedMu.Lock()
	if last, ok := touchLastUsedSeen[id]; ok && now().Sub(last) < touchLastUsedInterval {
		touchLastUsedMu.Unlock()
		return
	}
	touchLastUsedSeen[id] = now()
	touchLastUsedMu.Unlock()

	go func() {
		ctx, cancel := context.WithTimeout(context.Background(), touchLastUsedTimeout)
		defer cancel()
		if err := repo.TouchLastUsed(ctx, id); err != nil {
			// 写失败静默处理, 不影响认证热路径。
			slog.Debug("touch api key last_used_at failed", "id", id, "error", err)
		}
	}()
}
