// Global error handler to prevent page refreshes
window.addEventListener('error', function (e) {
    console.error('Global error caught:', e.error);
    console.error('Error message:', e.message);
    console.error('Error filename:', e.filename);
    console.error('Error line:', e.lineno);
    e.preventDefault(); // Prevent default browser error handling
    return true; // Prevent page refresh
});

window.addEventListener('unhandledrejection', function (e) {
    console.error('Unhandled promise rejection:', e.reason);
    e.preventDefault(); // Prevent default browser error handling
    return true; // Prevent page refresh
});

// Global state
let nlLite = null;
let userPubkey = null;
let isLoggedIn = false;
let currentConfig = null;
// Global subscription state
let relayPool = null;
let subscriptionId = null;
// Relay connection state
let relayInfo = null;
let isRelayConnected = false;
let relayPubkey = null;
// Database statistics auto-refresh
let statsAutoRefreshInterval = null;
let countdownInterval = null;
let countdownSeconds = 10;

// DOM elements
const loginModal = document.getElementById('login-modal');
const loginModalContainer = document.getElementById('login-modal-container');
const profileArea = document.getElementById('profile-area');
const headerUserImage = document.getElementById('header-user-image');
const headerUserName = document.getElementById('header-user-name');
const logoutDropdown = document.getElementById('logout-dropdown');
const logoutBtn = document.getElementById('logout-btn');

// Legacy elements (kept for backward compatibility)
const persistentUserName = document.getElementById('persistent-user-name');
const persistentUserPubkey = document.getElementById('persistent-user-pubkey');
const persistentUserAbout = document.getElementById('persistent-user-about');
const persistentUserDetails = document.getElementById('persistent-user-details');
const fetchConfigBtn = document.getElementById('fetch-config-btn');
// Relay connection elements
const relayConnectionUrl = document.getElementById('relay-connection-url');
const relayPubkeyManual = document.getElementById('relay-pubkey-manual');
const relayConnectionStatus = document.getElementById('relay-connection-status');
const connectRelayBtn = document.getElementById('connect-relay-btn');
const disconnectRelayBtn = document.getElementById('disconnect-relay-btn');
const restartRelayBtn = document.getElementById('restart-relay-btn');
const configDisplay = document.getElementById('config-display');
const configTableBody = document.getElementById('config-table-body');

// NIP-17 DM elements
const dmOutbox = document.getElementById('dm-outbox');
const dmInbox = document.getElementById('dm-inbox');
const sendDmBtn = document.getElementById('send-dm-btn');

// Utility functions
function log(message, type = 'INFO') {
    const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
    const logMessage = `${timestamp} [${type}]: ${message}`;

    // Always log to browser console so we don't lose logs on refresh
    console.log(logMessage);

    // UI logging removed - using console only
}

// Utility functions
function log(message, type = 'INFO') {
    const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
    const logMessage = `${timestamp} [${type}]: ${message}`;

    // Always log to browser console so we don't lose logs on refresh
    console.log(logMessage);

    // UI logging removed - using console only
}

// Show authentication warning message
function showAuthenticationWarning(message) {
    // Remove any existing warning
    hideAuthenticationWarning();

    // Create warning element
    const warningDiv = document.createElement('div');
    warningDiv.id = 'auth-warning-message';
    warningDiv.className = 'auth-warning-message';
    warningDiv.innerHTML = `
        <div class="warning-content">
            <strong>⚠️ Authentication Issue:</strong> ${message}
            <br><br>
            <small>This usually means your pubkey is not authorized as an admin for this relay.
            Please check that you are using the correct admin pubkey that was shown during relay startup.</small>
        </div>
    `;

    // Insert warning at the top of the relay connection section
    const relaySection = document.getElementById('relay-connection-section');
    if (relaySection) {
        relaySection.insertBefore(warningDiv, relaySection.firstChild);
    }

    log(`Authentication warning displayed: ${message}`, 'WARNING');
}

// Hide authentication warning message
function hideAuthenticationWarning() {
    const warningDiv = document.getElementById('auth-warning-message');
    if (warningDiv) {
        warningDiv.remove();
    }
}

// NIP-59 helper: randomize created_at to thwart time-analysis (past 2 days)
function randomNow() {
    const TWO_DAYS = 2 * 24 * 60 * 60; // 172800 seconds
    const now = Math.round(Date.now() / 1000);
    return Math.round(now - Math.random() * TWO_DAYS);
}

// Safe JSON parse with error handling
function safeJsonParse(jsonString) {
    try {
        return JSON.parse(jsonString);
    } catch (error) {
        console.error('JSON parse error:', error);
        return null;
    }
}
// ================================
// NIP-11 RELAY CONNECTION FUNCTIONS
// ================================

// Convert WebSocket URL to HTTP URL for NIP-11
function wsToHttpUrl(wsUrl) {
    if (wsUrl.startsWith('ws://')) {
        return wsUrl.replace('ws://', 'http://');
    } else if (wsUrl.startsWith('wss://')) {
        return wsUrl.replace('wss://', 'https://');
    }
    return wsUrl;
}

// Fetch relay information using NIP-11
async function fetchRelayInfo(relayUrl) {
    try {
        log(`Fetching NIP-11 relay info from: ${relayUrl}`, 'INFO');

        // Convert WebSocket URL to HTTP URL
        const httpUrl = wsToHttpUrl(relayUrl);

        // Make HTTP request with NIP-11 headers
        const response = await fetch(httpUrl, {
            method: 'GET',
            headers: {
                'Accept': 'application/nostr+json',
                'User-Agent': 'C-Relay-Admin-API/1.0'
            },
            timeout: 10000 // 10 second timeout
        });

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        const contentType = response.headers.get('content-type');
        if (!contentType || !contentType.includes('application/nostr+json')) {
            throw new Error(`Invalid content type: ${contentType}. Expected application/nostr+json`);
        }

        const relayInfo = await response.json();

        // Log if relay info is empty (not configured yet) but don't throw error
        if (!relayInfo || Object.keys(relayInfo).length === 0) {
            log('Relay returned empty NIP-11 info - relay not configured yet, will use manual pubkey if provided', 'INFO');
            // Return empty object - this is valid, caller will handle manual pubkey fallback
            return {};
        }

        // Validate pubkey if present
        if (relayInfo.pubkey && !/^[0-9a-fA-F]{64}$/.test(relayInfo.pubkey)) {
            throw new Error(`Invalid relay pubkey format: ${relayInfo.pubkey}`);
        }

        log(`Successfully fetched relay info. Pubkey: ${relayInfo.pubkey ? relayInfo.pubkey.substring(0, 16) + '...' : 'not set'}`, 'INFO');
        return relayInfo;

    } catch (error) {
        log(`Failed to fetch relay info: ${error.message}`, 'ERROR');
        throw error;
    }
}

// Test WebSocket connection to relay
async function testWebSocketConnection(wsUrl) {
    return new Promise((resolve, reject) => {
        try {
            log(`Testing WebSocket connection to: ${wsUrl}`, 'INFO');

            const ws = new WebSocket(wsUrl);
            const timeout = setTimeout(() => {
                ws.close();
                reject(new Error('WebSocket connection timeout (10s)'));
            }, 10000);

            ws.onopen = () => {
                clearTimeout(timeout);
                log('WebSocket connection successful', 'INFO');
                ws.close();
                resolve(true);
            };

            ws.onerror = (error) => {
                clearTimeout(timeout);
                log(`WebSocket connection failed: ${error.message || 'Unknown error'}`, 'ERROR');
                reject(new Error('WebSocket connection failed'));
            };

            ws.onclose = (event) => {
                if (event.code !== 1000) { // 1000 = normal closure
                    clearTimeout(timeout);
                    reject(new Error(`WebSocket closed unexpectedly: ${event.code} ${event.reason}`));
                }
            };

        } catch (error) {
            log(`WebSocket test error: ${error.message}`, 'ERROR');
            reject(error);
        }
    });
}

// Connect to relay (NIP-11 + WebSocket test)
async function connectToRelay() {
    try {
        const url = relayConnectionUrl.value.trim();
        if (!url) {
            throw new Error('Please enter a relay URL');
        }

        // Update UI to show connecting state
        updateRelayConnectionStatus('connecting');
        connectRelayBtn.disabled = true;

        log(`Connecting to relay: ${url}`, 'INFO');

        // Clear any previous authentication warnings
        hideAuthenticationWarning();

        let fetchedRelayInfo;

        try {
            // Step 1: Try to fetch NIP-11 relay information
            fetchedRelayInfo = await fetchRelayInfo(url);

            // Check if NIP-11 response includes a pubkey
            if (fetchedRelayInfo.pubkey) {
                // NIP-11 provided pubkey - populate the manual input field
                log(`NIP-11 provided relay pubkey: ${fetchedRelayInfo.pubkey.substring(0, 16)}...`, 'INFO');
                relayPubkeyManual.value = fetchedRelayInfo.pubkey;
            } else {
                // NIP-11 response missing pubkey, check for manual input
                log('NIP-11 response missing pubkey, checking for manual input...', 'INFO');

                const manualPubkey = relayPubkeyManual.value.trim();
                if (!manualPubkey) {
                    throw new Error('Relay NIP-11 response does not include a pubkey. Please enter the relay pubkey manually (shown during relay startup).');
                }

                if (!/^[0-9a-fA-F]{64}$/.test(manualPubkey)) {
                    throw new Error('Manual relay pubkey must be exactly 64 hexadecimal characters');
                }

                log(`Using manual relay pubkey: ${manualPubkey.substring(0, 16)}...`, 'INFO');

                // Add manual pubkey to the fetched relay info
                fetchedRelayInfo.pubkey = manualPubkey;

                // If relay info was completely empty, create minimal info
                if (Object.keys(fetchedRelayInfo).length === 1) {
                    fetchedRelayInfo = {
                        name: 'C-Relay (Manual Config)',
                        description: 'C-Relay instance - pubkey provided manually',
                        pubkey: manualPubkey,
                        contact: 'admin@manual.config.relay',
                        supported_nips: [1, 9, 11, 13, 15, 20, 33, 40, 42],
                        software: 'https://github.com/0xtrr/c-relay',
                        version: '1.0.0'
                    };
                }
            }

        } catch (nip11Error) {
            // If NIP-11 completely fails (network error, etc.), require manual pubkey
            const manualPubkey = relayPubkeyManual.value.trim();
            if (!manualPubkey) {
                throw new Error(`NIP-11 fetch failed: ${nip11Error.message}. Please enter the relay pubkey manually if the relay hasn't been configured yet.`);
            }

            if (!/^[0-9a-fA-F]{64}$/.test(manualPubkey)) {
                throw new Error('Manual relay pubkey must be exactly 64 hexadecimal characters');
            }

            log(`NIP-11 failed, using manual relay pubkey: ${manualPubkey.substring(0, 16)}...`, 'INFO');

            // Create minimal relay info with manual pubkey
            fetchedRelayInfo = {
                name: 'C-Relay (Manual Config)',
                description: 'C-Relay instance - pubkey provided manually',
                pubkey: manualPubkey,
                contact: 'admin@manual.config.relay',
                supported_nips: [1, 9, 11, 13, 15, 20, 33, 40, 42],
                software: 'https://github.com/0xtrr/c-relay',
                version: '1.0.0'
            };
        }

        // Step 2: Test WebSocket connection
        await testWebSocketConnection(url);

        // Step 3: Update global state
        relayInfo = fetchedRelayInfo;
        relayPubkey = fetchedRelayInfo.pubkey;
        isRelayConnected = true;

        // Step 4: Update UI
        updateRelayConnectionStatus('connected');
        updateAdminSectionsVisibility();

        // Step 5: Relay URL updated

        // Step 6: Automatically load configuration and auth rules
        log('Relay connected successfully. Auto-loading configuration and auth rules...', 'INFO');

        // Auto-fetch configuration
        setTimeout(() => {
            fetchConfiguration().catch(error => {
                log('Auto-fetch configuration failed: ' + error.message, 'ERROR');
            });
        }, 500);

        // Auto-fetch auth rules
        setTimeout(() => {
            loadAuthRules().catch(error => {
                log('Auto-fetch auth rules failed: ' + error.message, 'ERROR');
            });
        }, 1000);

        // Auto-fetch database statistics
        setTimeout(() => {
            sendStatsQuery().catch(error => {
                log('Auto-fetch statistics failed: ' + error.message, 'ERROR');
            });
        }, 1500);

        log(`Successfully connected to relay: ${relayInfo.name || 'Unknown'}`, 'INFO');

    } catch (error) {
        log(`Failed to connect to relay: ${error.message}`, 'ERROR');

        // Check if this is an authentication-related error
        if (error.message.includes('authentication') ||
            error.message.includes('auth') ||
            error.message.includes('permission') ||
            error.message.includes('unauthorized') ||
            error.message.includes('forbidden')) {
            updateRelayConnectionStatus('auth_error');
            showAuthenticationWarning(error.message);
        } else {
            updateRelayConnectionStatus('error');
        }

        // Reset state on failure
        relayInfo = null;
        relayPubkey = null;
        isRelayConnected = false;

    } finally {
        connectRelayBtn.disabled = false;
    }
}

// Disconnect from relay
function disconnectFromRelay() {
    try {
        log('Disconnecting from relay...', 'INFO');

        // Clean up relay pool if exists
        if (relayPool) {
            const url = relayConnectionUrl.value.trim();
            if (url) {
                relayPool.close([url]);
            }
            relayPool = null;
            subscriptionId = null;
        }

        // Reset state
        relayInfo = null;
        relayPubkey = null;
        isRelayConnected = false;

        // Update UI
        updateRelayConnectionStatus('disconnected');
        hideRelayInfo();
        updateAdminSectionsVisibility();

        // Hide any authentication warnings
        hideAuthenticationWarning();

        log('Disconnected from relay', 'INFO');

    } catch (error) {
        log(`Error during relay disconnection: ${error.message}`, 'ERROR');
    }
}

// Update relay connection status UI
function updateRelayConnectionStatus(status) {
    if (!relayConnectionStatus) return;

    switch (status) {
        case 'connecting':
            relayConnectionStatus.textContent = 'CONNECTING...';
            relayConnectionStatus.className = 'status connected';
            connectRelayBtn.disabled = true;
            disconnectRelayBtn.disabled = true;
            restartRelayBtn.disabled = true;
            break;
        case 'connected':
            relayConnectionStatus.textContent = 'CONNECTED';
            relayConnectionStatus.className = 'status connected';
            connectRelayBtn.disabled = true;
            disconnectRelayBtn.disabled = false;
            restartRelayBtn.disabled = false;
            break;
        case 'disconnected':
            relayConnectionStatus.textContent = 'NOT CONNECTED';
            relayConnectionStatus.className = 'status disconnected';
            connectRelayBtn.disabled = false;
            disconnectRelayBtn.disabled = true;
            restartRelayBtn.disabled = true;
            break;
        case 'error':
            relayConnectionStatus.textContent = 'CONNECTION FAILED';
            relayConnectionStatus.className = 'status error';
            connectRelayBtn.disabled = false;
            disconnectRelayBtn.disabled = true;
            restartRelayBtn.disabled = true;
            break;
        case 'auth_error':
            relayConnectionStatus.textContent = 'AUTHENTICATION FAILED';
            relayConnectionStatus.className = 'status error';
            connectRelayBtn.disabled = false;
            disconnectRelayBtn.disabled = true;
            restartRelayBtn.disabled = true;
            break;
    }
}

// Hide relay information display (placeholder for removed functionality)
function hideRelayInfo() {
    // Relay info display functionality has been removed
    console.log('Relay info display functionality has been removed');
}

// Check for existing authentication state with multiple API methods and retry logic
async function checkExistingAuthWithRetries() {
    console.log('Starting authentication state detection with retry logic...');

    const maxAttempts = 3;
    const delay = 200; // ms between attempts (reduced from 500ms)

    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
        console.log(`Authentication detection attempt ${attempt}/${maxAttempts}`);

        try {
            // Method 1: Try window.NOSTR_LOGIN_LITE.getAuthState()
            if (window.NOSTR_LOGIN_LITE && typeof window.NOSTR_LOGIN_LITE.getAuthState === 'function') {
                console.log('Trying window.NOSTR_LOGIN_LITE.getAuthState()...');
                const authState = window.NOSTR_LOGIN_LITE.getAuthState();
                if (authState && authState.pubkey) {
                    console.log('✅ Auth state found via NOSTR_LOGIN_LITE.getAuthState():', authState.pubkey);
                    await restoreAuthenticationState(authState.pubkey);
                    return true;
                }
            }

            // Method 2: Try nlLite.getPublicKey()
            if (nlLite && typeof nlLite.getPublicKey === 'function') {
                console.log('Trying nlLite.getPublicKey()...');
                const pubkey = await nlLite.getPublicKey();
                if (pubkey && pubkey.length === 64) {
                    console.log('✅ Pubkey found via nlLite.getPublicKey():', pubkey);
                    await restoreAuthenticationState(pubkey);
                    return true;
                }
            }

            // Method 3: Try window.nostr.getPublicKey() (NIP-07)
            if (window.nostr && typeof window.nostr.getPublicKey === 'function') {
                console.log('Trying window.nostr.getPublicKey()...');
                const pubkey = await window.nostr.getPublicKey();
                if (pubkey && pubkey.length === 64) {
                    console.log('✅ Pubkey found via window.nostr.getPublicKey():', pubkey);
                    await restoreAuthenticationState(pubkey);
                    return true;
                }
            }

            // Method 4: Check localStorage directly for NOSTR_LOGIN_LITE data
            const localStorageData = localStorage.getItem('NOSTR_LOGIN_LITE_DATA');
            if (localStorageData) {
                try {
                    const parsedData = JSON.parse(localStorageData);
                    if (parsedData.pubkey) {
                        console.log('✅ Pubkey found in localStorage:', parsedData.pubkey);
                        await restoreAuthenticationState(parsedData.pubkey);
                        return true;
                    }
                } catch (parseError) {
                    console.log('Failed to parse localStorage data:', parseError.message);
                }
            }

            console.log(`❌ Attempt ${attempt}: No authentication found via any method`);

            // Wait before next attempt (except for last attempt)
            if (attempt < maxAttempts) {
                await new Promise(resolve => setTimeout(resolve, delay));
            }

        } catch (error) {
            console.log(`❌ Attempt ${attempt} failed:`, error.message);
            if (attempt < maxAttempts) {
                await new Promise(resolve => setTimeout(resolve, delay));
            }
        }
    }

    console.log('🔍 Authentication detection completed - no existing auth found after all attempts');
    return false;
}

// Helper function to restore authentication state
async function restoreAuthenticationState(pubkey) {
    console.log('🔄 Restoring authentication state for pubkey:', pubkey);

    userPubkey = pubkey;
    isLoggedIn = true;

    // Show main interface and profile in header
    showProfileInHeader();
    loadUserProfile();

    // Automatically attempt to connect to relay after restoring authentication state
    console.log('✅ Authentication state restored - automatically attempting to connect to relay...');
    setTimeout(() => {
        connectToRelay().catch(error => {
            console.log(`Automatic relay connection failed: ${error.message}`);
            // Check if this is an authentication-related error
            if (error.message.includes('authentication') ||
                error.message.includes('auth') ||
                error.message.includes('permission') ||
                error.message.includes('unauthorized') ||
                error.message.includes('forbidden')) {
                showAuthenticationWarning(error.message);
            }
        });
    }, 500); // Small delay to allow profile loading to complete

    console.log('✅ Authentication state restored successfully');
}

// Legacy function for backward compatibility
async function checkExistingAuth() {
    return await checkExistingAuthWithRetries();
}

// Initialize NOSTR_LOGIN_LITE
async function initializeApp() {
    try {
        await window.NOSTR_LOGIN_LITE.init({
            theme: 'default',
            methods: {
                extension: true,
                local: true,
                seedphrase: true,
                readonly: true,
                connect: true,
                remote: true,
                otp: false
            },
            floatingTab: {
                enabled: false
            }
        });

        nlLite = window.NOSTR_LOGIN_LITE;
        console.log('Nostr login system initialized');

        // Check for existing authentication state after initialization
        const wasAlreadyLoggedIn = await checkExistingAuth();
        if (wasAlreadyLoggedIn) {
            console.log('User was already logged in, showing profile in header');
            showProfileInHeader();
        } else {
            console.log('No existing authentication found, showing login modal');
            showLoginModal();
        }

        // Listen for authentication events
        window.addEventListener('nlMethodSelected', handleAuthEvent);
        window.addEventListener('nlLogout', handleLogoutEvent);

    } catch (error) {
        console.log('Failed to initialize Nostr login: ' + error.message);
    }
}

// Handle authentication events
function handleAuthEvent(event) {
    const { pubkey, method, error } = event.detail;

    if (method && pubkey) {
        userPubkey = pubkey;
        isLoggedIn = true;
        console.log(`Login successful! Method: ${method}`);
        console.log(`Public key: ${pubkey}`);

        // Hide login modal and show profile in header
        hideLoginModal();
        showProfileInHeader();
        loadUserProfile();

        // Automatically attempt to connect to relay after successful login
        console.log('Login successful. Automatically attempting to connect to relay...');
        setTimeout(() => {
            connectToRelay().catch(error => {
                console.log(`Automatic relay connection failed: ${error.message}`);
                // Check if this is an authentication-related error
                if (error.message.includes('authentication') ||
                    error.message.includes('auth') ||
                    error.message.includes('permission') ||
                    error.message.includes('unauthorized')) {
                    showAuthenticationWarning(error.message);
                }
            });
        }, 500); // Small delay to allow profile loading to complete

    } else if (error) {
        console.log(`Authentication error: ${error}`);
    }
}

// Handle logout events
function handleLogoutEvent() {
    console.log('Logout event received');

    userPubkey = null;
    isLoggedIn = false;
    currentConfig = null;

    // Clean up relay connection
    disconnectFromRelay();

    // Hide any authentication warnings
    hideAuthenticationWarning();

    // Reset UI - hide profile and show login modal
    hideProfileFromHeader();
    showLoginModal();

    updateConfigStatus(false);
    updateAdminSectionsVisibility();

    console.log('Logout event handled successfully');
}


// Update visibility of admin sections based on login and relay connection status
function updateAdminSectionsVisibility() {
    const divConfig = document.getElementById('div_config');
    const authRulesSection = document.getElementById('authRulesSection');
    const databaseStatisticsSection = document.getElementById('databaseStatisticsSection');
    const nip17DMSection = document.getElementById('nip17DMSection');
    const shouldShow = isLoggedIn && isRelayConnected;

    if (divConfig) divConfig.style.display = shouldShow ? 'block' : 'none';
    if (authRulesSection) authRulesSection.style.display = shouldShow ? 'block' : 'none';
    if (databaseStatisticsSection) databaseStatisticsSection.style.display = shouldShow ? 'block' : 'none';
    if (nip17DMSection) nip17DMSection.style.display = shouldShow ? 'block' : 'none';

    // Start/stop auto-refresh based on visibility
    if (shouldShow && databaseStatisticsSection && databaseStatisticsSection.style.display === 'block') {
        startStatsAutoRefresh();
    } else {
        stopStatsAutoRefresh();
    }

    // Update countdown display when visibility changes
    updateCountdownDisplay();
}

// Show login modal
function showLoginModal() {
    if (loginModal && loginModalContainer) {
        // Initialize the login UI in the modal
        if (window.NOSTR_LOGIN_LITE && typeof window.NOSTR_LOGIN_LITE.embed === 'function') {
            window.NOSTR_LOGIN_LITE.embed('#login-modal-container', {
                seamless: true
            });
        }
        loginModal.style.display = 'flex';
    }
}

// Hide login modal
function hideLoginModal() {
    if (loginModal) {
        loginModal.style.display = 'none';
    }
}

// Show profile in header
function showProfileInHeader() {
    if (profileArea) {
        profileArea.style.display = 'flex';
    }
}

// Hide profile from header
function hideProfileFromHeader() {
    if (profileArea) {
        profileArea.style.display = 'none';
    }
    // Also hide logout dropdown if visible
    if (logoutDropdown) {
        logoutDropdown.style.display = 'none';
    }
}

// Update login/logout UI visibility (legacy function - kept for backward compatibility)
function updateLoginLogoutUI() {
    // This function is now handled by showProfileInHeader() and hideProfileFromHeader()
    // Kept for backward compatibility with any existing code that might call it
}

// Show main interface after login (legacy function - kept for backward compatibility)
function showMainInterface() {
    // This function is now handled by showProfileInHeader() and updateAdminSectionsVisibility()
    // Kept for backward compatibility with any existing code that might call it
    updateAdminSectionsVisibility();
}

// Load user profile using nostr-tools pool
async function loadUserProfile() {
    if (!userPubkey) return;

    console.log('Loading user profile...');

    // Update header display (new system)
    if (headerUserName) {
        headerUserName.textContent = 'Loading...';
    }

    // Update legacy elements if they exist (backward compatibility)
    if (persistentUserName) {
        persistentUserName.textContent = 'Loading...';
    }
    if (persistentUserAbout) {
        persistentUserAbout.textContent = 'Loading...';
    }

    // Convert hex pubkey to npub for initial display
    let displayPubkey = userPubkey;
    let npubLink = '';
    try {
        if (userPubkey && userPubkey.length === 64 && /^[0-9a-fA-F]+$/.test(userPubkey)) {
            const npub = window.NostrTools.nip19.npubEncode(userPubkey);
            displayPubkey = npub;
            npubLink = `<a href="https://njump.me/${npub}" target="_blank" class="npub-link">${npub}</a>`;
        }
    } catch (error) {
        console.log('Failed to encode user pubkey to npub:', error.message);
    }

    if (persistentUserPubkey) {
        if (npubLink) {
            persistentUserPubkey.innerHTML = npubLink;
        } else {
            persistentUserPubkey.textContent = displayPubkey;
        }
    }

    try {
        // Create a SimplePool instance for profile loading
        const profilePool = new window.NostrTools.SimplePool();
        const relays = ['wss://relay.damus.io',
            'wss://relay.nostr.band',
            'wss://nos.lol',
            'wss://relay.primal.net',
            'wss://relay.snort.social',
            'wss://relay.laantungir.net'];

        // Get profile event (kind 0) for the user
        const events = await profilePool.querySync(relays, {
            kinds: [0],
            authors: [userPubkey],
            limit: 1
        });

        if (events.length > 0) {
            console.log('Profile event found:', events[0]);
            const profile = JSON.parse(events[0].content);
            console.log('Parsed profile:', profile);
            displayProfile(profile);
        } else {
            console.log('No profile events found for pubkey:', userPubkey);

            // Update header display (new system)
            if (headerUserName) {
                headerUserName.textContent = 'Anonymous User';
            }

            // Update legacy elements if they exist (backward compatibility)
            if (persistentUserName) {
                persistentUserName.textContent = 'Anonymous User';
            }
            if (persistentUserAbout) {
                persistentUserAbout.textContent = 'No profile found';
            }
            // Keep the npub display
        }

        // Close the profile pool
        profilePool.close(relays);

    } catch (error) {
        console.log('Profile loading failed: ' + error.message);

        // Update header display (new system)
        if (headerUserName) {
            headerUserName.textContent = 'Error loading profile';
        }

        // Update legacy elements if they exist (backward compatibility)
        if (persistentUserName) {
            persistentUserName.textContent = 'Error loading profile';
        }
        if (persistentUserAbout) {
            persistentUserAbout.textContent = error.message;
        }
        // Keep the npub display
    }
}

// Display profile data
function displayProfile(profile) {
    const name = profile.name || profile.display_name || profile.displayName || 'Anonymous User';
    const about = profile.about || 'No description provided';
    const picture = profile.picture || profile.image || null;

    // Convert hex pubkey to npub for display
    let displayPubkey = userPubkey;
    let npubLink = '';
    try {
        if (userPubkey && userPubkey.length === 64 && /^[0-9a-fA-F]+$/.test(userPubkey)) {
            const npub = window.NostrTools.nip19.npubEncode(userPubkey);
            displayPubkey = npub;
            npubLink = `<a href="https://njump.me/${npub}" target="_blank" class="npub-link">${npub}</a>`;
        }
    } catch (error) {
        console.log('Failed to encode user pubkey to npub:', error.message);
    }

    // Update header profile display
    if (headerUserName) {
        headerUserName.textContent = name;
    }

    // Handle header profile picture
    if (headerUserImage) {
        if (picture && typeof picture === 'string' && (picture.startsWith('http') || picture.startsWith('https'))) {
            headerUserImage.src = picture;
            headerUserImage.style.display = 'block';
            headerUserImage.onerror = function() {
                // Hide image on error
                this.style.display = 'none';
                console.log('Profile image failed to load:', picture);
            };
        } else {
            headerUserImage.style.display = 'none';
        }
    }

    // Update legacy persistent user details (kept for backward compatibility)
    if (persistentUserName) persistentUserName.textContent = name;
    if (persistentUserPubkey && npubLink) {
        persistentUserPubkey.innerHTML = npubLink;
    } else if (persistentUserPubkey) {
        persistentUserPubkey.textContent = displayPubkey;
    }
    if (persistentUserAbout) persistentUserAbout.textContent = about;

    // Handle legacy profile picture
    const userImageContainer = document.getElementById('persistent-user-image');
    if (userImageContainer) {
        if (picture && typeof picture === 'string' && picture.startsWith('http')) {
            // Create or update image element
            let img = userImageContainer.querySelector('img');
            if (!img) {
                img = document.createElement('img');
                img.className = 'user-profile-image';
                img.alt = `${name}'s profile picture`;
                img.onerror = function() {
                    // Hide image on error
                    this.style.display = 'none';
                };
                userImageContainer.appendChild(img);
            }
            img.src = picture;
            img.style.display = 'block';
        } else {
            // Hide image if no valid picture
            const img = userImageContainer.querySelector('img');
            if (img) {
                img.style.display = 'none';
            }
        }
    }

    console.log(`Profile loaded for: ${name} with pubkey: ${userPubkey}`);
}

// Logout function
async function logout() {
    log('Logging out...', 'INFO');
    try {
        // Stop auto-refresh before disconnecting
        stopStatsAutoRefresh();

        // Clean up relay connection
        disconnectFromRelay();

        // Clean up configuration pool
        if (relayPool) {
            log('Closing configuration pool...', 'INFO');
            const url = relayConnectionUrl.value.trim();
            if (url) {
                relayPool.close([url]);
            }
            relayPool = null;
            subscriptionId = null;
        }

        await nlLite.logout();

        userPubkey = null;
        isLoggedIn = false;
        currentConfig = null;

        // Hide any authentication warnings
        hideAuthenticationWarning();

        // Reset UI - hide profile and show login modal
        hideProfileFromHeader();
        // showLoginModal() removed - handled by handleLogoutEvent()

        updateConfigStatus(false);
        updateAdminSectionsVisibility();

        log('Logged out successfully', 'INFO');

    } catch (error) {
        log('Logout failed: ' + error.message, 'ERROR');
    }
}

function updateConfigStatus(loaded) {
    if (loaded) {
        configDisplay.classList.remove('hidden');
    } else {
        configDisplay.classList.add('hidden');
    }
}



// Generate random subscription ID (avoiding colons which are rejected by relay)
function generateSubId() {
    // Use only alphanumeric characters, underscores, and hyphens
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
    let result = '';
    for (let i = 0; i < 12; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
}

// Configuration subscription using nostr-tools SimplePool
async function subscribeToConfiguration() {
    try {
        console.log('=== STARTING SIMPLEPOOL CONFIGURATION SUBSCRIPTION ===');

        if (!isLoggedIn) {
            console.log('WARNING: Not logged in, but proceeding with subscription test');
        }

        const url = relayConnectionUrl.value.trim();
        if (!url) {
            console.error('Please enter a relay URL');
            return false;
        }

        console.log(`Connecting to relay via SimplePool: ${url}`);

        // Clean up existing pool
        if (relayPool) {
            console.log('Closing existing pool connection');
            relayPool.close([url]);
            relayPool = null;
            subscriptionId = null;
        }

        // Create new SimplePool instance
        relayPool = new window.NostrTools.SimplePool();
        subscriptionId = generateSubId();

        console.log(`Generated subscription ID: ${subscriptionId}`);
        console.log(`User pubkey ${userPubkey}`)
        // Subscribe to kind 23457 events (admin response events), kind 4 (NIP-04 DMs), and kind 1059 (NIP-17 GiftWrap)
        const subscription = relayPool.subscribeMany([url], [{
            since: Math.floor(Date.now() / 1000) - 5,  // Look back 5 seconds to avoid race condition
            kinds: [23457],
            authors: [getRelayPubkey()], // Only listen to responses from the relay
            "#p": [userPubkey], // Only responses directed to this user
            limit: 50
        }, {
            since: Math.floor(Date.now() / 1000),
            kinds: [4], // NIP-04 Direct Messages
            authors: [getRelayPubkey()], // Only listen to DMs from the relay
            "#p": [userPubkey], // Only DMs directed to this user
            limit: 50
        }, {
            kinds: [1059], // NIP-17 GiftWrap events
            "#p": [userPubkey], // Only GiftWrap events addressed to this user
            limit: 50
        }], {
            async onevent(event) {
                console.log('=== EVENT RECEIVED VIA SIMPLEPOOL ===');
                console.log('Event data:', event);
                console.log('Event kind:', event.kind);
                console.log('Event tags:', event.tags);
                console.log('Event pubkey:', event.pubkey);
                console.log('=== END EVENT ===');

                // Handle NIP-04 DMs
                if (event.kind === 4) {
                    console.log('=== NIP-04 DM RECEIVED ===');
                    try {
                        // Decrypt the DM content
                        const decryptedContent = await window.nostr.nip04.decrypt(event.pubkey, event.content);
                        log(`Received NIP-04 DM from relay: ${decryptedContent.substring(0, 50)}...`, 'INFO');

                        // Add to inbox
                        const timestamp = new Date(event.created_at * 1000).toLocaleString();
                        addMessageToInbox('received', decryptedContent, timestamp, event.pubkey);

                        // Log for testing
                        if (typeof logTestEvent === 'function') {
                            logTestEvent('RECV', `NIP-04 DM: ${decryptedContent}`, 'DM');
                        }
                    } catch (decryptError) {
                        log(`Failed to decrypt NIP-04 DM: ${decryptError.message}`, 'ERROR');
                        if (typeof logTestEvent === 'function') {
                            logTestEvent('ERROR', `Failed to decrypt DM: ${decryptError.message}`, 'DM');
                        }
                    }
                    return;
                }

                // Handle NIP-17 GiftWrap DMs
                if (event.kind === 1059) {
                    console.log('=== NIP-17 GIFTWRAP RECEIVED ===');
                    try {
                        // Step 1: Unwrap gift wrap to get seal
                        const sealJson = await window.nostr.nip44.decrypt(event.pubkey, event.content);
                        const seal = safeJsonParse(sealJson);
                        if (!seal || seal.kind !== 13) {
                            throw new Error('Unwrapped content is not a valid seal (kind 13)');
                        }

                        // Step 2: Unseal to get rumor
                        const rumorJson = await window.nostr.nip44.decrypt(seal.pubkey, seal.content);
                        const rumor = safeJsonParse(rumorJson);
                        if (!rumor || rumor.kind !== 14) {
                            throw new Error('Unsealed content is not a valid rumor (kind 14)');
                        }

                        log(`Received NIP-17 DM from relay: ${rumor.content.substring(0, 50)}...`, 'INFO');

                        // Add to inbox
                        const timestamp = new Date(event.created_at * 1000).toLocaleString();
                        addMessageToInbox('received', rumor.content, timestamp, rumor.pubkey);

                        // Log for testing
                        if (typeof logTestEvent === 'function') {
                            logTestEvent('RECV', `NIP-17 DM: ${rumor.content}`, 'DM');
                        }
                    } catch (unwrapError) {
                        log(`Failed to unwrap NIP-17 DM: ${unwrapError.message}`, 'ERROR');
                        if (typeof logTestEvent === 'function') {
                            logTestEvent('ERROR', `Failed to unwrap DM: ${unwrapError.message}`, 'DM');
                        }
                    }
                    return;
                }

                // Handle admin response events (kind 23457)
                if (event.kind === 23457) {
                    // Log all received messages for testing
                    if (typeof logTestEvent === 'function') {
                        logTestEvent('RECV', `Admin response event: ${JSON.stringify(event)}`, 'EVENT');
                    }

                    // Process admin response event
                    processAdminResponse(event);
                }
            },
            oneose() {
                console.log('EOSE received - End of stored events');
                console.log('Current config after EOSE:', currentConfig);

                if (!currentConfig) {
                    console.log('No configuration events were received');
                }
            },
            onclose(reason) {
                console.log('Subscription closed:', reason);
                updateConfigStatus(false);
            }
        });

        // Store subscription for cleanup
        relayPool.currentSubscription = subscription;

        console.log('SimplePool subscription established');
        return true;

    } catch (error) {
        console.error('Configuration subscription failed:', error.message);
        console.error('Configuration subscription failed:', error);
        console.error('Error stack:', error.stack);
        return false;
    }
}

// Process admin response events (kind 23457)
async function processAdminResponse(event) {
    try {
        console.log('=== PROCESSING ADMIN RESPONSE ===');
        console.log('Response event:', event);

        // Verify this is a kind 23457 admin response event
        if (event.kind !== 23457) {
            console.log('Ignoring non-admin response event, kind:', event.kind);
            return;
        }

        // Verify the event is from the relay
        const expectedRelayPubkey = getRelayPubkey();
        if (event.pubkey !== expectedRelayPubkey) {
            console.log('Ignoring response from unknown pubkey:', event.pubkey);
            return;
        }

        // Decrypt the NIP-44 encrypted content
        const decryptedContent = await decryptFromRelay(event.content);
        if (!decryptedContent) {
            throw new Error('Failed to decrypt admin response content');
        }

        console.log('Decrypted admin response:', decryptedContent);

        // Parse the decrypted JSON response
        const responseData = JSON.parse(decryptedContent);
        console.log('Parsed response data:', responseData);

        // Log the response for testing
        if (typeof logTestEvent === 'function') {
            logTestEvent('RECV', `Decrypted response: ${JSON.stringify(responseData)}`, 'RESPONSE');
        }

        // Handle different types of admin responses
        handleAdminResponseData(responseData);

    } catch (error) {
        console.error('Error processing admin response:', error);
        if (typeof logTestEvent === 'function') {
            logTestEvent('ERROR', `Failed to process admin response: ${error.message}`, 'ERROR');
        }
    }
}

// Handle different types of admin response data
function handleAdminResponseData(responseData) {
    try {
        console.log('=== HANDLING ADMIN RESPONSE DATA ===');
        console.log('Response data:', responseData);
        console.log('Response query_type:', responseData.query_type);

        // Handle auth query responses - updated to match backend response types
        if (responseData.query_type &&
            (responseData.query_type.includes('auth_rules') ||
                responseData.query_type.includes('auth'))) {
            console.log('Routing to auth query handler');
            handleAuthQueryResponse(responseData);
            return;
        }

        // Handle config update responses specifically
        if (responseData.query_type === 'config_update') {
            console.log('Routing to config update handler');
            handleConfigUpdateResponse(responseData);
            return;
        }

        // Handle config query responses - updated to match backend response types
        if (responseData.query_type &&
            (responseData.query_type.includes('config') ||
                responseData.query_type.startsWith('config_'))) {
            console.log('Routing to config query handler');
            handleConfigQueryResponse(responseData);
            return;
        }

        // Handle system command responses
        if (responseData.command) {
            console.log('Routing to system command handler');
            handleSystemCommandResponse(responseData);
            return;
        }

        // Handle auth rule modification responses
        if (responseData.operation || responseData.rules_processed !== undefined) {
            console.log('Routing to auth rule modification handler');
            handleAuthRuleResponse(responseData);
            return;
        }

        // Handle stats query responses
        if (responseData.query_type === 'stats_query') {
            console.log('Routing to stats query handler');
            handleStatsQueryResponse(responseData);
            return;
        }

        // Generic response handling
        console.log('Using generic response handler');
        if (typeof logTestEvent === 'function') {
            logTestEvent('RECV', `Generic admin response: ${JSON.stringify(responseData)}`, 'RESPONSE');
        }

    } catch (error) {
        console.error('Error handling admin response data:', error);
        if (typeof logTestEvent === 'function') {
            logTestEvent('ERROR', `Failed to handle response data: ${error.message}`, 'ERROR');
        }
    }
}

// Handle config query responses
function handleConfigQueryResponse(responseData) {
    console.log('=== CONFIG QUERY RESPONSE ===');
    console.log('Query type:', responseData.query_type);
    console.log('Total results:', responseData.total_results);
    console.log('Data:', responseData.data);

    // Convert the config response data to the format expected by displayConfiguration
    if (responseData.data && responseData.data.length > 0) {
        console.log('Converting config response to display format...');

        // Create a synthetic event structure for displayConfiguration
        const syntheticEvent = {
            id: 'config_response_' + Date.now(),
            pubkey: getRelayPubkey(),
            created_at: Math.floor(Date.now() / 1000),
            kind: 'config_response',
            content: 'Configuration from admin API',
            tags: []
        };

        // Convert config data to tags format
        responseData.data.forEach(config => {
            const key = config.key || config.config_key;
            const value = config.value || config.config_value;
            if (key && value !== undefined) {
                syntheticEvent.tags.push([key, value]);
            }
        });

        console.log('Synthetic event created:', syntheticEvent);
        console.log('Calling displayConfiguration with synthetic event...');

        // Display the configuration using the original display function
        displayConfiguration(syntheticEvent);

        log(`Configuration loaded: ${responseData.total_results} parameters`, 'INFO');
    } else {
        console.log('No configuration data received');
        updateConfigStatus(false);
    }

    // Also log to test interface for debugging
    if (typeof logTestEvent === 'function') {
        logTestEvent('RECV', `Config query response: ${responseData.query_type}, ${responseData.total_results} results`, 'CONFIG_QUERY');

        if (responseData.data && responseData.data.length > 0) {
            logTestEvent('RECV', '=== CONFIGURATION VALUES ===', 'CONFIG');
            responseData.data.forEach((config, index) => {
                const key = config.key || config.config_key || `config_${index}`;
                const value = config.value || config.config_value || 'undefined';
                const category = config.category || 'general';
                const dataType = config.data_type || 'string';

                logTestEvent('RECV', `${key}: ${value} (${dataType}, ${category})`, 'CONFIG');
            });
            logTestEvent('RECV', '=== END CONFIGURATION VALUES ===', 'CONFIG');
        } else {
            logTestEvent('RECV', 'No configuration values found', 'CONFIG_QUERY');
        }
    }
}

// Handle config update responses
function handleConfigUpdateResponse(responseData) {
    console.log('=== CONFIG UPDATE RESPONSE ===');
    console.log('Query type:', responseData.query_type);
    console.log('Status:', responseData.status);
    console.log('Data:', responseData.data);

    if (responseData.status === 'success') {
        const updatesApplied = responseData.updates_applied || 0;
        log(`Configuration updated successfully: ${updatesApplied} parameters changed`, 'INFO');

        // Show success message with details
        if (responseData.data && Array.isArray(responseData.data)) {
            responseData.data.forEach((config, index) => {
                if (config.status === 'success') {
                    log(`✓ ${config.key}: ${config.value} (${config.data_type})`, 'INFO');
                } else {
                    log(`✗ ${config.key}: ${config.error || 'Failed to update'}`, 'ERROR');
                }
            });
        }

        // Configuration updated successfully - user can manually refresh using Fetch Config button
        log('Configuration updated successfully. Click "Fetch Config" to refresh the display.', 'INFO');

    } else {
        const errorMessage = responseData.message || responseData.error || 'Unknown error';
        log(`Configuration update failed: ${errorMessage}`, 'ERROR');

        // Show detailed error information if available
        if (responseData.data && Array.isArray(responseData.data)) {
            responseData.data.forEach((config, index) => {
                if (config.status === 'error') {
                    log(`✗ ${config.key}: ${config.error || 'Failed to update'}`, 'ERROR');
                }
            });
        }
    }

    // Log to test interface for debugging
    if (typeof logTestEvent === 'function') {
        logTestEvent('RECV', `Config update response: ${responseData.status}`, 'CONFIG_UPDATE');

        if (responseData.data && responseData.data.length > 0) {
            responseData.data.forEach((config, index) => {
                const status = config.status === 'success' ? '✓' : '✗';
                const message = config.status === 'success' ?
                    `${config.key} = ${config.value}` :
                    `${config.key}: ${config.error || 'Failed'}`;
                logTestEvent('RECV', `${status} ${message}`, 'CONFIG_UPDATE');
            });
        } else {
            logTestEvent('RECV', 'No configuration update details received', 'CONFIG_UPDATE');
        }
    }
}

// Handle auth query responses
function handleAuthQueryResponse(responseData) {
    console.log('=== AUTH QUERY RESPONSE ===');
    console.log('Query type:', responseData.query_type);
    console.log('Total results:', responseData.total_results);
    console.log('Data:', responseData.data);

    // Update the current auth rules with the response data
    if (responseData.data && Array.isArray(responseData.data)) {
        currentAuthRules = responseData.data;
        console.log('Updated currentAuthRules with', currentAuthRules.length, 'rules');

        // Always show the auth rules table when we receive data (no VIEW RULES button anymore)
        console.log('Auto-showing auth rules table since we received data...');
        showAuthRulesTable();

        updateAuthRulesStatus('loaded');
        log(`Loaded ${responseData.total_results} auth rules from relay`, 'INFO');
    } else {
        currentAuthRules = [];
        console.log('No auth rules data received, cleared currentAuthRules');

        // Show empty table (no VIEW RULES button anymore)
        console.log('Auto-showing auth rules table with empty data...');
        showAuthRulesTable();

        updateAuthRulesStatus('loaded');
        log('No auth rules found on relay', 'INFO');
    }

    if (typeof logTestEvent === 'function') {
        logTestEvent('RECV', `Auth query response: ${responseData.query_type}, ${responseData.total_results} results`, 'AUTH_QUERY');

        if (responseData.data && responseData.data.length > 0) {
            responseData.data.forEach((rule, index) => {
                logTestEvent('RECV', `Rule ${index + 1}: ${rule.rule_type} - ${rule.pattern_value || rule.rule_target}`, 'AUTH_RULE');
            });
        } else {
            logTestEvent('RECV', 'No auth rules found', 'AUTH_QUERY');
        }
    }
}

// Handle system command responses
function handleSystemCommandResponse(responseData) {
    console.log('=== SYSTEM COMMAND RESPONSE ===');
    console.log('Command:', responseData.command);
    console.log('Status:', responseData.status);

    // Handle delete auth rule responses
    if (responseData.command === 'delete_auth_rule') {
        if (responseData.status === 'success') {
            log('Auth rule deleted successfully', 'INFO');
            // Refresh the auth rules display
            loadAuthRules();
        } else {
            log(`Failed to delete auth rule: ${responseData.message || 'Unknown error'}`, 'ERROR');
        }
    }

    // Handle clear all auth rules responses
    if (responseData.command === 'clear_all_auth_rules') {
        if (responseData.status === 'success') {
            const rulesCleared = responseData.rules_cleared || 0;
            log(`Successfully cleared ${rulesCleared} auth rules`, 'INFO');
            // Clear local auth rules and refresh display
            currentAuthRules = [];
            displayAuthRules(currentAuthRules);
        } else {
            log(`Failed to clear auth rules: ${responseData.message || 'Unknown error'}`, 'ERROR');
        }
    }

    if (typeof logTestEvent === 'function') {
        logTestEvent('RECV', `System command response: ${responseData.command} - ${responseData.status}`, 'SYSTEM_CMD');
    }
}

// Handle auth rule modification responses
function handleAuthRuleResponse(responseData) {
    console.log('=== AUTH RULE MODIFICATION RESPONSE ===');
    console.log('Operation:', responseData.operation);
    console.log('Status:', responseData.status);

    // Handle auth rule addition/modification responses
    if (responseData.status === 'success') {
        const rulesProcessed = responseData.rules_processed || 0;
        log(`Successfully processed ${rulesProcessed} auth rule modifications`, 'INFO');

        // Refresh the auth rules display to show the new rules
        if (authRulesTableContainer && authRulesTableContainer.style.display !== 'none') {
            loadAuthRules();
        }
    } else {
        log(`Failed to process auth rule modifications: ${responseData.message || 'Unknown error'}`, 'ERROR');
    }

    if (typeof logTestEvent === 'function') {
        logTestEvent('RECV', `Auth rule response: ${responseData.operation} - ${responseData.status}`, 'AUTH_RULE');

        if (responseData.processed_rules) {
            responseData.processed_rules.forEach((rule, index) => {
                logTestEvent('RECV', `Processed rule ${index + 1}: ${rule.rule_type} - ${rule.pattern_value || rule.rule_target}`, 'AUTH_RULE');
            });
        }
    }
}

// Helper function to decrypt content from relay using NIP-44
async function decryptFromRelay(encryptedContent) {
    try {
        console.log('Decrypting content from relay...');

        // Get the relay public key for decryption
        const relayPubkey = getRelayPubkey();

        // Use NIP-07 extension's NIP-44 decrypt method
        if (!window.nostr || !window.nostr.nip44) {
            throw new Error('NIP-44 decryption not available via NIP-07 extension');
        }

        const decryptedContent = await window.nostr.nip44.decrypt(relayPubkey, encryptedContent);

        if (!decryptedContent) {
            throw new Error('NIP-44 decryption returned empty result');
        }

        console.log('Successfully decrypted content from relay');
        return decryptedContent;

    } catch (error) {
        console.error('NIP-44 decryption failed:', error);
        throw error;
    }
}

// Fetch configuration using admin API
async function fetchConfiguration() {
    try {
        console.log('=== FETCHING CONFIGURATION VIA ADMIN API ===');

        // Require both login and relay connection
        if (!isLoggedIn || !userPubkey) {
            throw new Error('Must be logged in to fetch configuration');
        }

        if (!isRelayConnected || !relayPubkey) {
            throw new Error('Must be connected to relay to fetch configuration. Please use the Relay Connection section first.');
        }

        // First establish subscription to receive responses
        const subscriptionResult = await subscribeToConfiguration();
        if (!subscriptionResult) {
            throw new Error('Failed to establish admin response subscription');
        }

        // Wait a moment for subscription to be established
        await new Promise(resolve => setTimeout(resolve, 500));

        // Send config query command if logged in
        if (isLoggedIn && userPubkey && relayPool) {
            console.log('Sending config query command...');

            // Create command array for getting configuration
            const command_array = ["config_query", "all"];

            // Encrypt the command array directly using NIP-44
            const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
            if (!encrypted_content) {
                throw new Error('Failed to encrypt command array');
            }

            // Create single kind 23456 admin event
            const configEvent = {
                kind: 23456,
                pubkey: userPubkey,
                created_at: Math.floor(Date.now() / 1000),
                tags: [["p", getRelayPubkey()]],
                content: encrypted_content
            };

            // Sign the event
            const signedEvent = await window.nostr.signEvent(configEvent);
            if (!signedEvent || !signedEvent.sig) {
                throw new Error('Event signing failed');
            }

            console.log('Config query event signed, publishing...');

            // Publish via SimplePool with detailed error diagnostics
            const url = relayConnectionUrl.value.trim();
            const publishPromises = relayPool.publish([url], signedEvent);

            // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
            const results = await Promise.allSettled(publishPromises);

            // Log detailed publish results for diagnostics
            let successCount = 0;
            results.forEach((result, index) => {
                if (result.status === 'fulfilled') {
                    successCount++;
                    console.log(`✅ Relay ${index} (${url}): Event published successfully`);
                    if (typeof logTestEvent === 'function') {
                        logTestEvent('INFO', `Relay ${index} publish success`, 'PUBLISH');
                    }
                } else {
                    console.error(`❌ Relay ${index} (${url}): Publish failed:`, result.reason);
                    if (typeof logTestEvent === 'function') {
                        logTestEvent('ERROR', `Relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
                    }
                }
            });

            // Throw error if all relays failed
            if (successCount === 0) {
                const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
                throw new Error(`All relays rejected the event. Details: ${errorDetails}`);
            }

            console.log('Config query command sent successfully - waiting for response...');

        } else {
            console.log('Not logged in - only subscription established for testing');
        }

        return true;

    } catch (error) {
        console.error('Failed to fetch configuration:', error);
        return false;
    }
}

function displayConfiguration(event) {
    try {
        console.log('=== DISPLAYING CONFIGURATION EVENT ===');
        console.log('Event received for display:', event);

        currentConfig = event;

        // Clear existing table
        configTableBody.innerHTML = '';

        // Display tags (editable configuration parameters only)
        console.log(`Processing ${event.tags.length} configuration parameters`);
        event.tags.forEach((tag, index) => {
            if (tag.length >= 2) {
                const row = document.createElement('tr');
                const key = tag[0];
                const value = tag[1];

                // Create editable input for value
                const valueInput = document.createElement('input');
                valueInput.type = 'text';
                valueInput.value = value;
                valueInput.className = 'config-value-input';
                valueInput.dataset.key = key;
                valueInput.dataset.originalValue = value;
                valueInput.dataset.rowIndex = index;

                // Create clickable Actions cell
                const actionsCell = document.createElement('td');
                actionsCell.className = 'config-actions-cell';
                actionsCell.textContent = 'SAVE';
                actionsCell.dataset.key = key;
                actionsCell.dataset.originalValue = value;
                actionsCell.dataset.rowIndex = index;

                // Initially hide the SAVE text
                actionsCell.style.color = 'transparent';

                // Show SAVE text and make clickable when value changes
                valueInput.addEventListener('input', function () {
                    if (this.value !== this.dataset.originalValue) {
                        actionsCell.style.color = 'var(--primary-color)';
                        actionsCell.style.cursor = 'pointer';
                        actionsCell.onclick = () => saveIndividualConfig(key, valueInput.value, valueInput.dataset.originalValue, actionsCell);
                    } else {
                        actionsCell.style.color = 'transparent';
                        actionsCell.style.cursor = 'default';
                        actionsCell.onclick = null;
                    }
                });

                row.innerHTML = `<td>${key}</td><td></td>`;
                row.cells[1].appendChild(valueInput);
                row.appendChild(actionsCell);
                configTableBody.appendChild(row);
            }
        });

        // Show message if no configuration parameters found
        if (event.tags.length === 0) {
            const row = document.createElement('tr');
            row.innerHTML = `<td colspan="3" style="text-align: center; font-style: italic;">No configuration parameters found</td>`;
            configTableBody.appendChild(row);
        }

        console.log('Configuration display completed successfully');
        updateConfigStatus(true);

    } catch (error) {
        console.error('Error in displayConfiguration:', error.message);
        console.error('Display configuration error:', error);
    }
}

// Save individual configuration parameter
async function saveIndividualConfig(key, newValue, originalValue, actionsCell) {
    if (!isLoggedIn || !userPubkey) {
        log('Must be logged in to save configuration', 'ERROR');
        return;
    }

    if (!currentConfig) {
        log('No current configuration to update', 'ERROR');
        return;
    }

    // Don't save if value hasn't changed
    if (newValue === originalValue) {
        return;
    }

    try {
        log(`Saving individual config: ${key} = ${newValue}`, 'INFO');

        // Determine data type based on key name
        let dataType = 'string';
        if (['max_connections', 'pow_min_difficulty', 'nip42_challenge_timeout', 'max_subscriptions_per_client', 'max_event_tags', 'max_content_length'].includes(key)) {
            dataType = 'integer';
        } else if (['auth_enabled', 'nip42_auth_required', 'nip40_expiration_enabled'].includes(key)) {
            dataType = 'boolean';
        }

        // Determine category based on key name
        let category = 'general';
        if (key.startsWith('relay_')) {
            category = 'relay';
        } else if (key.startsWith('nip40_')) {
            category = 'expiration';
        } else if (key.startsWith('nip42_') || key.startsWith('auth_')) {
            category = 'authentication';
        } else if (key.startsWith('pow_')) {
            category = 'proof_of_work';
        } else if (key.startsWith('max_')) {
            category = 'limits';
        }

        const configObj = {
            key: key,
            value: newValue,
            data_type: dataType,
            category: category
        };

        // Update cell during save
        actionsCell.textContent = 'SAVING...';
        actionsCell.style.color = 'var(--accent-color)';
        actionsCell.style.cursor = 'not-allowed';
        actionsCell.onclick = null;

        // Send single config update
        await sendConfigUpdateCommand([configObj]);

        // Update the original value on success
        const input = actionsCell.parentElement.cells[1].querySelector('input');
        if (input) {
            input.dataset.originalValue = newValue;
            // Hide SAVE text since value now matches original
            actionsCell.style.color = 'transparent';
            actionsCell.style.cursor = 'default';
            actionsCell.onclick = null;
        }

        actionsCell.textContent = 'SAVED';
        actionsCell.style.color = 'var(--accent-color)';
        setTimeout(() => {
            actionsCell.textContent = 'SAVE';
            // Keep transparent if value matches original
            if (input && input.value === input.dataset.originalValue) {
                actionsCell.style.color = 'transparent';
            }
        }, 2000);

        log(`Successfully saved config: ${key} = ${newValue}`, 'INFO');

    } catch (error) {
        log(`Failed to save individual config ${key}: ${error.message}`, 'ERROR');
        actionsCell.textContent = 'SAVE';
        actionsCell.style.color = 'var(--primary-color)';
        actionsCell.style.cursor = 'pointer';
        actionsCell.onclick = () => saveIndividualConfig(key, actionsCell.parentElement.cells[1].querySelector('input').value, originalValue, actionsCell);
    }
}




// Send config update command using kind 23456 with Administrator API (inner events)
async function sendConfigUpdateCommand(configObjects) {
    try {
        if (!relayPool) {
            throw new Error('SimplePool connection not available');
        }

        console.log(`Sending config_update command with ${configObjects.length} configuration object(s)`);

        // Create command array for config update
        const command_array = ["config_update", configObjects];

        // Encrypt the command array directly using NIP-44
        const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
        if (!encrypted_content) {
            throw new Error('Failed to encrypt command array');
        }

        // Create single kind 23456 admin event
        const configEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [["p", getRelayPubkey()]],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(configEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        console.log(`Config update event signed with ${configObjects.length} object(s)`);

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                console.log(`✅ Config Update Relay ${index} (${url}): Event published successfully`);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('INFO', `Config update relay ${index} publish success`, 'PUBLISH');
                }
            } else {
                console.error(`❌ Config Update Relay ${index} (${url}): Publish failed:`, result.reason);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('ERROR', `Config update relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
                }
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected config update event. Details: ${errorDetails}`);
        }

        console.log(`Config update command sent successfully with ${configObjects.length} configuration object(s)`);

        // Log for testing
        if (typeof logTestEvent === 'function') {
            logTestEvent('SENT', `Config update command: ${configObjects.length} object(s)`, 'CONFIG_UPDATE');
            configObjects.forEach((config, index) => {
                logTestEvent('SENT', `Config ${index + 1}: ${config.key} = ${config.value} (${config.data_type})`, 'CONFIG');
            });
        }

    } catch (error) {
        console.error(`Failed to send config_update command:`, error);
        throw error;
    }
}



// Profile area click handler for logout dropdown
function toggleLogoutDropdown(event) {
    if (!logoutDropdown) return;

    // Only toggle if clicking on the image, not the text or container
    if (event.target === headerUserImage) {
        const isVisible = logoutDropdown.style.display === 'block';
        logoutDropdown.style.display = isVisible ? 'none' : 'block';
    }
}

// Close logout dropdown when clicking outside
document.addEventListener('click', function(event) {
    if (profileArea && logoutDropdown && !profileArea.contains(event.target)) {
        logoutDropdown.style.display = 'none';
    }
});

// Initialize profile area click handler
if (profileArea) {
    profileArea.addEventListener('click', toggleLogoutDropdown);
}

// Initialize logout button handler
if (logoutBtn) {
    logoutBtn.addEventListener('click', function(e) {
        e.stopPropagation(); // Prevent profile area click
        logout();
    });
}

// Event handlers
fetchConfigBtn.addEventListener('click', function (e) {
    e.preventDefault();
    e.stopPropagation();
    fetchConfiguration().catch(error => {
        console.log('Manual fetch configuration failed: ' + error.message);
    });
});




// Relay connection event handlers
connectRelayBtn.addEventListener('click', function (e) {
    e.preventDefault();
    e.stopPropagation();
    connectToRelay().catch(error => {
        console.log('Relay connection failed: ' + error.message);
    });
});

disconnectRelayBtn.addEventListener('click', function (e) {
    e.preventDefault();
    e.stopPropagation();
    disconnectFromRelay();
});

restartRelayBtn.addEventListener('click', function (e) {
    e.preventDefault();
    e.stopPropagation();
    sendRestartCommand().catch(error => {
        log(`Restart command failed: ${error.message}`, 'ERROR');
    });
});

// ================================
// AUTH RULES MANAGEMENT FUNCTIONS
// ================================

// Global auth rules state
let currentAuthRules = [];
let editingAuthRule = null;

// DOM elements for auth rules
const authRulesSection = document.getElementById('authRulesSection');
const refreshAuthRulesBtn = document.getElementById('refreshAuthRulesBtn');
const authRulesTableContainer = document.getElementById('authRulesTableContainer');
const authRulesTableBody = document.getElementById('authRulesTableBody');
const authRuleFormContainer = document.getElementById('authRuleFormContainer');
const authRuleForm = document.getElementById('authRuleForm');
const authRuleFormTitle = document.getElementById('authRuleFormTitle');
const saveAuthRuleBtn = document.getElementById('saveAuthRuleBtn');
const cancelAuthRuleBtn = document.getElementById('cancelAuthRuleBtn');

// Show auth rules section after login
function showAuthRulesSection() {
    if (authRulesSection) {
        authRulesSection.style.display = 'block';
        updateAuthRulesStatus('ready');
        log('Auth rules section is now available', 'INFO');
    }
}

// Hide auth rules section on logout
function hideAuthRulesSection() {
    if (authRulesSection) {
        authRulesSection.style.display = 'none';

        // Add null checks for all elements
        if (authRulesTableContainer) {
            authRulesTableContainer.style.display = 'none';
        }
        if (authRuleFormContainer) {
            authRuleFormContainer.style.display = 'none';
        }

        currentAuthRules = [];
        editingAuthRule = null;
        log('Auth rules section hidden', 'INFO');
    }
}

// Update auth rules status indicator (removed - no status element)
function updateAuthRulesStatus(status) {
    // Status element removed - no-op
}

// Load auth rules from relay using admin API
async function loadAuthRules() {
    try {
        log('Loading auth rules via admin API...', 'INFO');
        updateAuthRulesStatus('loading');

        if (!isLoggedIn || !userPubkey) {
            throw new Error('Must be logged in to load auth rules');
        }

        if (!relayPool) {
            throw new Error('SimplePool connection not available');
        }

        // Create command array for getting all auth rules
        const command_array = ["auth_query", "all"];

        // Encrypt the command array directly using NIP-44
        const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
        if (!encrypted_content) {
            throw new Error('Failed to encrypt command array');
        }

        // Create single kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [["p", getRelayPubkey()]],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        log('Sending auth rules query to relay...', 'INFO');

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                console.log(`✅ Auth Rules Query Relay ${index} (${url}): Event published successfully`);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('INFO', `Auth rules query relay ${index} publish success`, 'PUBLISH');
                }
            } else {
                console.error(`❌ Auth Rules Query Relay ${index} (${url}): Publish failed:`, result.reason);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('ERROR', `Auth rules query relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
                }
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected auth rules query event. Details: ${errorDetails}`);
        }

        log('Auth rules query sent successfully - waiting for response...', 'INFO');
        updateAuthRulesStatus('loaded');

    } catch (error) {
        log(`Failed to load auth rules: ${error.message}`, 'ERROR');
        updateAuthRulesStatus('error');
        currentAuthRules = [];
        displayAuthRules(currentAuthRules);
    }
}

// Display auth rules in the table
function displayAuthRules(rules) {
    console.log('=== DISPLAY AUTH RULES DEBUG ===');
    console.log('authRulesTableBody element:', authRulesTableBody);
    console.log('Rules to display:', rules);
    console.log('Rules length:', rules ? rules.length : 'undefined');
    console.log('authRulesTableContainer display:', authRulesTableContainer ? authRulesTableContainer.style.display : 'element not found');

    if (!authRulesTableBody) {
        console.log('ERROR: authRulesTableBody element not found');
        return;
    }

    authRulesTableBody.innerHTML = '';
    console.log('Cleared existing table content');

    if (!rules || rules.length === 0) {
        console.log('No rules to display, showing empty message');
        const row = document.createElement('tr');
        row.innerHTML = `<td colspan="6" style="text-align: center; font-style: italic;">No auth rules configured</td>`;
        authRulesTableBody.appendChild(row);
        console.log('Added empty rules message row');
        return;
    }

    console.log(`Displaying ${rules.length} auth rules`);
    rules.forEach((rule, index) => {
        console.log(`Adding rule ${index + 1}:`, rule);
        const row = document.createElement('tr');

        // Convert hex pubkey to npub for display in pattern_value
        let displayPatternValue = rule.pattern_value || rule.rule_target || '-';
        let patternValueLink = displayPatternValue;
        try {
            if (rule.pattern_value && rule.pattern_value.length === 64 && /^[0-9a-fA-F]+$/.test(rule.pattern_value)) {
                const npub = window.NostrTools.nip19.npubEncode(rule.pattern_value);
                displayPatternValue = npub;
                patternValueLink = `<a href="https://njump.me/${npub}" target="_blank" class="npub-link">${npub}</a>`;
            }
        } catch (error) {
            console.log('Failed to encode pattern_value to npub:', error.message);
        }

        row.innerHTML = `
                    <td>${rule.rule_type}</td>
                    <td>${rule.pattern_type || rule.operation || '-'}</td>
                    <td style="font-family: 'Courier New', monospace; font-size: 12px; word-break: break-all; max-width: 200px;">${patternValueLink}</td>
                    <td>${rule.enabled !== false ? 'Active' : 'Inactive'}</td>
                    <td>
                        <div class="inline-buttons">
                            <button onclick="editAuthRule(${index})" style="margin: 2px; padding: 4px 8px; font-size: 12px;">EDIT</button>
                            <button onclick="deleteAuthRule(${index})" style="margin: 2px; padding: 4px 8px; font-size: 12px;">DELETE</button>
                        </div>
                    </td>
                `;
        authRulesTableBody.appendChild(row);
    });

    // Update status display
    console.log(`Total Rules: ${rules.length}, Active Rules: ${rules.filter(r => r.enabled !== false).length}`);

    console.log('=== END DISPLAY AUTH RULES DEBUG ===');
}

// Show auth rules table (automatically called when auth rules are loaded)
function showAuthRulesTable() {
    console.log('=== SHOW AUTH RULES TABLE DEBUG ===');
    console.log('authRulesTableContainer element:', authRulesTableContainer);
    console.log('Current display style:', authRulesTableContainer ? authRulesTableContainer.style.display : 'element not found');

    if (authRulesTableContainer) {
        authRulesTableContainer.style.display = 'block';
        console.log('Set authRulesTableContainer display to block');

        // If we already have cached auth rules, display them immediately
        if (currentAuthRules && currentAuthRules.length >= 0) {
            console.log('Displaying cached auth rules:', currentAuthRules.length, 'rules');
            displayAuthRules(currentAuthRules);
            updateAuthRulesStatus('loaded');
            log(`Auth rules table displayed with ${currentAuthRules.length} cached rules`, 'INFO');
        } else {
            // No cached rules, load from relay
            console.log('No cached auth rules, loading from relay...');
            loadAuthRules();
            log('Auth rules table displayed - loading from relay', 'INFO');
        }
    } else {
        console.log('ERROR: authRulesTableContainer element not found');
    }
    console.log('=== END SHOW AUTH RULES TABLE DEBUG ===');
}

// Show add auth rule form
function showAddAuthRuleForm() {
    if (authRuleFormContainer && authRuleFormTitle) {
        editingAuthRule = null;
        authRuleFormTitle.textContent = 'Add Auth Rule';
        authRuleForm.reset();
        authRuleFormContainer.style.display = 'block';
        log('Opened add auth rule form', 'INFO');
    }
}

// Show edit auth rule form
function editAuthRule(index) {
    if (index < 0 || index >= currentAuthRules.length) return;

    const rule = currentAuthRules[index];
    editingAuthRule = { ...rule, index: index };

    if (authRuleFormTitle && authRuleForm) {
        authRuleFormTitle.textContent = 'Edit Auth Rule';

        // Populate form fields
        document.getElementById('authRuleType').value = rule.rule_type || '';
        document.getElementById('authPatternType').value = rule.pattern_type || rule.operation || '';
        document.getElementById('authPatternValue').value = rule.pattern_value || rule.rule_target || '';
        document.getElementById('authRuleAction').value = rule.action || 'allow';
        document.getElementById('authRuleDescription').value = rule.description || '';

        authRuleFormContainer.style.display = 'block';
        log(`Editing auth rule: ${rule.rule_type} - ${rule.pattern_value || rule.rule_target}`, 'INFO');
    }
}

// Delete auth rule using Administrator API (inner events)
async function deleteAuthRule(index) {
    if (index < 0 || index >= currentAuthRules.length) return;

    const rule = currentAuthRules[index];
    const confirmMsg = `Delete auth rule: ${rule.rule_type} - ${rule.pattern_value || rule.rule_target}?`;

    if (!confirm(confirmMsg)) return;

    try {
        log(`Deleting auth rule: ${rule.rule_type} - ${rule.pattern_value || rule.rule_target}`, 'INFO');

        if (!isLoggedIn || !userPubkey) {
            throw new Error('Must be logged in to delete auth rules');
        }

        if (!relayPool) {
            throw new Error('SimplePool connection not available');
        }

        // Create command array for deleting auth rule
        // Format: ["system_command", "delete_auth_rule", rule_type, pattern_type, pattern_value]
        const rule_type = rule.rule_type;
        const pattern_type = rule.pattern_type || 'pubkey';
        const pattern_value = rule.pattern_value || rule.rule_target;

        const command_array = ["system_command", "delete_auth_rule", rule_type, pattern_type, pattern_value];

        // Encrypt the command array directly using NIP-44
        const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
        if (!encrypted_content) {
            throw new Error('Failed to encrypt command array');
        }

        // Create single kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [["p", getRelayPubkey()]],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        log('Sending delete auth rule command to relay...', 'INFO');

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                console.log(`✅ Delete Auth Rule Relay ${index} (${url}): Event published successfully`);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('INFO', `Delete auth rule relay ${index} publish success`, 'PUBLISH');
                }
            } else {
                console.error(`❌ Delete Auth Rule Relay ${index} (${url}): Publish failed:`, result.reason);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('ERROR', `Delete auth rule relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
                }
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected delete auth rule event. Details: ${errorDetails}`);
        }

        log('Delete auth rule command sent successfully - waiting for response...', 'INFO');

        // Remove from local array immediately for UI responsiveness
        currentAuthRules.splice(index, 1);
        displayAuthRules(currentAuthRules);

    } catch (error) {
        log(`Failed to delete auth rule: ${error.message}`, 'ERROR');
    }
}

// Hide auth rule form
function hideAuthRuleForm() {
    if (authRuleFormContainer) {
        authRuleFormContainer.style.display = 'none';
        editingAuthRule = null;
        log('Auth rule form hidden', 'INFO');
    }
}

// Validate auth rule form
function validateAuthRuleForm() {
    const ruleType = document.getElementById('authRuleType').value;
    const patternType = document.getElementById('authPatternType').value;
    const patternValue = document.getElementById('authPatternValue').value.trim();
    const action = document.getElementById('authRuleAction').value;

    if (!ruleType) {
        alert('Please select a rule type');
        return false;
    }

    if (!patternType) {
        alert('Please select a pattern type');
        return false;
    }

    if (!patternValue) {
        alert('Please enter a pattern value');
        return false;
    }

    if (!action) {
        alert('Please select an action');
        return false;
    }

    // Validate pubkey format for pubkey rules
    if ((ruleType === 'pubkey_whitelist' || ruleType === 'pubkey_blacklist') &&
        patternValue.length !== 64) {
        alert('Pubkey must be exactly 64 hex characters');
        return false;
    }

    // Validate hex format for pubkey rules
    if ((ruleType === 'pubkey_whitelist' || ruleType === 'pubkey_blacklist')) {
        const hexPattern = /^[0-9a-fA-F]+$/;
        if (!hexPattern.test(patternValue)) {
            alert('Pubkey must contain only hex characters (0-9, a-f, A-F)');
            return false;
        }
    }

    return true;
}

// Save auth rule (add or update)
async function saveAuthRule(event) {
    event.preventDefault();

    if (!validateAuthRuleForm()) return;

    try {
        const ruleData = {
            rule_type: document.getElementById('authRuleType').value,
            pattern_type: document.getElementById('authPatternType').value,
            pattern_value: document.getElementById('authPatternValue').value.trim(),
            action: document.getElementById('authRuleAction').value,
            description: document.getElementById('authRuleDescription').value.trim() || null,
            enabled: true
        };

        if (editingAuthRule) {
            log(`Updating auth rule: ${ruleData.rule_type} - ${ruleData.pattern_value}`, 'INFO');

            // TODO: Implement actual rule update via WebSocket kind 23456 event
            // For now, just update local array
            currentAuthRules[editingAuthRule.index] = { ...ruleData, id: editingAuthRule.id || Date.now() };

            log('Auth rule updated (placeholder implementation)', 'INFO');
        } else {
            log(`Adding new auth rule: ${ruleData.rule_type} - ${ruleData.pattern_value}`, 'INFO');

            // TODO: Implement actual rule creation via WebSocket kind 23456 event
            // For now, just add to local array
            currentAuthRules.push({ ...ruleData, id: Date.now() });

            log('Auth rule added (placeholder implementation)', 'INFO');
        }

        displayAuthRules(currentAuthRules);
        hideAuthRuleForm();

    } catch (error) {
        log(`Failed to save auth rule: ${error.message}`, 'ERROR');
    }
}

// Update existing logout and showMainInterface functions to handle auth rules and NIP-17 DMs
const originalLogout = logout;
logout = async function () {
    hideAuthRulesSection();
    // Clear DM inbox and outbox on logout
    if (dmInbox) {
        dmInbox.innerHTML = '<div class="log-entry">No messages received yet.</div>';
    }
    if (dmOutbox) {
        dmOutbox.value = '';
    }
    await originalLogout();
};

const originalShowMainInterface = showMainInterface;
showMainInterface = function () {
    originalShowMainInterface();
    // Removed showAuthRulesSection() call - visibility now handled by updateAdminSectionsVisibility()
};

// Auth rules event handlers
if (refreshAuthRulesBtn) {
    refreshAuthRulesBtn.addEventListener('click', function (e) {
        e.preventDefault();
        loadAuthRules();
    });
}

if (authRuleForm) {
    authRuleForm.addEventListener('submit', saveAuthRule);
}

if (cancelAuthRuleBtn) {
    cancelAuthRuleBtn.addEventListener('click', function (e) {
        e.preventDefault();
        hideAuthRuleForm();
    });
}

// ================================
// STREAMLINED AUTH RULE FUNCTIONS
// ================================

// Utility function to convert nsec to hex pubkey or npub to hex pubkey
function nsecToHex(input) {
    if (!input || input.trim().length === 0) {
        return null;
    }

    const trimmed = input.trim();

    // If it's already 64-char hex, return as-is
    if (/^[0-9a-fA-F]{64}$/.test(trimmed)) {
        return trimmed;
    }

    // If it starts with nsec1, try to decode
    if (trimmed.startsWith('nsec1')) {
        try {
            if (window.NostrTools && window.NostrTools.nip19 && window.NostrTools.nip19.decode) {
                const decoded = window.NostrTools.nip19.decode(trimmed);
                if (decoded.type === 'nsec') {
                    // Handle different versions of nostr-tools
                    if (typeof decoded.data === 'string') {
                        // v1 style - data is already hex
                        return decoded.data;
                    } else {
                        // v2 style - data is Uint8Array
                        const hexPubkey = Array.from(decoded.data)
                            .map(b => b.toString(16).padStart(2, '0'))
                            .join('');
                        return hexPubkey;
                    }
                }
            }
        } catch (error) {
            console.error('Failed to decode nsec:', error);
            return null;
        }
    }

    // If it starts with npub1, try to decode to hex
    if (trimmed.startsWith('npub1')) {
        try {
            if (window.NostrTools && window.NostrTools.nip19 && window.NostrTools.nip19.decode) {
                const decoded = window.NostrTools.nip19.decode(trimmed);
                if (decoded.type === 'npub') {
                    // Handle different versions of nostr-tools
                    if (typeof decoded.data === 'string') {
                        // v1 style - data is already hex
                        return decoded.data;
                    } else {
                        // v2 style - data is Uint8Array
                        const hexPubkey = Array.from(decoded.data)
                            .map(b => b.toString(16).padStart(2, '0'))
                            .join('');
                        return hexPubkey;
                    }
                }
            }
        } catch (error) {
            console.error('Failed to decode npub:', error);
            return null;
        }
    }

    return null; // Invalid format
}

// Add blacklist rule (updated to use combined input)
function addBlacklistRule() {
    const input = document.getElementById('authRulePubkey');

    if (!input) return;

    const inputValue = input.value.trim();
    if (!inputValue) {
        log('Please enter a pubkey or nsec', 'ERROR');
        return;
    }

    // Convert nsec or npub to hex if needed
    const hexPubkey = nsecToHex(inputValue);
    if (!hexPubkey) {
        log('Invalid pubkey format. Please enter nsec1..., npub1..., or 64-character hex', 'ERROR');
        return;
    }

    // Validate hex length
    if (hexPubkey.length !== 64) {
        log('Invalid pubkey length. Must be exactly 64 characters', 'ERROR');
        return;
    }

    log('Adding to blacklist...', 'INFO');

    // Create auth rule data
    const ruleData = {
        rule_type: 'pubkey_blacklist',
        pattern_type: 'Global',
        pattern_value: hexPubkey,
        action: 'deny'
    };

    // Add to WebSocket queue for processing
    addAuthRuleViaWebSocket(ruleData)
        .then(() => {
            log(`Pubkey ${hexPubkey.substring(0, 16)}... added to blacklist`, 'INFO');
            input.value = '';

            // Refresh auth rules display if visible
            if (authRulesTableContainer && authRulesTableContainer.style.display !== 'none') {
                loadAuthRules();
            }
        })
        .catch(error => {
            log(`Failed to add rule: ${error.message}`, 'ERROR');
        });
}

// Add whitelist rule (updated to use combined input)
function addWhitelistRule() {
    const input = document.getElementById('authRulePubkey');
    const warningDiv = document.getElementById('whitelistWarning');

    if (!input) return;

    const inputValue = input.value.trim();
    if (!inputValue) {
        log('Please enter a pubkey or nsec', 'ERROR');
        return;
    }

    // Convert nsec or npub to hex if needed
    const hexPubkey = nsecToHex(inputValue);
    if (!hexPubkey) {
        log('Invalid pubkey format. Please enter nsec1..., npub1..., or 64-character hex', 'ERROR');
        return;
    }

    // Validate hex length
    if (hexPubkey.length !== 64) {
        log('Invalid pubkey length. Must be exactly 64 characters', 'ERROR');
        return;
    }

    // Show whitelist warning
    if (warningDiv) {
        warningDiv.style.display = 'block';
    }

    log('Adding to whitelist...', 'INFO');

    // Create auth rule data
    const ruleData = {
        rule_type: 'pubkey_whitelist',
        pattern_type: 'Global',
        pattern_value: hexPubkey,
        action: 'allow'
    };

    // Add to WebSocket queue for processing
    addAuthRuleViaWebSocket(ruleData)
        .then(() => {
            log(`Pubkey ${hexPubkey.substring(0, 16)}... added to whitelist`, 'INFO');
            input.value = '';

            // Refresh auth rules display if visible
            if (authRulesTableContainer && authRulesTableContainer.style.display !== 'none') {
                loadAuthRules();
            }
        })
        .catch(error => {
            log(`Failed to add rule: ${error.message}`, 'ERROR');
        });
}

// Add auth rule via SimplePool (kind 23456 event) - FIXED to match working test pattern
async function addAuthRuleViaWebSocket(ruleData) {
    if (!isLoggedIn || !userPubkey) {
        throw new Error('Must be logged in to add auth rules');
    }

    if (!relayPool) {
        throw new Error('SimplePool connection not available');
    }

    try {
        log(`Adding auth rule: ${ruleData.rule_type} - ${ruleData.pattern_value.substring(0, 16)}...`, 'INFO');

        // Map client-side rule types to command array format (matching working tests)
        let commandRuleType, commandPatternType;

        switch (ruleData.rule_type) {
            case 'pubkey_blacklist':
                commandRuleType = 'blacklist';
                commandPatternType = 'pubkey';
                break;
            case 'pubkey_whitelist':
                commandRuleType = 'whitelist';
                commandPatternType = 'pubkey';
                break;
            case 'hash_blacklist':
                commandRuleType = 'blacklist';
                commandPatternType = 'hash';
                break;
            default:
                throw new Error(`Unknown rule type: ${ruleData.rule_type}`);
        }

        // Create command array in the same format as working tests
        // Format: ["blacklist", "pubkey", "abc123..."] or ["whitelist", "pubkey", "def456..."]
        const command_array = [commandRuleType, commandPatternType, ruleData.pattern_value];

        // Encrypt the command array directly using NIP-44
        const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
        if (!encrypted_content) {
            throw new Error('Failed to encrypt command array');
        }

        // Create single kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [["p", getRelayPubkey()]],
            content: encrypted_content
        };

        // DEBUG: Log the complete event structure being sent
        console.log('=== AUTH RULE EVENT DEBUG (Administrator API) ===');
        console.log('Original Rule Data:', ruleData);
        console.log('Command Array:', command_array);
        console.log('Encrypted Content:', encrypted_content.substring(0, 50) + '...');
        console.log('Auth Event (before signing):', JSON.stringify(authEvent, null, 2));
        console.log('=== END AUTH RULE EVENT DEBUG ===');

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                console.log(`✅ Add Auth Rule Relay ${index} (${url}): Event published successfully`);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('INFO', `Add auth rule relay ${index} publish success`, 'PUBLISH');
                }
            } else {
                console.error(`❌ Add Auth Rule Relay ${index} (${url}): Publish failed:`, result.reason);
                if (typeof logTestEvent === 'function') {
                    logTestEvent('ERROR', `Add auth rule relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
                }
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected add auth rule event. Details: ${errorDetails}`);
        }

        log('Auth rule added successfully', 'INFO');

    } catch (error) {
        log(`Failed to add auth rule: ${error.message}`, 'ERROR');
        throw error;
    }
}

// ================================
// TEST FUNCTIONS FOR ADMIN API
// ================================

// Test event logging function
function logTestEvent(direction, message, type = 'INFO') {
    const testLog = document.getElementById('test-event-log');
    if (!testLog) return;

    const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
    const logEntry = document.createElement('div');
    logEntry.className = 'log-entry';

    const directionColor = direction === 'SENT' ? '#007bff' : '#28a745';
    logEntry.innerHTML = `
                <span class="log-timestamp">${timestamp}</span>
                <span style="color: ${directionColor}; font-weight: bold;">[${direction}]</span>
                <span style="color: #666;">[${type}]</span>
                ${message}
            `;

    testLog.appendChild(logEntry);
    testLog.scrollTop = testLog.scrollHeight;
}

// Test: Get Auth Rules
async function testGetAuthRules() {
    if (!isLoggedIn || !userPubkey) {
        logTestEvent('ERROR', 'Must be logged in to test admin API', 'ERROR');
        return;
    }

    if (!relayPool) {
        logTestEvent('ERROR', 'SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        logTestEvent('INFO', 'Testing Get Auth Rules command...', 'TEST');

        // Create command array for getting auth rules
        const command_array = '["auth_query", "all"]';

        // Encrypt the command content using NIP-44
        const encrypted_content = await encryptForRelay(command_array);
        if (!encrypted_content) {
            throw new Error('Failed to encrypt auth query command');
        }

        // Create kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [
                ["p", getRelayPubkey()]
            ],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        logTestEvent('SENT', `Get Auth Rules event: ${JSON.stringify(signedEvent)}`, 'EVENT');

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                logTestEvent('INFO', `Test Add Blacklist relay ${index} publish success`, 'PUBLISH');
            } else {
                logTestEvent('ERROR', `Test Add Blacklist relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected test add blacklist event. Details: ${errorDetails}`);
        }

        logTestEvent('INFO', 'Get Auth Rules command sent successfully', 'SUCCESS');

    } catch (error) {
        logTestEvent('ERROR', `Get Auth Rules test failed: ${error.message}`, 'ERROR');
    }
}

// Test: Clear All Auth Rules
async function testClearAuthRules() {
    if (!isLoggedIn || !userPubkey) {
        logTestEvent('ERROR', 'Must be logged in to test admin API', 'ERROR');
        return;
    }

    if (!relayPool) {
        logTestEvent('ERROR', 'SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        logTestEvent('INFO', 'Testing Clear All Auth Rules command...', 'TEST');

        // Create command array for clearing auth rules
        const command_array = '["system_command", "clear_all_auth_rules"]';

        // Encrypt the command content using NIP-44
        const encrypted_content = await encryptForRelay(command_array);
        if (!encrypted_content) {
            throw new Error('Failed to encrypt clear auth rules command');
        }

        // Create kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [
                ["p", getRelayPubkey()]
            ],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        logTestEvent('SENT', `Clear Auth Rules event: ${JSON.stringify(signedEvent)}`, 'EVENT');

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                logTestEvent('INFO', `Test Add Whitelist relay ${index} publish success`, 'PUBLISH');
            } else {
                logTestEvent('ERROR', `Test Add Whitelist relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected test add whitelist event. Details: ${errorDetails}`);
        }

        logTestEvent('INFO', 'Clear Auth Rules command sent successfully', 'SUCCESS');

    } catch (error) {
        logTestEvent('ERROR', `Clear Auth Rules test failed: ${error.message}`, 'ERROR');
    }
}

// Test: Add Blacklist
async function testAddBlacklist() {
    const testPubkeyInput = document.getElementById('test-pubkey-input');
    let testPubkey = testPubkeyInput ? testPubkeyInput.value.trim() : '';

    // Use a default test pubkey if none provided
    if (!testPubkey) {
        testPubkey = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
        logTestEvent('INFO', `Using default test pubkey: ${testPubkey}`, 'INFO');
    }

    if (!isLoggedIn || !userPubkey) {
        logTestEvent('ERROR', 'Must be logged in to test admin API', 'ERROR');
        return;
    }

    if (!relayPool) {
        logTestEvent('ERROR', 'SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        logTestEvent('INFO', `Testing Add Blacklist for pubkey: ${testPubkey.substring(0, 16)}...`, 'TEST');

        // Create command array for adding blacklist rule
        const command_array = `["blacklist", "pubkey", "${testPubkey}"]`;

        // Encrypt the command content using NIP-44
        const encrypted_content = await encryptForRelay(command_array);
        if (!encrypted_content) {
            throw new Error('Failed to encrypt blacklist command');
        }

        // Create kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [
                ["p", getRelayPubkey()]
            ],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        logTestEvent('SENT', `Add Blacklist event: ${JSON.stringify(signedEvent)}`, 'EVENT');

        // Publish via SimplePool with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                logTestEvent('INFO', `Test Config Query relay ${index} publish success`, 'PUBLISH');
            } else {
                logTestEvent('ERROR', `Test Config Query relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected test config query event. Details: ${errorDetails}`);
        }

        logTestEvent('INFO', 'Add Blacklist command sent successfully', 'SUCCESS');

    } catch (error) {
        logTestEvent('ERROR', `Add Blacklist test failed: ${error.message}`, 'ERROR');
    }
}

// Test: Add Whitelist
async function testAddWhitelist() {
    const testPubkeyInput = document.getElementById('test-pubkey-input');
    let testPubkey = testPubkeyInput ? testPubkeyInput.value.trim() : '';

    // Use a default test pubkey if none provided
    if (!testPubkey) {
        testPubkey = 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890';
        logTestEvent('INFO', `Using default test pubkey: ${testPubkey}`, 'INFO');
    }

    if (!isLoggedIn || !userPubkey) {
        logTestEvent('ERROR', 'Must be logged in to test admin API', 'ERROR');
        return;
    }

    if (!relayPool) {
        logTestEvent('ERROR', 'SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        logTestEvent('INFO', `Testing Add Whitelist for pubkey: ${testPubkey.substring(0, 16)}...`, 'TEST');

        // Create command array for adding whitelist rule
        const command_array = `["whitelist", "pubkey", "${testPubkey}"]`;

        // Encrypt the command content using NIP-44
        const encrypted_content = await encryptForRelay(command_array);
        if (!encrypted_content) {
            throw new Error('Failed to encrypt whitelist command');
        }

        // Create kind 23456 admin event
        const authEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [
                ["p", getRelayPubkey()]
            ],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(authEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        logTestEvent('SENT', `Add Whitelist event: ${JSON.stringify(signedEvent)}`, 'EVENT');

        // Publish via SimplePool
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                logTestEvent('INFO', `Test Post Event relay ${index} publish success`, 'PUBLISH');
            } else {
                logTestEvent('ERROR', `Test Post Event relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected test post event. Details: ${errorDetails}`);
        }

        logTestEvent('INFO', 'Add Whitelist command sent successfully', 'SUCCESS');

    } catch (error) {
        logTestEvent('ERROR', `Add Whitelist test failed: ${error.message}`, 'ERROR');
    }
}

// Test: Config Query
async function testConfigQuery() {
    if (!isLoggedIn || !userPubkey) {
        logTestEvent('ERROR', 'Must be logged in to test admin API', 'ERROR');
        return;
    }

    if (!relayPool) {
        logTestEvent('ERROR', 'SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        logTestEvent('INFO', 'Testing Config Query command...', 'TEST');

        // Create command array for getting configuration
        const command_array = '["config_query", "all"]';

        // Encrypt the command content using NIP-44
        const encrypted_content = await encryptForRelay(command_array);
        if (!encrypted_content) {
            throw new Error('Failed to encrypt config query command');
        }

        // Create kind 23456 admin event
        const configEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [
                ["p", getRelayPubkey()]
            ],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(configEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        logTestEvent('SENT', `Config Query event: ${JSON.stringify(signedEvent)}`, 'EVENT');

        // Publish via SimplePool with detailed error diagnostics
        const url = relayUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                logTestEvent('INFO', `Test Config Query relay ${index} publish success`, 'PUBLISH');
            } else {
                logTestEvent('ERROR', `Test Config Query relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected test config query event. Details: ${errorDetails}`);
        }

        logTestEvent('INFO', 'Config Query command sent successfully', 'SUCCESS');

    } catch (error) {
        logTestEvent('ERROR', `Config Query test failed: ${error.message}`, 'ERROR');
    }
}

// Test: Post Basic Event
async function testPostEvent() {
    if (!isLoggedIn || !userPubkey) {
        logTestEvent('ERROR', 'Must be logged in to test event posting', 'ERROR');
        return;
    }

    if (!relayPool) {
        logTestEvent('ERROR', 'SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        logTestEvent('INFO', 'Testing basic event posting...', 'TEST');

        // Create a simple kind 1 text note event
        const testEvent = {
            kind: 1,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [
                ["t", "test"],
                ["client", "c-relay-admin-api"]
            ],
            content: `Test event from C-Relay Admin API at ${new Date().toISOString()}`
        };

        logTestEvent('SENT', `Test event (before signing): ${JSON.stringify(testEvent)}`, 'EVENT');

        // Sign the event using NIP-07
        const signedEvent = await window.nostr.signEvent(testEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        logTestEvent('SENT', `Signed test event: ${JSON.stringify(signedEvent)}`, 'EVENT');

        // Publish via SimplePool to the same relay with detailed error diagnostics
        const url = relayConnectionUrl.value.trim();
        logTestEvent('INFO', `Publishing to relay: ${url}`, 'INFO');

        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes instead of Promise.any
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results for diagnostics
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                logTestEvent('INFO', `Test Post Event relay ${index} publish success`, 'PUBLISH');
            } else {
                logTestEvent('ERROR', `Test Post Event relay ${index} publish failed: ${result.reason?.message || result.reason}`, 'PUBLISH');
            }
        });

        // Throw error if all relays failed
        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected test post event. Details: ${errorDetails}`);
        }

        logTestEvent('INFO', 'Test event published successfully!', 'SUCCESS');
        logTestEvent('INFO', 'Check if the event appears in the subscription above...', 'INFO');

    } catch (error) {
        logTestEvent('ERROR', `Post Event test failed: ${error.message}`, 'ERROR');
        console.error('Post Event test error:', error);
    }
}

// Helper function to encrypt content for relay using NIP-44
async function encryptForRelay(content) {
    try {
        logTestEvent('INFO', `Encrypting content: ${content}`, 'DEBUG');

        // Get the relay public key for encryption
        const relayPubkey = getRelayPubkey();

        // Check if we have access to NIP-44 encryption via nostr-tools
        if (!window.NostrTools || !window.NostrTools.nip44) {
            throw new Error('NIP-44 encryption not available - nostr-tools library missing');
        }

        // Get user's private key for encryption
        // We need to use the NIP-07 extension to get the private key
        if (!window.nostr || !window.nostr.nip44) {
            throw new Error('NIP-44 encryption not available via NIP-07 extension');
        }

        // Use NIP-07 extension's NIP-44 encrypt method
        const encrypted_content = await window.nostr.nip44.encrypt(relayPubkey, content);

        if (!encrypted_content) {
            throw new Error('NIP-44 encryption returned empty result');
        }

        logTestEvent('INFO', `Successfully encrypted content using NIP-44`, 'DEBUG');
        logTestEvent('INFO', `Encrypted content: ${encrypted_content.substring(0, 50)}...`, 'DEBUG');

        return encrypted_content;
    } catch (error) {
        logTestEvent('ERROR', `NIP-44 encryption failed: ${error.message}`, 'ERROR');

        // Fallback: Try using nostr-tools directly if NIP-07 fails
        try {
            logTestEvent('INFO', 'Attempting fallback encryption with nostr-tools...', 'DEBUG');

            if (!window.NostrTools || !window.NostrTools.nip44) {
                throw new Error('nostr-tools NIP-44 not available');
            }

            // We need the user's private key, but we can't get it directly
            // This is a security limitation - we should use NIP-07
            throw new Error('Cannot access private key for direct encryption - use NIP-07 extension');

        } catch (fallbackError) {
            logTestEvent('ERROR', `Fallback encryption failed: ${fallbackError.message}`, 'ERROR');
            return null;
        }
    }
}

// Send NIP-17 Direct Message to relay using NIP-59 layering
async function sendNIP17DM() {
    if (!isLoggedIn || !userPubkey) {
        log('Must be logged in to send DM', 'ERROR');
        return;
    }

    if (!isRelayConnected || !relayPubkey) {
        log('Must be connected to relay to send DM', 'ERROR');
        return;
    }

    const message = dmOutbox.value.trim();
    if (!message) {
        log('Please enter a message to send', 'ERROR');
        return;
    }

    // Capability checks
    if (!window.nostr || !window.nostr.nip44 || !window.nostr.signEvent) {
        log('NIP-17 DMs require a NIP-07 extension with NIP-44 support', 'ERROR');
        alert('NIP-17 DMs require a NIP-07 extension with NIP-44 support. Please install and configure a compatible extension.');
        return;
    }

    if (!window.NostrTools || !window.NostrTools.generateSecretKey || !window.NostrTools.getPublicKey || !window.NostrTools.finalizeEvent) {
        log('NostrTools library not available for ephemeral key operations', 'ERROR');
        alert('NostrTools library not available. Please ensure nostr.bundle.js is loaded.');
        return;
    }

    try {
        log(`Sending NIP-17 DM to relay: ${message.substring(0, 50)}...`, 'INFO');

        // Step 1: Build unsigned rumor (kind 14)
        const rumor = {
            kind: 14,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000), // Canonical time for rumor
            tags: [["p", relayPubkey]],
            content: message
        };
        // NOTE: Rumor remains unsigned per NIP-59

        log('Rumor built (unsigned), creating seal...', 'INFO');

        // Step 2: Create seal (kind 13)
        const seal = {
            kind: 13,
            pubkey: userPubkey,
            created_at: randomNow(), // Randomized to past for metadata protection
            tags: [], // Empty tags per NIP-59
            content: await window.nostr.nip44.encrypt(relayPubkey, JSON.stringify(rumor))
        };

        // Sign seal with long-term key
        const signedSeal = await window.nostr.signEvent(seal);
        if (!signedSeal || !signedSeal.sig) {
            throw new Error('Failed to sign seal event');
        }

        log('Seal created and signed, creating gift wrap...', 'INFO');

        // Step 3: Create gift wrap (kind 1059) with ephemeral key
        const ephemeralPriv = window.NostrTools.generateSecretKey();
        const ephemeralPub = window.NostrTools.getPublicKey(ephemeralPriv);

        const giftWrap = {
            kind: 1059,
            pubkey: ephemeralPub,
            created_at: randomNow(), // Randomized to past for metadata protection
            tags: [["p", relayPubkey]],
            content: await window.NostrTools.nip44.encrypt(
                JSON.stringify(signedSeal),
                window.NostrTools.nip44.getConversationKey(ephemeralPriv, relayPubkey)
            )
        };

        // Sign gift wrap with ephemeral key using finalizeEvent
        const signedGiftWrap = window.NostrTools.finalizeEvent(giftWrap, ephemeralPriv);
        if (!signedGiftWrap || !signedGiftWrap.sig) {
            throw new Error('Failed to sign gift wrap event');
        }

        log('NIP-17 DM event created and signed with ephemeral key, publishing...', 'INFO');

        // Publish via SimplePool
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedGiftWrap);

        // Use Promise.allSettled to capture per-relay outcomes
        const results = await Promise.allSettled(publishPromises);

        // Log detailed publish results
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                log(`✅ NIP-17 DM published successfully to relay ${index}`, 'INFO');
            } else {
                log(`❌ NIP-17 DM failed on relay ${index}: ${result.reason?.message || result.reason}`, 'ERROR');
            }
        });

        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected NIP-17 DM event. Details: ${errorDetails}`);
        }

        // Clear the outbox and show success
        dmOutbox.value = '';
        log('NIP-17 DM sent successfully', 'INFO');

        // Add to inbox for display
        addMessageToInbox('sent', message, new Date().toLocaleString());

    } catch (error) {
        log(`Failed to send NIP-17 DM: ${error.message}`, 'ERROR');
    }
}

// Add message to inbox display
function addMessageToInbox(direction, message, timestamp, pubkey = null) {
    if (!dmInbox) return;

    const messageDiv = document.createElement('div');
    messageDiv.className = 'log-entry';

    const directionColor = direction === 'sent' ? '#007bff' : '#28a745';

    // Convert newlines to <br> tags for proper HTML display
    const formattedMessage = message.replace(/\n/g, '<br>');

    // Add pubkey display for received messages
    let pubkeyDisplay = '';
    if (pubkey && direction === 'received') {
        try {
            const npub = window.NostrTools.nip19.npubEncode(pubkey);
            pubkeyDisplay = ` <span style="color: #666; font-size: 11px;">(${npub})</span>`;
        } catch (error) {
            console.error('Failed to encode pubkey to npub:', error);
        }
    }

    messageDiv.innerHTML = `
                <span class="log-timestamp">${timestamp}</span>
                <span style="color: ${directionColor}; font-weight: bold;">[${direction.toUpperCase()}]</span>
                <span style="white-space: pre-wrap;">${formattedMessage}${pubkeyDisplay}</span>
            `;

    // Remove the "No messages received yet" placeholder if it exists
    const placeholder = dmInbox.querySelector('.log-entry');
    if (placeholder && placeholder.textContent === 'No messages received yet.') {
        dmInbox.innerHTML = '';
    }

    // Add new message at the top
    dmInbox.insertBefore(messageDiv, dmInbox.firstChild);

    // Limit to last 50 messages
    while (dmInbox.children.length > 50) {
        dmInbox.removeChild(dmInbox.lastChild);
    }
}

// Helper function to get relay pubkey
function getRelayPubkey() {
    // Use the dynamically fetched relay pubkey if available
    if (relayPubkey && isRelayConnected) {
        return relayPubkey;
    }

    // Fallback to hardcoded value for testing/development
    log('Warning: Using hardcoded relay pubkey. Please connect to relay first.', 'WARNING');
    return '4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa';
}

// Enhanced SimplePool message handler to capture test responses
function enhancePoolForTesting() {
    // SimplePool handles message parsing automatically, so we just need to
    // ensure our event handlers log appropriately. This is already done
    // in the subscription onevent callback.
    console.log('SimplePool enhanced for testing - automatic message handling enabled');
}

// Generate random test pubkey function
function generateRandomTestKey() {
    // Generate 32 random bytes (64 hex characters) for a valid pubkey
    const randomBytes = new Uint8Array(32);
    crypto.getRandomValues(randomBytes);

    // Convert to hex string
    const hexPubkey = Array.from(randomBytes)
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');

    // Set the generated key in the input field
    const testPubkeyInput = document.getElementById('test-pubkey-input');
    if (testPubkeyInput) {
        testPubkeyInput.value = hexPubkey;
        logTestEvent('INFO', `Generated random test pubkey: ${hexPubkey.substring(0, 16)}...`, 'KEYGEN');
    }

    return hexPubkey;
}

// ================================
// DATABASE STATISTICS FUNCTIONS
// ================================

// Send restart command to restart the relay using Administrator API
async function sendRestartCommand() {
    if (!isLoggedIn || !userPubkey) {
        log('Must be logged in to restart relay', 'ERROR');
        return;
    }

    if (!relayPool) {
        log('SimplePool connection not available', 'ERROR');
        return;
    }

    try {
        log('Sending restart command to relay...', 'INFO');

        // Create command array for restart
        const command_array = ["system_command", "restart"];

        // Encrypt the command array directly using NIP-44
        const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
        if (!encrypted_content) {
            throw new Error('Failed to encrypt command array');
        }

        // Create single kind 23456 admin event
        const restartEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [["p", getRelayPubkey()]],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(restartEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        // Publish via SimplePool
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes
        const results = await Promise.allSettled(publishPromises);

        // Check if any relay accepted the event
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                log(`Restart command published successfully to relay ${index}`, 'INFO');
            } else {
                log(`Restart command failed on relay ${index}: ${result.reason?.message || result.reason}`, 'ERROR');
            }
        });

        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected restart command. Details: ${errorDetails}`);
        }

        log('Restart command sent successfully - relay should restart shortly...', 'INFO');

        // Update connection status to indicate restart is in progress
        updateRelayConnectionStatus('connecting');
        relayConnectionStatus.textContent = 'RESTARTING...';

        // The relay will disconnect and need to be reconnected after restart
        // This will be handled by the WebSocket disconnection event

    } catch (error) {
        log(`Failed to send restart command: ${error.message}`, 'ERROR');
        updateRelayConnectionStatus('error');
    }
}

// Send stats_query command to get database statistics using Administrator API (inner events)
async function sendStatsQuery() {
    if (!isLoggedIn || !userPubkey) {
        log('Must be logged in to query database statistics', 'ERROR');
        updateStatsStatus('error', 'Not logged in');
        return;
    }

    if (!relayPool) {
        log('SimplePool connection not available', 'ERROR');
        updateStatsStatus('error', 'No relay connection');
        return;
    }

    try {
        updateStatsStatus('loading', 'Querying database...');

        // Create command array for stats query
        const command_array = ["stats_query", "all"];

        // Encrypt the command array directly using NIP-44
        const encrypted_content = await encryptForRelay(JSON.stringify(command_array));
        if (!encrypted_content) {
            throw new Error('Failed to encrypt command array');
        }

        // Create single kind 23456 admin event
        const statsEvent = {
            kind: 23456,
            pubkey: userPubkey,
            created_at: Math.floor(Date.now() / 1000),
            tags: [["p", getRelayPubkey()]],
            content: encrypted_content
        };

        // Sign the event
        const signedEvent = await window.nostr.signEvent(statsEvent);
        if (!signedEvent || !signedEvent.sig) {
            throw new Error('Event signing failed');
        }

        log('Sending stats query command...', 'INFO');

        // Publish via SimplePool
        const url = relayConnectionUrl.value.trim();
        const publishPromises = relayPool.publish([url], signedEvent);

        // Use Promise.allSettled to capture per-relay outcomes
        const results = await Promise.allSettled(publishPromises);

        // Check if any relay accepted the event
        let successCount = 0;
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                successCount++;
                log(`Stats query published successfully to relay ${index}`, 'INFO');
            } else {
                log(`Stats query failed on relay ${index}: ${result.reason?.message || result.reason}`, 'ERROR');
            }
        });

        if (successCount === 0) {
            const errorDetails = results.map((r, i) => `Relay ${i}: ${r.reason?.message || r.reason}`).join('; ');
            throw new Error(`All relays rejected stats query event. Details: ${errorDetails}`);
        }

        log('Stats query command sent successfully - waiting for response...', 'INFO');
        updateStatsStatus('waiting', 'Waiting for response...');

    } catch (error) {
        log(`Failed to send stats query: ${error.message}`, 'ERROR');
        updateStatsStatus('error', error.message);
    }
}

// Handle stats_query response and populate tables
function handleStatsQueryResponse(responseData) {
    try {
        log('Processing stats query response...', 'INFO');
        console.log('Stats response data:', responseData);

        if (responseData.query_type !== 'stats_query') {
            log('Ignoring non-stats response', 'WARNING');
            return;
        }

        // Populate overview table
        populateStatsOverview(responseData);

        // Populate event kinds table
        populateStatsKinds(responseData);

        // Populate time-based statistics
        populateStatsTime(responseData);

        // Populate top pubkeys table
        populateStatsPubkeys(responseData);

        updateStatsStatus('loaded');
        log('Database statistics updated successfully', 'INFO');

    } catch (error) {
        log(`Error processing stats response: ${error.message}`, 'ERROR');
        updateStatsStatus('error', 'Failed to process response');
    }
}

// Populate database overview table
function populateStatsOverview(data) {
    if (!data) return;

    // Update individual cells with flash animation for changed values
    updateStatsCell('db-size', data.database_size_bytes ? formatFileSize(data.database_size_bytes) : '-');
    updateStatsCell('total-events', data.total_events || '-');
    updateStatsCell('oldest-event', data.database_created_at ? formatTimestamp(data.database_created_at) : '-');
    updateStatsCell('newest-event', data.latest_event_at ? formatTimestamp(data.latest_event_at) : '-');
}

// Populate event kinds distribution table
function populateStatsKinds(data) {
    const tableBody = document.getElementById('stats-kinds-table-body');
    if (!tableBody || !data.event_kinds) return;

    tableBody.innerHTML = '';

    if (data.event_kinds.length === 0) {
        const row = document.createElement('tr');
        row.innerHTML = '<td colspan="3" style="text-align: center; font-style: italic;">No event data</td>';
        tableBody.appendChild(row);
        return;
    }

    data.event_kinds.forEach(kind => {
        const row = document.createElement('tr');
        row.innerHTML = `
                    <td>${kind.kind}</td>
                    <td>${kind.count}</td>
                    <td>${kind.percentage}%</td>
                `;
        tableBody.appendChild(row);
    });
}

// Populate time-based statistics table
function populateStatsTime(data) {
    if (!data) return;

    // Access the nested time_stats object from backend response
    const timeStats = data.time_stats || {};

    // Update cells with flash animation for changed values
    updateStatsCell('events-24h', timeStats.last_24h || '0');
    updateStatsCell('events-7d', timeStats.last_7d || '0');
    updateStatsCell('events-30d', timeStats.last_30d || '0');
}

// Populate top pubkeys table
function populateStatsPubkeys(data) {
    const tableBody = document.getElementById('stats-pubkeys-table-body');
    if (!tableBody || !data.top_pubkeys) return;

    tableBody.innerHTML = '';

    if (data.top_pubkeys.length === 0) {
        const row = document.createElement('tr');
        row.innerHTML = '<td colspan="4" style="text-align: center; font-style: italic;">No pubkey data</td>';
        tableBody.appendChild(row);
        return;
    }

    data.top_pubkeys.forEach((pubkey, index) => {
        const row = document.createElement('tr');
        // Convert hex pubkey to npub for display
        let displayPubkey = pubkey.pubkey || '-';
        let npubLink = displayPubkey;
        try {
            if (pubkey.pubkey && pubkey.pubkey.length === 64 && /^[0-9a-fA-F]+$/.test(pubkey.pubkey)) {
                const npub = window.NostrTools.nip19.npubEncode(pubkey.pubkey);
                displayPubkey = npub;
                npubLink = `<a href="https://njump.me/${npub}" target="_blank" class="npub-link">${npub}</a>`;
            }
        } catch (error) {
            console.log('Failed to encode pubkey to npub:', error.message);
        }
        row.innerHTML = `
                    <td>${index + 1}</td>
                    <td style="font-family: 'Courier New', monospace; font-size: 12px; word-break: break-all;">${npubLink}</td>
                    <td>${pubkey.event_count}</td>
                    <td>${pubkey.percentage}%</td>
                `;
        tableBody.appendChild(row);
    });
}

// Update statistics status indicator (disabled - status display removed)
function updateStatsStatus(status, message = '') {
    // Status display has been removed from the UI
    return;
}

// Utility function to format file size
function formatFileSize(bytes) {
    if (!bytes || bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}

// Utility function to format timestamp
function formatTimestamp(timestamp) {
    if (!timestamp) return '-';
    const date = new Date(timestamp * 1000);
    return date.toLocaleString();
}

// Update statistics cell with flash animation if value changed
function updateStatsCell(cellId, newValue) {
    const cell = document.getElementById(cellId);
    if (!cell) return;

    const currentValue = cell.textContent;
    cell.textContent = newValue;

    // Flash if value changed
    if (currentValue !== newValue && currentValue !== '-') {
        cell.classList.add('flash-value');
        setTimeout(() => {
            cell.classList.remove('flash-value');
        }, 500);
    }
}

// Start auto-refreshing database statistics every 10 seconds
function startStatsAutoRefresh() {
    // Clear any existing interval
    stopStatsAutoRefresh();

    // Reset countdown
    countdownSeconds = 10;
    updateCountdownDisplay();

    // Start countdown interval - update every second
    countdownInterval = setInterval(() => {
        countdownSeconds--;
        updateCountdownDisplay();

        if (countdownSeconds <= 0) {
            // Time to refresh
            if (isLoggedIn && isRelayConnected) {
                log('Auto-refreshing database statistics...', 'INFO');
                sendStatsQuery().then(() => {
                    // Flash button red on successful refresh
                    flashRefreshButton();
                    // Reset countdown
                    countdownSeconds = 10;
                    updateCountdownDisplay();
                }).catch(error => {
                    log(`Auto-refresh failed: ${error.message}`, 'ERROR');
                    // Reset countdown even on failure
                    countdownSeconds = 10;
                    updateCountdownDisplay();
                });
            } else {
                // Reset countdown if not logged in/connected
                countdownSeconds = 10;
                updateCountdownDisplay();
            }
        }
    }, 1000); // Update every 1 second

    log('Database statistics auto-refresh started (10 second intervals)', 'INFO');
}

// Stop auto-refreshing database statistics
function stopStatsAutoRefresh() {
    if (statsAutoRefreshInterval) {
        clearInterval(statsAutoRefreshInterval);
        statsAutoRefreshInterval = null;
    }
    if (countdownInterval) {
        clearInterval(countdownInterval);
        countdownInterval = null;
    }
    // Reset countdown display
    updateCountdownDisplay();
    log('Database statistics auto-refresh stopped', 'INFO');
}

// Update countdown display in refresh button
function updateCountdownDisplay() {
    const refreshBtn = document.getElementById('refresh-stats-btn');
    if (!refreshBtn) return;

    if (countdownInterval && isLoggedIn && isRelayConnected) {
        // Japanese Kanji numbers: 〇 一 二 三 四 五 六 七 八 九 十
        const kanjiNumbers = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];

        // Show single character counting down from 十 (10) to 〇 (0)
        if (countdownSeconds >= 0 && countdownSeconds <= 10) {
            refreshBtn.textContent = kanjiNumbers[countdownSeconds];
        } else {
            refreshBtn.textContent = '';
        }
    } else {
        // Show empty when not active
        refreshBtn.textContent = '';
    }
}

// Flash refresh button red on successful refresh
function flashRefreshButton() {
    const refreshBtn = document.getElementById('refresh-stats-btn');
    if (!refreshBtn) return;

    // Add red flash class
    refreshBtn.classList.add('flash-red');

    // Remove flash class after animation
    setTimeout(() => {
        refreshBtn.classList.remove('flash-red');
    }, 500); // Match CSS animation duration
}

// Event handlers for test buttons
document.addEventListener('DOMContentLoaded', () => {
    // Test button event handlers
    const testGetAuthRulesBtn = document.getElementById('test-get-auth-rules-btn');
    const testClearAuthRulesBtn = document.getElementById('test-clear-auth-rules-btn');
    const testAddBlacklistBtn = document.getElementById('test-add-blacklist-btn');
    const testAddWhitelistBtn = document.getElementById('test-add-whitelist-btn');
    const testConfigQueryBtn = document.getElementById('test-config-query-btn');
    const testPostEventBtn = document.getElementById('test-post-event-btn');
    const clearTestLogBtn = document.getElementById('clear-test-log-btn');
    const generateTestKeyBtn = document.getElementById('generate-test-key-btn');

    if (testGetAuthRulesBtn) {
        testGetAuthRulesBtn.addEventListener('click', testGetAuthRules);
    }

    if (testClearAuthRulesBtn) {
        testClearAuthRulesBtn.addEventListener('click', testClearAuthRules);
    }

    if (testAddBlacklistBtn) {
        testAddBlacklistBtn.addEventListener('click', testAddBlacklist);
    }

    if (testAddWhitelistBtn) {
        testAddWhitelistBtn.addEventListener('click', testAddWhitelist);
    }

    if (testConfigQueryBtn) {
        testConfigQueryBtn.addEventListener('click', testConfigQuery);
    }

    if (testPostEventBtn) {
        testPostEventBtn.addEventListener('click', testPostEvent);
    }

    if (clearTestLogBtn) {
        clearTestLogBtn.addEventListener('click', () => {
            const testLog = document.getElementById('test-event-log');
            if (testLog) {
                testLog.innerHTML = '<div class="log-entry"><span class="log-timestamp">SYSTEM:</span> Test log cleared.</div>';
            }
        });
    }

    if (generateTestKeyBtn) {
        generateTestKeyBtn.addEventListener('click', generateRandomTestKey);
    }

    // Show test input section when needed
    const testInputSection = document.getElementById('test-input-section');
    if (testInputSection) {
        testInputSection.style.display = 'block';
    }

    // Database statistics event handlers
    const refreshStatsBtn = document.getElementById('refresh-stats-btn');
    if (refreshStatsBtn) {
        refreshStatsBtn.addEventListener('click', sendStatsQuery);
    }

    // NIP-17 DM event handlers
    if (sendDmBtn) {
        sendDmBtn.addEventListener('click', sendNIP17DM);
    }
});

// Set default relay URL based on where the page is being served from
function setDefaultRelayUrl() {
    const relayUrlInput = document.getElementById('relay-connection-url');
    if (!relayUrlInput) return;

    // Get the current page's protocol and hostname
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const hostname = window.location.hostname;
    const port = window.location.port;

    // Construct the relay URL
    let relayUrl;
    if (hostname === 'localhost' || hostname === '127.0.0.1') {
        // For localhost, default to ws://localhost:8888
        relayUrl = 'ws://localhost:8888';
    } else {
        // For production, use the same hostname with WebSocket protocol
        // Remove port from URL since relay typically runs on standard ports (80/443)
        relayUrl = `${protocol}//${hostname}`;
    }

    relayUrlInput.value = relayUrl;
    log(`Default relay URL set to: ${relayUrl}`, 'INFO');
}

// Initialize the app
document.addEventListener('DOMContentLoaded', () => {
    console.log('C-Relay Admin API interface loaded');

    // Set default relay URL based on current page location
    setDefaultRelayUrl();

    // Ensure admin sections are hidden by default on page load
    updateAdminSectionsVisibility();

    setTimeout(() => {
        initializeApp();
        // Enhance SimplePool for testing after initialization
        setTimeout(enhancePoolForTesting, 2000);
    }, 100);
});