package com.ruoyi.security.service.impl;

import java.security.SecureRandom;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ruoyi.security.service.AuthenticationService;

/**
 * Authentication service implementation
 */
@Service
public class AuthenticationServiceImpl implements AuthenticationService {
    
    private static final Logger log = LoggerFactory.getLogger(AuthenticationServiceImpl.class);
    
    private static final int MAX_LOGIN_ATTEMPTS = 5;
    private static final long LOCKOUT_DURATION = 30 * 60 * 1000; // 30 minutes
    
    // Login failure tracking
    private final ConcurrentHashMap<String, AtomicInteger> loginFailureCount = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Long> lockoutTime = new ConcurrentHashMap<>();
    
    @Override
    public boolean authenticate(String username, String password) {
        if (isAccountLocked(username)) {
            log.warn("Authentication failed - account locked: {}", username);
            return false;
        }
        
        // Simple authentication logic for demo
        boolean isValid = username != null && password != null && password.length() >= 6;
        
        if (!isValid) {
            handleLoginFailure(username, "127.0.0.1");
        } else {
            // Clear failure count on successful login
            loginFailureCount.remove(username);
            lockoutTime.remove(username);
        }
        
        return isValid;
    }
    
    @Override
    public String generateMfaToken(Long userId, String tokenType) {
        // Generate 6-digit MFA token
        SecureRandom random = new SecureRandom();
        int token = 100000 + random.nextInt(900000);
        
        log.info("Generated MFA token for user: {}, type: {}", userId, tokenType);
        
        return String.valueOf(token);
    }
    
    @Override
    public boolean validateMfaToken(Long userId, String token) {
        // Simple validation - in real implementation, this would check against stored tokens
        return token != null && token.matches("\\d{6}");
    }
    
    @Override
    public boolean isAccountLocked(String username) {
        Long lockTime = lockoutTime.get(username);
        if (lockTime != null && System.currentTimeMillis() - lockTime < LOCKOUT_DURATION) {
            return true;
        }
        
        AtomicInteger failCount = loginFailureCount.get(username);
        return failCount != null && failCount.get() >= MAX_LOGIN_ATTEMPTS;
    }
    
    @Override
    public void handleLoginFailure(String username, String ipAddress) {
        AtomicInteger failCount = loginFailureCount.computeIfAbsent(username, k -> new AtomicInteger(0));
        int currentCount = failCount.incrementAndGet();
        
        log.warn("Login failure for user: {}, count: {}", username, currentCount);
        
        if (currentCount >= MAX_LOGIN_ATTEMPTS) {
            lockoutTime.put(username, System.currentTimeMillis());
            log.warn("Account locked due to too many failures: {}", username);
            
            // Cleanup user data
            cleanupUserData(getUserIdByUsername(username));
        }
    }
    
    @Override
    public void cleanupUserData(Long userId) {
        if (userId != null) {
            log.info("Cleaning up user data for user: {}", userId);
            // In real implementation, this would clear sessions, tokens, etc.
        }
    }
    
    private Long getUserIdByUsername(String username) {
        // Mock implementation - in real system, this would query the database
        return username != null ? (long) username.hashCode() : null;
    }
}