package com.cnooc.expert.auth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.time.format.DateTimeFormatter;

@Service
public class AccountLockService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 锁定策略：3次错误 -> 10分钟，4次错误 -> 30分钟，5次及以上错误 -> 1小时
    private static final int[] LOCK_DURATIONS = {10, 30, 60}; // 分钟
    private static final int MAX_ATTEMPTS = 3;
    private String getLockKey(String account) {
        return "login:lock:" + account;
    }
    private String getAttemptKey(String account) {
        return "login:attempt:" + account;
    }
    private int calculateLockMinutes(long failureCount) {
        if (failureCount < MAX_ATTEMPTS) {
            return 0; // 不锁定
        } else if (failureCount == MAX_ATTEMPTS) {
            return LOCK_DURATIONS[0]; // 10分钟
        } else if (failureCount == MAX_ATTEMPTS + 1) {
            return LOCK_DURATIONS[1]; // 30分钟
        } else {
            return LOCK_DURATIONS[2]; // 60分钟
        }
    }
    private void lockAccount(String account, int lockMinutes) {
            String lockKey = getLockKey(account);
            String lockValue = LocalDateTime.now().toString() + "|" + lockMinutes;
            redisTemplate.opsForValue().set(lockKey, lockValue, lockMinutes*60, TimeUnit.SECONDS);//这个超时时间需要考虑一下
    }
    /**
     * 手动解锁账号
     */
    public void unlockAccount(String account) {
            String attemptKey = getAttemptKey(account);
            String lockKey = getLockKey(account);
            redisTemplate.delete(attemptKey);
            redisTemplate.delete(lockKey);
    }

    /**
     * 处理登录成功（重置失败计数和锁定）
     */
    public void handleLoginSuccess(String account) {
            String attemptKey = getAttemptKey(account);
            String lockKey = getLockKey(account);
            redisTemplate.delete(attemptKey);
            redisTemplate.delete(lockKey);
    }
    /**
     * 处理登录失败
     */
    public void handleLoginFailure(String account) {
            String attemptKey = getAttemptKey(account);
            String lockKey = getLockKey(account);

            // 如果已经锁定，不再增加计数
            if (Boolean.TRUE.equals(redisTemplate.hasKey(lockKey))) {
                return;
            }

            // 增加失败计数
            //long failureCount = jedis.incr(attemptKey);
            String failureCountStr = redisTemplate.opsForValue().get(attemptKey)!=null?redisTemplate.opsForValue().get(attemptKey).toString():"0";
            long failureCount = Long.parseLong(failureCountStr)+1;
             LocalDateTime now = LocalDateTime.now();
             LocalDateTime midnight = now.toLocalDate().atTime(LocalTime.MAX);
            redisTemplate.opsForValue().set(attemptKey,String.valueOf(failureCount),ChronoUnit.SECONDS.between(now, midnight), TimeUnit.SECONDS);

            // 设置计数过期时间（避免无限增长）
            if (failureCount == 1) {
                redisTemplate.expire(attemptKey, 24 * 60 * 60, TimeUnit.SECONDS); // 24小时过期
            }

            // 根据失败次数确定锁定时间
            int lockMinutes = calculateLockMinutes(failureCount);
            if (lockMinutes > 0) {
                lockAccount(account, lockMinutes);
                // 重置失败计数（锁定期间不需要继续计数）
                redisTemplate.delete(attemptKey);
            }
    }
    /**
     * 检查账号是否被锁定
     */
    public boolean isAccountLocked(String account) {
            String lockKey = getLockKey(account);
            return Boolean.TRUE.equals(redisTemplate.hasKey(lockKey));
    }

    /**
     * 获取锁定剩余时间
     */
    public String getLockRemainingTime(String account) {
            String lockKey = getLockKey(account);
            boolean isExist = Boolean.TRUE.equals(redisTemplate.hasKey(lockKey));
            if(isExist){
                LocalDateTime now = LocalDateTime.now();
                LocalDateTime futureTime = now.plusSeconds(redisTemplate.getExpire(lockKey,TimeUnit.SECONDS));
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
                return futureTime.format(formatter);
            }else{
                return "";
            }
    }
}
