package com.xly.erp.module.usr.security;

import org.springframework.stereotype.Component;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
public class LoginAttemptStore {

    public static final int MAX_ATTEMPTS = 5;
    public static final Duration LOCK_DURATION = Duration.ofMinutes(15);

    private final ConcurrentMap<String, AttemptRecord> records = new ConcurrentHashMap<>();
    private final Clock clock;

    public LoginAttemptStore() {
        this(Clock.systemDefaultZone());
    }

    public LoginAttemptStore(Clock clock) {
        this.clock = clock;
    }

    public Optional<Long> isLocked(String userName) {
        AttemptRecord r = records.get(userName);
        if (r == null || r.lockExpireAt == null) {
            return Optional.empty();
        }
        Instant now = Instant.now(clock);
        if (now.isAfter(r.lockExpireAt)) {
            records.remove(userName);
            return Optional.empty();
        }
        return Optional.of(r.lockExpireAt.getEpochSecond() - now.getEpochSecond());
    }

    public synchronized int recordFailure(String userName) {
        AttemptRecord r = records.computeIfAbsent(userName, k -> new AttemptRecord());
        r.count++;
        if (r.count >= MAX_ATTEMPTS) {
            r.lockExpireAt = Instant.now(clock).plus(LOCK_DURATION);
        }
        return r.count;
    }

    public void clearFailures(String userName) {
        records.remove(userName);
    }

    private static class AttemptRecord {
        int count = 0;
        Instant lockExpireAt = null;
    }
}
