package services

import (
	"fmt"
	"sync"
	"time"
)

var (

	// 登录尝试记录
	loginAttempts = struct {
		sync.RWMutex
		m map[string]AttemptInfo
	}{m: make(map[string]AttemptInfo)}
)

// AttemptInfo 登录尝试信息
type AttemptInfo struct {
	Count       int
	FirstTry    time.Time
	LockedUntil *time.Time
}

// CheckLoginAttempts 检查登录尝试次数
func CheckLoginAttempts(identifier string) (bool, string) {
	loginAttempts.RLock()
	info, exists := loginAttempts.m[identifier]
	loginAttempts.RUnlock()

	if !exists {
		return true, ""
	}

	// 检查是否被锁定
	if info.LockedUntil != nil && time.Now().Before(*info.LockedUntil) {
		remaining := info.LockedUntil.Sub(time.Now())
		return false, fmt.Sprintf("账户已锁定，请%.0f分钟后再试", remaining.Minutes())
	}

	// 检查尝试次数
	if info.Count >= 5 {
		// 锁定30分钟
		lockedUntil := time.Now().Add(30 * time.Minute)
		info.LockedUntil = &lockedUntil
		loginAttempts.Lock()
		loginAttempts.m[identifier] = info
		loginAttempts.Unlock()

		return false, "尝试次数过多，账户已锁定30分钟"
	}

	return true, ""
}

// RecordLoginAttempt 记录登录尝试
func RecordLoginAttempt(identifier string, success bool) {
	loginAttempts.Lock()
	defer loginAttempts.Unlock()

	info, exists := loginAttempts.m[identifier]

	if success {
		// 登录成功，清除记录
		delete(loginAttempts.m, identifier)
		return
	}

	if !exists {
		// 第一次失败
		loginAttempts.m[identifier] = AttemptInfo{
			Count:    1,
			FirstTry: time.Now(),
		}
	} else {
		// 增加失败次数
		info.Count++
		loginAttempts.m[identifier] = info

		// 如果30分钟内失败5次，锁定账户
		if info.Count >= 5 && time.Since(info.FirstTry) <= 30*time.Minute {
			lockedUntil := time.Now().Add(30 * time.Minute)
			info.LockedUntil = &lockedUntil
			loginAttempts.m[identifier] = info
		}
	}

	// 清理30分钟前的记录
	for key, attemptInfo := range loginAttempts.m {
		if time.Since(attemptInfo.FirstTry) > 30*time.Minute {
			delete(loginAttempts.m, key)
		}
	}
}
