package com.saas.shared.security;

import com.saas.admin.repository.UserRoleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class PermissionCacheService {
    
    private final UserRoleRepository userRoleRepository;
    
    private final Map<Long, CachedPermissions> permissionCache = new ConcurrentHashMap<>();
    
    private static final long CACHE_TTL_MS = TimeUnit.MINUTES.toMillis(5);
    
    public PermissionCacheService(UserRoleRepository userRoleRepository) {
        this.userRoleRepository = userRoleRepository;
    }
    
    public List<String> getPermissionsForUser(Long userId) {
        CachedPermissions cached = permissionCache.get(userId);
        
        if (cached != null && !cached.isExpired()) {
            log.debug("Cache HIT for user {} ({} permissions)", userId, cached.permissions.size());
            return cached.permissions;
        }
        
        log.debug("Cache MISS for user {} - loading from database", userId);
        List<String> permissions = userRoleRepository.findAllPermissionsByUserId(userId);
        
        permissionCache.put(userId, new CachedPermissions(permissions));
        log.debug("Cached {} permissions for user {}", permissions.size(), userId);
        
        return permissions;
    }
    
    public void invalidateUser(Long userId) {
        permissionCache.remove(userId);
        log.info("Invalidated permission cache for user {}", userId);
    }
    
    public void invalidateAll() {
        int size = permissionCache.size();
        permissionCache.clear();
        log.info("Invalidated all permission caches ({} entries)", size);
    }
    
    public void invalidateByRole(Long roleId) {
        permissionCache.clear();
        log.info("Invalidated all permission caches due to role {} change", roleId);
    }
    
    public void invalidateByPermission(Long permissionId) {
        permissionCache.clear();
        log.info("Invalidated all permission caches due to permission {} change", permissionId);
    }
    
    public int getCacheSize() {
        return permissionCache.size();
    }
    
    public void evictExpired() {
        int before = permissionCache.size();
        permissionCache.entrySet().removeIf(entry -> entry.getValue().isExpired());
        int evicted = before - permissionCache.size();
        if (evicted > 0) {
            log.debug("Evicted {} expired cache entries", evicted);
        }
    }
    
    private static class CachedPermissions {
        final List<String> permissions;
        final long createdAt;
        
        CachedPermissions(List<String> permissions) {
            this.permissions = Collections.unmodifiableList(permissions);
            this.createdAt = System.currentTimeMillis();
        }
        
        boolean isExpired() {
            return System.currentTimeMillis() - createdAt > CACHE_TTL_MS;
        }
    }
}
