package middleware

import (
	"fmt"
	"time"
)

// RateLimitResult 限流检查结果
type RateLimitResult struct {
	Blocked    bool
	RetryAfter int
	Message    string
}

const (
	accountWindow   = 1 * time.Minute
	accountMaxFails = 3
	accountBlockDur = 1 * time.Minute
	ipWindow        = 1 * time.Minute
	ipMaxFails      = 10
	ipBlockDur      = 1 * time.Minute
	cleanupInterval = 2 * time.Minute
	maxEntries      = 10000
)

// windowState 单个维度的限流状态
type windowState struct {
	count        int
	windowStart  time.Time
	blockedUntil time.Time
}

// try 原子检查+递增：在持锁状态下判断是否被限流，若允许则递增计数。
// 检查与递增在同一临界区内完成，无竞态窗口。
// 调用方需在操作成功后调用 Clear/或 ClearIP 清除计数。
func (rl *RateLimiter) try(m map[string]*windowState, key string, window, blockDur time.Duration, maxFails int, lowKey bool) RateLimitResult {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()
	state, exists := m[key]
	if !exists {
		state = &windowState{}
		if len(m) < maxEntries {
			m[key] = state
		}
	}

	// 已被封禁中
	if !state.blockedUntil.IsZero() && now.Before(state.blockedUntil) {
		retry := int(state.blockedUntil.Sub(now).Seconds()) + 1
		msg := "请求过于频繁，请稍后重试"
		if lowKey {
			msg = fmt.Sprintf("该账号登录尝试过于频繁，请 %d 秒后重试", retry)
		}
		return RateLimitResult{Blocked: true, RetryAfter: retry, Message: msg}
	}

	// 窗口过期 → 重置
	if now.Sub(state.windowStart) > window {
		state.count = 0
		state.windowStart = now
		state.blockedUntil = time.Time{}
	}

	// 原子递增计数（本次尝试已记录）
	state.count++
	if state.count >= maxFails {
		state.blockedUntil = now.Add(blockDur)
	}

	return RateLimitResult{Blocked: false}
}
