'use strict';

document.addEventListener('DOMContentLoaded', function() {
    let network = null;
    let allNodes = new vis.DataSet();
    let allEdges = new vis.DataSet();
    let allLocationsData = {};
    let clientIpApiUrls = {};

    const lgForm = document.getElementById('lg-form');
    const executeBtn = document.getElementById('execute-btn');
    const methodSelect = document.getElementById('method');
    const outputConsole = document.getElementById('output-console');
    const formError = document.getElementById('form-error');
    const mainLocationSelector = document.getElementById('main-location-selector');
    const locationNameDisplay = document.getElementById('location-name-display');
    const facilityNameDisplay = document.getElementById('facility-name-display');
    const mapLinkBtn = document.getElementById('map-link-btn');
    const peeringdbLinkBtn = document.getElementById('peeringdb-link-btn');
    const lgIpv4Input = document.getElementById('lg-ipv4');
    const lgIpv6Input = document.getElementById('lg-ipv6');
    const clientIpv4Input = document.getElementById('client-ipv4');
    const clientIpv6Input = document.getElementById('client-ipv6');
    const iperfInInput = document.getElementById('iperf-in');
    const iperfOutInput = document.getElementById('iperf-out');
    const speedtestLinksContainer = document.getElementById('speedtest-links');
    const webSpeedtestBtn = document.getElementById('web-speedtest-btn');
    const visualizerContainer = document.getElementById('visualizer-container');
    const networkContainer = document.getElementById('mynetwork');
    const loader = document.getElementById('visualizer-loader');
    const legendAndFilters = document.querySelector('.bgprtv-controls-wrapper');
    const filterControls = document.querySelectorAll('input[name="bgprtv-filter"]');
    const allCommunitiesCheckbox = document.querySelector('input[value="all"]');
    const activeCheckbox = document.querySelector('input[value="active"]');

    fetch('/api/locations')
        .then(response => {
            if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
            return response.json();
        })
        .then(config => {
            if (config.error) throw new Error(config.error);
            allLocationsData = config.locations;
            clientIpApiUrls = config.client_ip_api;
            populateLocationSelectors();
            updateLocationInfo();
            fetchClientIPs();
        })
        .catch(error => {
            console.error('Fatal Error: Could not fetch initial configuration:', error);
            if(lgForm) lgForm.innerHTML = `<div class="alert alert-danger">Could not load application configuration.</div>`;
        });

    if (lgForm) {
        lgForm.addEventListener('submit', async function(event) {
            event.preventDefault();
            const target = document.getElementById('target').value.trim();
            const method = methodSelect.value;
            formError.textContent = '';
            outputConsole.style.display = 'block';
            outputConsole.innerHTML = 'Output will appear here...';
            visualizerContainer.style.display = 'none';
            if (legendAndFilters) legendAndFilters.style.display = 'none';
            if (network) {
                network.destroy();
                network = null;
            }
            setLoadingState(true);
            
            if (method === 'visualize') {
                handleVisualize(target);
            } else if (method === 'bgp_raw') {
                handleRawBgpLookup(target);
            } else {
                handleCommand(method, target);
            }
        });
    }

    if (mainLocationSelector) {
        mainLocationSelector.addEventListener('change', updateLocationInfo);
    }
    
    if (filterControls.length > 0) {
        filterControls.forEach(checkbox => {
            checkbox.addEventListener('change', function(e) {
                const changedValue = e.target.value;
                if (changedValue === 'all' && e.target.checked) {
                    filterControls.forEach(cb => {
                        if (cb.value !== 'all' && cb.value !== 'active') cb.checked = false;
                    });
                } else if (changedValue !== 'all' && changedValue !== 'active' && e.target.checked) {
                    if (allCommunitiesCheckbox) allCommunitiesCheckbox.checked = false;
                }
                const specificCommunityChecked = Array.from(filterControls).some(cb => cb.checked && cb.value !== 'all' && cb.value !== 'active');
                if (!specificCommunityChecked && allCommunitiesCheckbox) {
                    allCommunitiesCheckbox.checked = true;
                }
                filterGraph();
            });
        });
    }

    async function handleApiRequest(url, body, isStreaming = false) {
        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(body)
            });

            if (!response.ok) {
                const data = await response.json();
                throw new Error(data.error || 'An unknown server error occurred.');
            }

            if (isStreaming) {
                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                outputConsole.textContent = '';
                
                while (true) {
                    const { value, done } = await reader.read();
                    if (done) break;
                    const chunk = decoder.decode(value, { stream: true });
                    
                    if ((body.method === 'mtr' || body.method === 'mtr6') && chunk.includes('@@@')) {
                        const parts = chunk.split('@@@');
                        outputConsole.textContent = parts[parts.length - 1];
                    } else {
                        outputConsole.textContent += chunk;
                    }
                    outputConsole.scrollTop = outputConsole.scrollHeight;
                }
            } else {
                return await response.text();
            }
        } catch (error) {
            formError.textContent = error.message;
            outputConsole.textContent = '';
        } finally {
            setLoadingState(false);
        }
    }

    function handleCommand(method, target) {
        outputConsole.textContent = `Executing ${method} on ${target}...\n\nPlease wait.`;
        handleApiRequest('/api/execute', { method, target }, true);
    }

    async function handleRawBgpLookup(target) {
        outputConsole.innerHTML = `Looking up BGP route for ${target}...\n\nPlease wait.`;
        const location = mainLocationSelector.value;
        const rawText = await handleApiRequest('/api/bgp_raw_lookup', { target, location });
        if (rawText) {
            outputConsole.innerHTML = highlightBGPOutput(rawText);
        }
    }

    async function handleVisualize(target) {
        outputConsole.style.display = 'none';
        visualizerContainer.style.display = 'block';
        if(loader) loader.style.display = 'block';
        
        const location = mainLocationSelector.value;
        try {
            const response = await fetch('/api/visualize', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ ip_address: target, location })
            });

            if (!response.ok) {
                const data = await response.json();
                throw new Error(data.error || 'Server returned an error.');
            }
            const data = await response.json();
            
            if (data.not_found) throw new Error(`Route information not found for: ${data.target}`);
            if (!data.nodes || data.nodes.length === 0) throw new Error('Could not parse any valid AS paths.');

            if (legendAndFilters) legendAndFilters.style.display = 'flex';

            const pathCount = data.path_count || 0;
            const dynamicHeight = Math.max(600, 200 + (pathCount * 150));
            networkContainer.style.height = `${dynamicHeight}px`;

            allNodes = new vis.DataSet(data.nodes);
            allEdges = new vis.DataSet(data.edges);
            
            const options = {
                layout: { hierarchical: false },
                edges: {
                    arrows: { to: { enabled: true, scaleFactor: 0.7 } },
                    smooth: { enabled: true, type: "cubicBezier", forceDirection: "horizontal", roundness: 0.85 }
                },
                nodes: {
                    shape: 'box', margin: 15,
                    font: { size: 14, color: '#343a40', multi: 'html', align: 'left' },
                    borderWidth: 2
                },
                physics: { enabled: false }
            };
            
            network = new vis.Network(networkContainer, {}, options);
            
            if (activeCheckbox) activeCheckbox.checked = false;
            if (allCommunitiesCheckbox) allCommunitiesCheckbox.checked = true;
            filterControls.forEach(cb => { if (cb.value !== 'all' && cb.value !== 'active') cb.checked = false; });
            
            filterGraph();
        } catch (error) {
            formError.textContent = error.message;
            visualizerContainer.style.display = 'none';
        } finally {
            if(loader) loader.style.display = 'none';
            setLoadingState(false);
        }
    }
    
    function filterGraph() {
        if (!network) return;
        const showOnlyActive = activeCheckbox ? activeCheckbox.checked : false;
        const showAllCommunities = allCommunitiesCheckbox ? allCommunitiesCheckbox.checked : true;
        
        const selectedCategories = Array.from(filterControls)
            .filter(cb => cb.checked && cb.value !== 'active' && cb.value !== 'all')
            .map(cb => cb.value);

        const nodeFilter = (item) => {
            const activeFilterPassed = !showOnlyActive || item.is_active;
            const categoryFilterPassed = showAllCommunities || selectedCategories.includes(item.path_category);
            return item.path_category === 'global' || (activeFilterPassed && categoryFilterPassed);
        };
        
        const edgeFilter = (item) => {
            const activeFilterPassed = !showOnlyActive || item.is_active;
            const categoryFilterPassed = showAllCommunities || selectedCategories.includes(item.path_category);
            return activeFilterPassed && categoryFilterPassed;
        };

        const filteredNodes = allNodes.get({ filter: nodeFilter });
        const filteredEdges = allEdges.get({ filter: edgeFilter });
        network.setData({ nodes: new vis.DataSet(filteredNodes), edges: new vis.DataSet(filteredEdges) });
    }

    function highlightBGPOutput(text) { /* ... */ }
    function populateLocationSelectors() { /* ... */ }
    function updateLocationInfo() { /* ... */ }
    function fetchClientIPs() { /* ... */ }
    function setLoadingState(isLoading) { /* ... */ }

    function highlightBGPOutput(text) {
        if (!text) return '';
        text = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        text = text.split('\n').map(line => {
            const lowerLine = line.toLowerCase();
            if (lowerLine.includes('best') || lowerLine.includes('paths:') || lowerLine.includes('multipath')) {
                return `<strong class="best-line">${line}</strong>`;
            }
            return line;
        }).join('<br>');
        return text.replace(/\b(AS)?\d{4,9}\b/g, match => `<span class="asn-highlight">${match}</span>`);
    }
    
    function populateLocationSelectors() {
        if (!mainLocationSelector) return;
        mainLocationSelector.innerHTML = '';
        for (const locationName in allLocationsData) {
            const option = document.createElement('option');
            option.value = locationName;
            option.textContent = locationName;
            mainLocationSelector.appendChild(option);
        }
    }

    function updateLocationInfo() {
        if (!mainLocationSelector) return;
        const selectedLocationName = mainLocationSelector.value;
        const locationInfo = allLocationsData[selectedLocationName];
        if (!locationInfo) return;

        if (locationNameDisplay) locationNameDisplay.value = selectedLocationName;
        if (facilityNameDisplay) facilityNameDisplay.value = locationInfo.facility || 'N/A';
        if (mapLinkBtn) mapLinkBtn.href = `https://www.openstreetmap.org/search?query=${encodeURIComponent(selectedLocationName)}`;
        if (peeringdbLinkBtn) {
            peeringdbLinkBtn.href = locationInfo.peeringdb_url || '#';
            peeringdbLinkBtn.classList.toggle('disabled', !locationInfo.peeringdb_url);
        }
        if (lgIpv4Input) lgIpv4Input.value = locationInfo.ipv4 || 'N/A';
        if (lgIpv6Input) lgIpv6Input.value = locationInfo.ipv6 || 'N/A';
        if (iperfInInput) iperfInInput.value = locationInfo.iperf_in || 'N/A';
        if (iperfOutInput) iperfOutInput.value = locationInfo.iperf_out || 'N/A';
        
        if (webSpeedtestBtn) {
            if (locationInfo.web_speedtest_url) {
                webSpeedtestBtn.href = locationInfo.web_speedtest_url;
                webSpeedtestBtn.style.display = 'inline-block';
            } else {
                webSpeedtestBtn.style.display = 'none';
            }
        }

        if (speedtestLinksContainer) {
            speedtestLinksContainer.innerHTML = '';
            if (locationInfo.speedtest_url_base && Array.isArray(locationInfo.speedtest_files)) {
                locationInfo.speedtest_files.forEach(fileName => {
                    const link = document.createElement('a');
                    link.href = locationInfo.speedtest_url_base + fileName;
                    link.textContent = fileName.replace('.bin', '').toUpperCase();
                    link.className = 'btn btn-sm btn-outline-secondary';
                    link.target = '_blank';
                    speedtestLinksContainer.appendChild(link);
                });
            }
        }
    }

    function fetchClientIPs() {
        if (clientIpv4Input && clientIpApiUrls && clientIpApiUrls.v4) {
            clientIpv4Input.value = 'Detecting...';
            fetch(clientIpApiUrls.v4)
                .then(response => response.json())
                .then(data => { if(clientIpv4Input) clientIpv4Input.value = data.ip || 'Unavailable'; })
                .catch(() => { if(clientIpv4Input) clientIpv4Input.value = 'Unavailable'; });
        } else if (clientIpv4Input) {
            clientIpv4Input.value = 'Not Configured';
        }

        if (clientIpv6Input && clientIpApiUrls && clientIpApiUrls.v6) {
            clientIpv6Input.value = 'Detecting...';
            fetch(clientIpApiUrls.v6)
                .then(response => response.json())
                .then(data => { if(clientIpv6Input) clientIpv6Input.value = data.ip || 'Unavailable'; })
                .catch(() => { if(clientIpv6Input) clientIpv6Input.value = 'Unavailable'; });
        } else if (clientIpv6Input) {
            clientIpv6Input.value = 'Not Configured';
        }
    }

    function setLoadingState(isLoading) {
        if (!executeBtn) return;
        executeBtn.disabled = isLoading;
        executeBtn.innerHTML = isLoading 
            ? `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Executing...`
            : 'Execute';
    }
});

window.copyToClipboard = function(elementId) {
    const input = document.getElementById(elementId);
    if (!input) return;
    const textToCopy = input.value;

    if (navigator.clipboard && window.isSecureContext) {
        navigator.clipboard.writeText(textToCopy).then(() => {
            updateCopyButton(input.nextElementSibling);
        }).catch(err => {
            console.error('Modern copy failed: ', err);
        });
    } else {
        input.select();
        try {
            document.execCommand('copy');
            updateCopyButton(input.nextElementSibling);
        } catch (err) {
            console.error('Fallback copy failed: ', err);
        }
    }
}

function updateCopyButton(copyButton) {
    if (copyButton && copyButton.classList.contains('copy-btn')) {
        const originalText = copyButton.textContent;
        copyButton.textContent = 'Copied!';
        setTimeout(() => { copyButton.textContent = originalText; }, 2000);
    }
}