import crypto from 'crypto';

export function checkCooldown(cooldowns, key, windowMs, now = Date.now()) {
    const lastAllowedAt = cooldowns.get(key) || 0;
    if (now - lastAllowedAt < windowMs) {
        return false;
    }
    cooldowns.set(key, now);
    return true;
}

export function getCachedPayload(cache, key, ttlMs, buildPayload, now = Date.now()) {
    const cached = cache.get(key);
    if (cached && now - cached.createdAt < ttlMs) {
        return cached.payload;
    }

    const payload = buildPayload();
    cache.set(key, { createdAt: now, payload });
    return payload;
}

export function isAdminMetricsAuthorized(authHeader, adminToken) {
    if (!adminToken || typeof adminToken !== 'string') return false;
    if (!authHeader || typeof authHeader !== 'string') return false;

    const prefix = 'Bearer ';
    if (!authHeader.startsWith(prefix)) return false;

    const provided = authHeader.slice(prefix.length);
    if (!provided) return false;

    const expectedBuffer = Buffer.from(adminToken);
    const providedBuffer = Buffer.from(provided);

    if (expectedBuffer.length !== providedBuffer.length) return false;
    return crypto.timingSafeEqual(expectedBuffer, providedBuffer);
}

export function isAdminMetricsTokenStrong(adminToken, minLength = 32) {
    return !adminToken || (typeof adminToken === 'string' && adminToken.length >= minLength);
}

export function buildHealthPayload({
    rooms,
    connections,
    includeMetrics = false,
    now = Date.now(),
    uptime = 0,
    memoryUsage = () => process.memoryUsage(),
    rateLimitSizes = {}
}) {
    const payload = {
        status: 'ok',
        uptime,
        rooms: rooms.size,
        connections,
        timestamp: now
    };

    if (!includeMetrics) return payload;

    const roomValues = Array.from(rooms.values());
    const roomSizes = roomValues.map(room => room.peers?.size || 0);
    const peers = roomSizes.reduce((sum, size) => sum + size, 0);
    const maxPeersInRoom = roomSizes.length > 0 ? Math.max(...roomSizes) : 0;
    const avgPeersPerRoom = roomSizes.length > 0
        ? Math.round((peers / roomSizes.length) * 100) / 100
        : 0;
    const mem = memoryUsage();

    return {
        ...payload,
        peers,
        roomsWithLobby: roomValues.filter(room => !!room.activeLobby).length,
        avgPeersPerRoom,
        maxPeersInRoom,
        rateLimitEntries: {
            connections: rateLimitSizes.connections || 0,
            events: rateLimitSizes.events || 0,
            health: rateLimitSizes.health || 0,
            adminMetricsAuth: rateLimitSizes.adminMetricsAuth || 0,
            authFailures: rateLimitSizes.authFailures || 0,
            roomList: rateLimitSizes.roomList || 0
        },
        memory: {
            rss: mem.rss,
            heapUsed: mem.heapUsed,
            heapTotal: mem.heapTotal
        }
    };
}
