/**
 * Shadow Spot - Renderer Application Logic
 */

// IMMEDIATELY prevent default drag behavior before anything else loads
// This MUST run as early as possible to override Electron's native drag handling
document.ondragover = document.ondrop = function (e) {
    e.preventDefault();
    return false;
};

// State
let selectedLocationId = null;
let isConnected = false;
let isConnecting = false;
let isSwitching = false;
let deleteTargetId = null;

// Session tracking
let sessionStartTime = null;
let sessionTimerInterval = null;
let totalDownloadBytes = 0;
let totalUploadBytes = 0;

// Ping tracking
let pingInterval = null;

// Sparkline data (last 30 speed readings)
let sparklineData = [];
const SPARKLINE_MAX_POINTS = 30;

// DOM Elements
const locationsList = document.getElementById('locationsList');
const emptyState = document.getElementById('emptyState');
const connectBtn = document.getElementById('connectBtn');
const connectText = connectBtn.querySelector('.connect-text');
const ipAddress = document.getElementById('ipAddress');
const downloadSpeed = document.getElementById('downloadSpeed');
const uploadSpeed = document.getElementById('uploadSpeed');
const logContainer = document.getElementById('logContainer');
const minimizeBtn = document.getElementById('minimizeBtn');
const closeBtn = document.getElementById('closeBtn');
const addBtn = document.getElementById('addBtn');

// Settings Elements
const settingsBtn = document.getElementById('settingsBtn');
const settingsMenu = document.getElementById('settingsMenu');
const themeDark = document.getElementById('themeDark');
const themeLight = document.getElementById('themeLight');

// Status elements
const pingValue = document.getElementById('pingValue');
const sessionTime = document.getElementById('sessionTime');
const totalDownload = document.getElementById('totalDownload');
const totalUpload = document.getElementById('totalUpload');
const sparklineCanvas = document.getElementById('sparkline');
const sparklineCtx = sparklineCanvas ? sparklineCanvas.getContext('2d') : null;

// Import dialog elements
const importOverlay = document.getElementById('importOverlay');
const importInput = document.getElementById('importInput');
const importError = document.getElementById('importError');
const importSubmit = document.getElementById('importSubmit');
const importCancel = document.getElementById('importCancel');

// Delete dialog elements
const deleteOverlay = document.getElementById('deleteOverlay');
const deleteTitle = document.getElementById('deleteTitle');
const deleteMessage = document.getElementById('deleteMessage');
const deleteConfirm = document.getElementById('deleteConfirm');
const deleteCancel = document.getElementById('deleteCancel');

// ============ Utility Functions ============

function formatSpeed(bytesPerSecond) {
    if (bytesPerSecond < 1024) {
        return `${bytesPerSecond} B/s`;
    } else if (bytesPerSecond < 1024 * 1024) {
        return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`;
    } else {
        return `${(bytesPerSecond / (1024 * 1024)).toFixed(2)} MB/s`;
    }
}

function formatBytes(bytes) {
    if (bytes < 1024) {
        return `${bytes} B`;
    } else if (bytes < 1024 * 1024) {
        return `${(bytes / 1024).toFixed(1)} KB`;
    } else if (bytes < 1024 * 1024 * 1024) {
        return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
    } else {
        return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
    }
}

function formatTime(seconds) {
    const h = Math.floor(seconds / 3600);
    const m = Math.floor((seconds % 3600) / 60);
    const s = seconds % 60;
    return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
}

// ============ Session Timer ============

function startSessionTimer() {
    sessionStartTime = Date.now();
    totalDownloadBytes = 0;
    totalUploadBytes = 0;
    sparklineData = [];

    sessionTimerInterval = setInterval(() => {
        if (sessionStartTime && sessionTime) {
            const elapsed = Math.floor((Date.now() - sessionStartTime) / 1000);
            sessionTime.textContent = formatTime(elapsed);
        }
    }, 1000);
}

function stopSessionTimer() {
    if (sessionTimerInterval) {
        clearInterval(sessionTimerInterval);
        sessionTimerInterval = null;
    }
    sessionStartTime = null;
    if (sessionTime) sessionTime.textContent = '00:00:00';
}

// ============ Ping Functions ============

function startPingMonitor() {
    stopPingMonitor();
    updatePing();
    pingInterval = setInterval(updatePing, 5000);
}

function stopPingMonitor() {
    if (pingInterval) {
        clearInterval(pingInterval);
        pingInterval = null;
    }
    if (pingValue) {
        pingValue.textContent = '—';
        pingValue.className = 'status-value ping-value';
    }
}

async function updatePing() {
    if (!isConnected) return;

    const result = await window.shadowspot.ping();

    if (pingValue) {
        if (result.success && result.time !== null) {
            pingValue.textContent = `${result.time}ms`;
            pingValue.className = 'status-value ping-value';
            if (result.time < 350) {
                pingValue.classList.add('ping-good');
            } else if (result.time < 700) {
                pingValue.classList.add('ping-medium');
            } else if (result.time < 1000) {
                pingValue.classList.add('ping-bad');
            } else {
                pingValue.textContent = 'timeout';
                pingValue.classList.add('ping-timeout');
            }
        } else {
            pingValue.textContent = 'timeout';
            pingValue.className = 'status-value ping-value ping-timeout';
        }
    }
}

// ============ Sparkline ============

function drawSparkline(downloadSpeed) {
    if (!sparklineCtx || !sparklineCanvas) return;

    sparklineData.push(downloadSpeed);
    if (sparklineData.length > SPARKLINE_MAX_POINTS) {
        sparklineData.shift();
    }

    const width = sparklineCanvas.width;
    const height = sparklineCanvas.height;
    const padding = 2;

    sparklineCtx.clearRect(0, 0, width, height);

    if (sparklineData.length < 2) return;

    const maxVal = Math.max(...sparklineData, 1);

    sparklineCtx.beginPath();
    sparklineCtx.strokeStyle = '#00d4ff';
    sparklineCtx.lineWidth = 1.5;
    sparklineCtx.lineJoin = 'round';

    const stepX = (width - padding * 2) / (SPARKLINE_MAX_POINTS - 1);

    sparklineData.forEach((val, i) => {
        const x = padding + i * stepX;
        const y = height - padding - ((val / maxVal) * (height - padding * 2));

        if (i === 0) {
            sparklineCtx.moveTo(x, y);
        } else {
            sparklineCtx.lineTo(x, y);
        }
    });

    sparklineCtx.stroke();
}

// ============ Log Functions ============

function addLog(message, type = 'default') {
    const entry = document.createElement('div');
    entry.className = `log-entry ${type}`;

    const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;

    const cleanMessage = message
        .replace(ansiRegex, '')
        .replace(/\[\d+\]/g, '')
        .replace(/\d+ms/g, '')
        .trim();

    if (cleanMessage.length > 0) {
        const time = new Date().toLocaleTimeString();
        entry.textContent = `[${time}] ${cleanMessage}`;
        logContainer.appendChild(entry);
        logContainer.scrollTop = logContainer.scrollHeight;

        while (logContainer.children.length > 50) {
            logContainer.removeChild(logContainer.firstChild);
        }
    }
}

function clearLogs() {
    logContainer.innerHTML = '';
    addLog('Ready to connect', 'info');
}

// ============ Render Locations (iOS-style cards) ============

async function renderLocations() {
    const locations = await window.shadowspot.getLocations();

    // Clear all location items but keep empty state
    const existingItems = locationsList.querySelectorAll('.location-item');
    existingItems.forEach(item => item.remove());

    if (locations.length === 0) {
        emptyState.style.display = 'flex';
        connectBtn.disabled = true;
        return;
    }

    emptyState.style.display = 'none';

    locations.forEach(loc => {
        const item = document.createElement('div');
        item.className = 'location-item';
        item.dataset.id = loc.id;

        if (selectedLocationId === loc.id) {
            item.classList.add('selected');
        }

        // iOS-style card: name, address:port, protocol
        const securityLabel = (loc.security || 'none').toUpperCase();
        const typeLabel = (loc.type || 'tcp').toUpperCase();

        item.innerHTML = `
            <div class="location-info">
                <div class="location-name">${escapeHtml(loc.name || 'Unknown Server')}</div>
                <div class="location-address">${escapeHtml(loc.address)}:${loc.port}</div>
                <div class="location-protocol">${securityLabel} / ${typeLabel}</div>
            </div>
            <div class="location-actions">
                <button class="delete-btn" data-id="${loc.id}" title="Delete">
                    <span class="icon-trash"></span>
                </button>
            </div>
        `;

        // Click on card to select
        item.addEventListener('click', (e) => {
            // Don't select if clicking delete button
            if (e.target.closest('.delete-btn')) return;
            selectLocation(loc.id);
        });

        // Delete button handler
        const deleteBtn = item.querySelector('.delete-btn');
        deleteBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            showDeleteDialog(loc.id, loc.name || loc.address);
        });

        locationsList.appendChild(item);
    });

    // Select first location by default if nothing is selected
    if (!selectedLocationId && locations.length > 0) {
        selectLocation(locations[0].id);
    } else if (selectedLocationId) {
        // Check if selected location still exists
        const exists = locations.some(loc => loc.id === selectedLocationId);
        if (!exists && locations.length > 0) {
            selectLocation(locations[0].id);
        } else if (!exists) {
            selectedLocationId = null;
            connectBtn.disabled = true;
        } else {
            // Location exists and is selected — enable Connect button
            connectBtn.disabled = false;
        }
    }
}

function escapeHtml(str) {
    const div = document.createElement('div');
    div.textContent = str;
    return div.innerHTML;
}

// ============ Select Location ============

async function selectLocation(locationId) {
    const previousLocationId = selectedLocationId;
    selectedLocationId = locationId;
    localStorage.setItem('lastLocationId', locationId);

    document.querySelectorAll('.location-item').forEach(item => {
        item.classList.remove('selected');
        if (item.dataset.id === locationId) {
            item.classList.add('selected');
        }
    });

    connectBtn.disabled = false;

    // Auto-reconnect if connected and location changed
    if (isConnected && previousLocationId && previousLocationId !== locationId) {
        isSwitching = true;
        isConnecting = true;
        connectBtn.classList.add('connecting');
        connectText.textContent = 'Switching...';
        addLog('Switching location...', 'info');

        await window.shadowspot.disconnect();
        await new Promise(resolve => setTimeout(resolve, 500));

        const result = await window.shadowspot.connect(locationId);

        isSwitching = false;

        if (result.success) {
            fetchPublicIP();
        } else {
            addLog(`Connection Error: ${result.error}`, 'error');
            updateConnectionStatus(false);
        }
    }
}

// ============ Connection Status ============

function updateConnectionStatus(connected, location = null) {
    // The same transition can arrive twice (direct call + status event), so
    // gate the side-effects (timers, ping, log) on an actual state change.
    const stateChanged = (isConnected !== connected);
    isConnected = connected;
    isConnecting = false;

    if (connected) {
        connectBtn.classList.add('connected');
        connectBtn.classList.remove('connecting');
        connectText.textContent = 'Disconnect';

        document.querySelectorAll('.location-item').forEach(item => {
            item.classList.remove('connected');
            if (location && item.dataset.id === location.id) {
                item.classList.add('connected');
            }
        });

        if (stateChanged) {
            startSessionTimer();
            startPingMonitor();
            addLog(`Connected: ${location?.name || location?.address}`, 'success');
        }
    } else {
        connectBtn.classList.remove('connected', 'connecting');
        connectText.textContent = 'Connect';
        ipAddress.textContent = '—';
        downloadSpeed.textContent = '0 B/s';
        uploadSpeed.textContent = '0 B/s';

        if (totalDownload) totalDownload.textContent = '0 B';
        if (totalUpload) totalUpload.textContent = '0 B';

        document.querySelectorAll('.location-item').forEach(item => {
            item.classList.remove('connected');
        });

        if (stateChanged) {
            stopSessionTimer();
            stopPingMonitor();
            addLog('Disconnected', 'info');
        }
    }
}

// ============ Connect / Disconnect ============

async function handleConnect() {
    if (isConnecting) return;

    if (isConnected) {
        isConnecting = true;
        connectBtn.classList.add('connecting');
        connectText.textContent = 'Connecting...';

        const result = await window.shadowspot.disconnect();
        if (result.success) {
            updateConnectionStatus(false);
        } else {
            addLog(`Error: ${result.error}`, 'error');
            isConnecting = false;
            connectBtn.classList.remove('connecting');
        }
    } else {
        if (!selectedLocationId) return;

        isConnecting = true;
        connectBtn.classList.add('connecting');
        connectText.textContent = 'Connecting...';
        clearLogs();
        addLog('Connecting...', 'info');

        const result = await window.shadowspot.connect(selectedLocationId);
        if (result.success) {
            fetchPublicIP();
        } else {
            addLog(`Connection Error: ${result.error}`, 'error');
            updateConnectionStatus(false);
        }
    }
}

// ============ IP Detection ============

let ipFetchInterval = null;
let ipAttempts = 0;
const IP_MAX_ATTEMPTS = 6;

// Endpoints are tried in order; whichever responds first wins. Each host must
// also be whitelisted in the connect-src CSP in index.html.
const IP_ENDPOINTS = [
    { url: 'https://api.ipify.org?format=json', pick: (d) => d.ip },
    { url: 'https://ipinfo.io/json', pick: (d) => d.ip },
];

function stopIpFetch() {
    if (ipFetchInterval) {
        clearInterval(ipFetchInterval);
        ipFetchInterval = null;
    }
}

async function fetchPublicIP() {
    stopIpFetch();
    ipAttempts = 0;

    async function tryFetch() {
        if (!isConnected) {
            stopIpFetch();
            return;
        }

        ipAttempts++;
        ipAddress.textContent = 'Detecting...';

        for (const ep of IP_ENDPOINTS) {
            try {
                const response = await fetch(ep.url, { cache: 'no-store' });
                if (response.ok) {
                    const data = await response.json();
                    const ip = ep.pick(data);
                    if (ip) {
                        ipAddress.textContent = ip;
                        stopIpFetch();
                        return;
                    }
                }
            } catch (error) {
                // Try the next endpoint.
            }
        }

        // Give up gracefully instead of spinning on "Detecting..." forever.
        if (ipAttempts >= IP_MAX_ATTEMPTS) {
            ipAddress.textContent = 'Unavailable';
            stopIpFetch();
        }
    }

    await tryFetch();

    if (ipAddress.textContent === 'Detecting...' && isConnected) {
        ipFetchInterval = setInterval(tryFetch, 3000);
    }
}

// ============ Import Dialog ============

function openImportDialog() {
    importInput.value = '';
    importError.textContent = '';
    importError.style.display = 'none';
    importOverlay.classList.add('show');
    // Focus the input after animation
    setTimeout(() => importInput.focus(), 200);
}

function closeImportDialog() {
    importOverlay.classList.remove('show');
}

async function handleImport() {
    const url = importInput.value.trim();
    if (!url) return;

    // Support multiple links (one per line)
    const lines = url.split('\n').map(l => l.trim()).filter(l => l.length > 0);
    let imported = 0;
    let lastError = '';

    for (const line of lines) {
        const result = await window.shadowspot.addLocation(line);
        if (result.success) {
            imported++;
        } else {
            lastError = result.error;
        }
    }

    if (imported > 0) {
        closeImportDialog();
        await renderLocations();
        addLog(`Imported ${imported} server${imported > 1 ? 's' : ''}`, 'success');
    } else {
        importError.textContent = lastError || 'No valid VLESS links found';
        importError.style.display = 'block';
    }
}

// ============ Delete Dialog ============

function showDeleteDialog(locationId, locationName) {
    deleteTargetId = locationId;
    deleteMessage.textContent = `Delete "${locationName}"?`;
    deleteOverlay.classList.add('show');
    document.addEventListener('keydown', handleDeleteKeyboard);
}

function closeDeleteDialog() {
    deleteOverlay.classList.remove('show');
    deleteTargetId = null;
    document.removeEventListener('keydown', handleDeleteKeyboard);
}

function handleDeleteKeyboard(e) {
    if (e.key === 'Enter') {
        e.preventDefault();
        handleDelete();
    } else if (e.key === 'Escape') {
        e.preventDefault();
        closeDeleteDialog();
    }
}

async function handleDelete() {
    if (!deleteTargetId) return;

    const idToDelete = deleteTargetId;

    // If connected to this location, disconnect first
    if (isConnected && selectedLocationId === idToDelete) {
        await window.shadowspot.disconnect();
        updateConnectionStatus(false);
    }

    const result = await window.shadowspot.removeLocation(idToDelete);
    closeDeleteDialog();

    if (result.success) {
        // If we deleted the selected location, reset
        if (selectedLocationId === idToDelete) {
            selectedLocationId = null;
        }
        await renderLocations();
        addLog('Server removed', 'info');
    } else {
        addLog(`Delete error: ${result.error}`, 'error');
    }
}

// ============ QR Code Import (File Pick + Drag and Drop) ============

async function processQrFile(file) {
    if (!file) return false;

    // file.path is Electron-specific — gives the OS file path
    const filePath = file.path || file.name;

    if (!file.type.startsWith('image/') && !filePath.match(/\.(png|jpg|jpeg|gif|bmp|webp)$/i)) {
        addLog(`Skipped "${file.name}" — not an image`, 'error');
        return false;
    }

    addLog(`Decoding QR from "${file.name}"...`, 'info');

    const result = await window.shadowspot.decodeQr(filePath);

    if (result.success && result.data) {
        if (result.data.startsWith('vless://')) {
            const addResult = await window.shadowspot.addLocation(result.data);
            if (addResult.success) {
                addLog(`Imported server from QR: ${addResult.location.name}`, 'success');
                return true;
            } else {
                addLog(`QR import: ${addResult.error}`, 'error');
            }
        } else {
            addLog('QR code does not contain a VLESS link', 'error');
        }
    } else {
        addLog(result.error || 'No QR code found in image', 'error');
    }
    return false;
}

// File picker fallback for QR import
function handleQrFilePick() {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    input.multiple = true;
    input.style.display = 'none';
    document.body.appendChild(input);

    input.addEventListener('change', async () => {
        let importedCount = 0;
        for (const file of input.files) {
            const success = await processQrFile(file);
            if (success) importedCount++;
        }
        if (importedCount > 0) {
            await renderLocations();
        }
        document.body.removeChild(input);
    });

    input.click();
}

function setupDragAndDrop() {
    const dropTarget = locationsList;

    // Override document-level drag handlers to allow drops
    document.ondragover = function (e) {
        e.preventDefault();
        // Visual feedback on locations list
        const rect = dropTarget.getBoundingClientRect();
        const inside = e.clientX >= rect.left && e.clientX <= rect.right &&
            e.clientY >= rect.top && e.clientY <= rect.bottom;
        dropTarget.classList.toggle('drag-over', inside);
        return false;
    };

    document.ondragenter = function (e) {
        e.preventDefault();
        return false;
    };

    document.ondragleave = function (e) {
        if (e.clientX <= 0 || e.clientY <= 0 ||
            e.clientX >= window.innerWidth || e.clientY >= window.innerHeight) {
            dropTarget.classList.remove('drag-over');
        }
    };

    document.ondrop = async function (e) {
        e.preventDefault();
        dropTarget.classList.remove('drag-over');

        const files = e.dataTransfer.files;
        if (!files || files.length === 0) return false;

        let importedCount = 0;
        for (const file of files) {
            const success = await processQrFile(file);
            if (success) importedCount++;
        }
        if (importedCount > 0) {
            await renderLocations();
        }
        return false;
    };
}

// ============ Event Listeners ============

connectBtn.addEventListener('click', (e) => {
    connectBtn.blur();
    handleConnect();
});
minimizeBtn.addEventListener('click', () => window.shadowspot.minimize());
closeBtn.addEventListener('click', () => window.shadowspot.close());

// Add button
addBtn.addEventListener('click', () => openImportDialog());

// Import dialog buttons
importSubmit.addEventListener('click', handleImport);
importCancel.addEventListener('click', closeImportDialog);

// Browse QR button inside import dialog
const importBrowseQr = document.getElementById('importBrowseQr');
importBrowseQr.addEventListener('click', () => {
    closeImportDialog();
    handleQrFilePick();
});

// Import on Enter key (Ctrl+Enter for multi-line)
importInput.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
        // If single line, import on Enter
        const lines = importInput.value.trim().split('\n');
        if (lines.length <= 1) {
            e.preventDefault();
            handleImport();
        }
    }
});

// Close import dialog on overlay click
importOverlay.addEventListener('click', (e) => {
    if (e.target === importOverlay) {
        closeImportDialog();
    }
});

// Delete dialog buttons
deleteConfirm.addEventListener('click', handleDelete);
deleteCancel.addEventListener('click', closeDeleteDialog);

// Close delete dialog on overlay click
deleteOverlay.addEventListener('click', (e) => {
    if (e.target === deleteOverlay) {
        closeDeleteDialog();
    }
});

// ============ Traffic Updates ============

window.shadowspot.onTrafficUpdate((traffic) => {
    if (traffic.up === undefined || traffic.down === undefined) return;

    const downSpeed = Math.max(0, traffic.down);
    const upSpeed = Math.max(0, traffic.up);

    downloadSpeed.textContent = formatSpeed(downSpeed);
    uploadSpeed.textContent = formatSpeed(upSpeed);

    // Totals come straight from the core's cumulative counters — exact,
    // no drift from summing per-tick speeds.
    if (typeof traffic.downTotal === 'number') {
        totalDownloadBytes = traffic.downTotal;
        if (totalDownload) totalDownload.textContent = formatBytes(totalDownloadBytes);
    }
    if (typeof traffic.upTotal === 'number') {
        totalUploadBytes = traffic.upTotal;
        if (totalUpload) totalUpload.textContent = formatBytes(totalUploadBytes);
    }

    drawSparkline(downSpeed);
});

// Log updates
let lastTcpHintTime = 0;
const TCP_HINT_COOLDOWN = 30000; // 30 seconds between hints

window.shadowspot.onLogUpdate((message) => {
    let type = 'default';
    if (message.includes('ERROR')) {
        type = 'error';
    } else if (message.includes('INFO')) {
        type = 'info';
    }

    const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;

    const cleanMessage = message
        .replace(ansiRegex, '')
        .replace(/\[\d+\]/g, '')
        .replace(/\d+ms/g, '')
        .trim();

    addLog(cleanMessage, type);

    // Detect TCP network errors and show a friendly hint
    if (type === 'error') {
        const tcpErrorPatterns = [
            'i/o timeout',
            'forcibly closed',
            'connection was aborted',
            'connection reset',
            'broken pipe',
            'connection refused'
        ];
        const isNetworkError = tcpErrorPatterns.some(p => cleanMessage.toLowerCase().includes(p));

        if (isNetworkError) {
            const now = Date.now();
            if (now - lastTcpHintTime > TCP_HINT_COOLDOWN) {
                lastTcpHintTime = now;
                addLog('A TCP error was detected on one of the network nodes. If this prevents a stable connection, try switching to a different location from the list above.', 'hint');
            }
        }
    }
});

// Status updates
window.shadowspot.onStatusUpdate((status) => {
    if (isSwitching && !status.isConnected) return;
    updateConnectionStatus(status.isConnected, status.location);
});

// Locations changed (from main process)
window.shadowspot.onLocationsChanged(() => {
    renderLocations();
});

// Tray menu toggle — same behavior as clicking the Connect/Disconnect button
window.shadowspot.onTrayToggle(() => {
    handleConnect();
});

// ============ Modal System (Admin + Exit) ============

const modalOverlay = document.getElementById('modalOverlay');
const modalIcon = document.getElementById('modalIcon');
const modalTitle = document.getElementById('modalTitle');
const modalMessage = document.getElementById('modalMessage');
const modalBtnPrimary = document.getElementById('modalBtnPrimary');
const modalBtnSecondary = document.getElementById('modalBtnSecondary');

let currentModalType = null;

function showModal(options) {
    currentModalType = options.type;
    modalIcon.textContent = options.icon || '⚠️';
    modalTitle.textContent = options.title;
    modalMessage.textContent = options.message;
    modalBtnPrimary.textContent = options.primaryBtn || 'OK';

    if (options.secondaryBtn) {
        modalBtnSecondary.textContent = options.secondaryBtn;
        modalBtnSecondary.style.display = 'block';
    } else {
        modalBtnSecondary.style.display = 'none';
    }

    modalOverlay.classList.add('show');
    document.addEventListener('keydown', handleModalKeyboard);
}

function hideModal() {
    modalOverlay.classList.remove('show');
    currentModalType = null;
    document.removeEventListener('keydown', handleModalKeyboard);
}

function handleModalKeyboard(e) {
    if (e.key === 'Enter') {
        e.preventDefault();
        modalBtnPrimary.click();
    } else if (e.key === 'Escape' && modalBtnSecondary.style.display !== 'none') {
        e.preventDefault();
        modalBtnSecondary.click();
    }
}

modalBtnPrimary.addEventListener('click', () => {
    if (currentModalType === 'admin') {
        window.shadowspot.requestElevation();
    } else if (currentModalType === 'exit') {
        window.shadowspot.modalResponse('exit');
    }
    hideModal();
});

modalBtnSecondary.addEventListener('click', () => {
    window.shadowspot.modalResponse('cancel');
    hideModal();
});

window.shadowspot.onShowModal((data) => {
    showModal(data);
});

// ============ Theme & Settings ============

settingsBtn.addEventListener('click', (e) => {
    e.stopPropagation();
    settingsMenu.classList.toggle('show');
});

document.addEventListener('click', (e) => {
    if (!settingsMenu.contains(e.target) && !settingsBtn.contains(e.target)) {
        settingsMenu.classList.remove('show');
    }
});

function setTheme(theme) {
    if (theme === 'light') {
        document.body.classList.add('light-theme');
        themeDark.classList.remove('selected');
        themeLight.classList.add('selected');
    } else {
        document.body.classList.remove('light-theme');
        themeDark.classList.add('selected');
        themeLight.classList.remove('selected');
    }
    localStorage.setItem('theme', theme);
    settingsMenu.classList.remove('show');
}

themeDark.addEventListener('click', () => setTheme('dark'));
themeLight.addEventListener('click', () => setTheme('light'));

// ============ Initialize ============

async function init() {
    // Load theme
    const savedTheme = localStorage.getItem('theme') || 'dark';
    setTheme(savedTheme);

    // Setup drag and drop
    setupDragAndDrop();

    // Restore last selected location before rendering
    const lastLocationId = localStorage.getItem('lastLocationId');
    if (lastLocationId) {
        selectedLocationId = lastLocationId;
    }

    // Load locations (will use selectedLocationId if set)
    await renderLocations();

    // Check initial status
    const status = await window.shadowspot.getStatus();
    if (status.isConnected) {
        updateConnectionStatus(true, status.currentLocation);
        if (status.currentLocation) {
            selectedLocationId = status.currentLocation.id;
            renderLocations();
            fetchPublicIP();
        }
    }

    addLog('Ready to connect', 'info');
}

init();
