class Exchanges {
    constructor() {
        this.exchanges = {};
        this.balances = {};  // All balances by exchange name
        this.connected_exchanges = [];
        this.selectedBalanceExchange = null;  // Currently selected exchange for balance display
        this.isSubmitting = false;
    }

    initialize() {
        let el = document.getElementById('conned_excs');
        // Select all spans within the container
        let spans = el.querySelectorAll('.avail_exchange');

        // Extract the text content from each span and store it in the connected_exchanges array
        this.connected_exchanges = Array.from(spans).map(span => span.textContent.trim());

        // Get the currently selected exchange from the selector (defaults to chart view exchange)
        const selector = document.getElementById('balance_exchange_selector');
        if (selector && selector.value) {
            this.selectedBalanceExchange = selector.value;
        } else {
            // No selector or no options - will show empty state
            this.selectedBalanceExchange = null;
        }

        // Register handlers for exchange events
        if (window.UI && window.UI.data && window.UI.data.comms) {
            window.UI.data.comms.on('Exchange_connection_result', this.handleConnectionResult.bind(this));
            window.UI.data.comms.on('balances_refreshed', this.handleBalancesRefreshed.bind(this));
        }
    }

    onBalanceExchangeChange(exchangeName) {
        this.selectedBalanceExchange = exchangeName;
        // If we have cached balances for this exchange, display them
        if (this.balances[exchangeName]) {
            this.displaySingleExchangeBalances(exchangeName, this.balances[exchangeName]);
        } else {
            // No cached balances, show empty state
            this.displaySingleExchangeBalances(exchangeName, []);
        }
    }

    displaySingleExchangeBalances(exchangeName, balanceList) {
        const tbl = document.getElementById('balances_tbl');
        if (!tbl) return;

        let html = '<table><tr><th>Asset</th><th>Balance</th><th>Profit & Loss</th></tr>';
        let hasValidBalances = false;

        if (Array.isArray(balanceList) && balanceList.length > 0) {
            for (const balance of balanceList) {
                // Skip N/A placeholder entries
                if (balance.asset === 'N/A' && balance.balance === 0) continue;
                hasValidBalances = true;
                html += `<tr>
                    <td>${balance.asset || ''}</td>
                    <td>${this.formatBalance(balance.balance)}</td>
                    <td>${this.formatBalance(balance.pnl)}</td>
                </tr>`;
            }
        }

        if (!hasValidBalances) {
            html += '<tr><td colspan="3" style="text-align: center; color: #888;">No balances available</td></tr>';
        }

        html += '</table>';
        tbl.innerHTML = html;
    }

    status() {
        // Reset form state when opening
        this.resetFormState();
        document.getElementById('exchanges_config_form').style.display = "grid";
    }

    closeForm() {
        this.resetFormState();
        document.getElementById('exchanges_config_form').style.display = "none";
    }

    resetFormState() {
        this.isSubmitting = false;
        const statusEl = document.getElementById('exchange_status');
        const connectBtn = document.getElementById('exchange_connect_btn');

        if (statusEl) {
            statusEl.style.display = 'none';
            document.getElementById('exchange_status_text').textContent = '';
        }
        if (connectBtn) {
            connectBtn.disabled = false;
            connectBtn.textContent = 'Connect';
        }
    }

    showStatus(message, type) {
        const statusEl = document.getElementById('exchange_status');
        const statusText = document.getElementById('exchange_status_text');

        if (statusEl && statusText) {
            statusText.textContent = message;
            statusEl.style.display = 'block';

            // Set color based on type
            if (type === 'loading') {
                statusEl.style.color = '#666';
                statusEl.style.backgroundColor = '#f0f0f0';
            } else if (type === 'success') {
                statusEl.style.color = '#155724';
                statusEl.style.backgroundColor = '#d4edda';
            } else if (type === 'error') {
                statusEl.style.color = '#721c24';
                statusEl.style.backgroundColor = '#f8d7da';
            }
        }
    }

    validateApiKey(data) {
        return !(data === undefined || data === null || data === "");
    }

    handleConnectionResult(data) {
        this.isSubmitting = false;
        const connectBtn = document.getElementById('exchange_connect_btn');

        if (connectBtn) {
            connectBtn.disabled = false;
            connectBtn.textContent = 'Connect';
        }

        if (data.status === 'success') {
            this.showStatus('Exchange connected successfully! Reloading...', 'success');
            // Reload after a brief delay so user sees the success message
            setTimeout(() => {
                location.reload();
            }, 1500);
        } else if (data.status === 'already_connected') {
            this.showStatus(data.message || 'Exchange is already connected.', 'loading');
        } else if (data.status === 'failure' || data.status === 'error') {
            this.showStatus(data.message || 'Failed to connect exchange.', 'error');
        } else {
            this.showStatus(data.message || 'Unknown response from server.', 'error');
        }
    }

    // Legacy handler for backwards compatibility
    postConnection(data) {
        this.handleConnectionResult(data);
    }

    submitApi() {
        // Prevent double submission
        if (this.isSubmitting) {
            return;
        }

        // Collect the data to submit.
        let exchange = document.getElementById('c_exchanges').value;
        let user = window.UI.data.user_name;
        let key = document.getElementById('api_key').value;
        let secret_key = document.getElementById('api_secret_key').value;
        let passphrase = document.getElementById('api_passphrase').value;
        let keys = { 'key': key, 'secret': secret_key };
        if (passphrase) {
            keys.passphrase = passphrase;
        }

        // Determine if validation is required based on the exchange type.
        const isPublicExchange = bt_data.public_exchanges.includes(exchange);
        const isKeyValid = this.validateApiKey(key);
        const isSecretKeyValid = this.validateApiKey(secret_key);

        // For public exchanges, API keys are optional (for higher rate limits)
        // For non-public exchanges, API keys are required
        if (isPublicExchange) {
            // If user provided keys, use them; otherwise connect without keys
            if (!key && !secret_key && !passphrase) {
                keys = {};  // No keys provided, connect as public
            } else if (!isKeyValid || !isSecretKeyValid) {
                // User provided partial keys - warn them
                this.showStatus('Enter API key and secret together (and passphrase if required), or leave all fields empty for public access.', 'error');
                return;
            }
            // If both keys are valid, keep them (keys object already set)
        } else if (!isKeyValid || !isSecretKeyValid) {
            // Validate keys for non-public exchanges
            this.showStatus('Please enter a valid API key and secret key.', 'error');
            return;  // Exit early if validation fails
        }

        // KuCoin requires API passphrase for authenticated requests.
        if (exchange.toLowerCase() === 'kucoin' && key && secret_key && !passphrase) {
            this.showStatus('KuCoin requires an API passphrase.', 'error');
            return;
        }

        // Show loading state
        this.isSubmitting = true;
        const connectBtn = document.getElementById('exchange_connect_btn');
        if (connectBtn) {
            connectBtn.disabled = true;
            connectBtn.textContent = 'Connecting...';
        }
        this.showStatus('Connecting to exchange...', 'loading');

        // Send the data
        let payload = { 'user': user, 'exch': exchange, 'keys': keys };
        window.UI.data.comms.sendToApp("config_exchange", payload);

        // Set a timeout in case we don't get a response
        setTimeout(() => {
            if (this.isSubmitting) {
                this.isSubmitting = false;
                if (connectBtn) {
                    connectBtn.disabled = false;
                    connectBtn.textContent = 'Connect';
                }
                this.showStatus('Connection timed out. Please try again.', 'error');
            }
        }, 30000);  // 30 second timeout
    }

    refreshBalances() {
        console.log('refreshBalances() called');
        const btn = document.getElementById('refresh_balances_btn');
        if (btn) {
            btn.disabled = true;
            btn.textContent = '...';
        }

        console.log('Sending refresh_balances message for user:', window.UI.data.user_name);
        window.UI.data.comms.sendToApp("refresh_balances", {
            user: window.UI.data.user_name
        });

        // Set a timeout in case we don't get a response
        setTimeout(() => {
            if (btn && btn.disabled) {
                btn.disabled = false;
                btn.textContent = '↻';
            }
        }, 15000);  // 15 second timeout
    }

    handleBalancesRefreshed(data) {
        console.log('handleBalancesRefreshed called with:', data);
        const btn = document.getElementById('refresh_balances_btn');
        if (btn) {
            btn.disabled = false;
            btn.textContent = '↻';
        }

        if (data.success && data.balances) {
            console.log('Updating balances cache with:', data.balances);
            // Store all balances in cache
            this.balances = data.balances;
            // Display only the selected exchange's balances
            this.updateBalancesTable(data.balances);
        } else if (!data.success) {
            console.error('Failed to refresh balances:', data.message);
        }
    }

    updateBalancesTable(balances) {
        // Update the selector with available exchanges
        this.updateBalanceExchangeSelector(Object.keys(balances));

        // Only display the selected exchange's balances
        let selectedExchange = this.selectedBalanceExchange;

        // If no exchange is selected or selected doesn't exist, pick the first one
        if (!selectedExchange || !balances[selectedExchange]) {
            const exchanges = Object.keys(balances);
            if (exchanges.length > 0) {
                selectedExchange = exchanges[0];
                this.selectedBalanceExchange = selectedExchange;
                const selector = document.getElementById('balance_exchange_selector');
                if (selector) {
                    selector.value = selectedExchange;
                }
            }
        }

        const exchangeBalances = balances[selectedExchange] || [];
        this.displaySingleExchangeBalances(selectedExchange, exchangeBalances);
    }

    updateBalanceExchangeSelector(exchanges) {
        const selector = document.getElementById('balance_exchange_selector');
        if (!selector) return;

        // Get current selection
        const currentSelection = selector.value;

        // Rebuild options
        selector.innerHTML = '';
        for (const exchange of exchanges) {
            const option = document.createElement('option');
            option.value = exchange;
            option.textContent = exchange;
            if (exchange === currentSelection || exchange === this.selectedBalanceExchange) {
                option.selected = true;
            }
            selector.appendChild(option);
        }
    }

    formatBalance(value) {
        if (value === null || value === undefined) return '0';
        const val = parseFloat(value);
        if (isNaN(val)) return String(value);
        if (val === 0) return '0';

        if (Math.abs(val) < 0.00001) {
            return val.toFixed(8).replace(/\.?0+$/, '');
        } else if (Math.abs(val) < 1) {
            return val.toFixed(6).replace(/\.?0+$/, '');
        } else if (Math.abs(val) < 1000) {
            return val.toFixed(4).replace(/\.?0+$/, '');
        } else {
            return val.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
        }
    }
}
