/**
 * TradeUIManager - Handles DOM updates and trade card rendering
 */
class TradeUIManager {
    constructor() {
        this.targetEl = null;
        this.formElement = null;
        this.priceInput = null;
        this.currentPriceDisplay = null;
        this.qtyInput = null;
        this.tradeValueDisplay = null;
        this.orderTypeSelect = null;
        this.targetSelect = null;
        this.sideSelect = null;
        this.symbolInput = null;
        this.exchangeSelect = null;
        this.testnetCheckbox = null;
        this.testnetRow = null;
        this.stopLossInput = null;
        this.takeProfitInput = null;
        this.timeInForceSelect = null;
        this.onCloseTrade = null;

        // Exchanges known to support testnet/sandbox mode
        this.testnetSupportedExchanges = [
            'binance', 'binanceus', 'binanceusdm', 'binancecoinm',
            'kucoin', 'kucoinfutures',
            'bybit',
            'okx', 'okex',
            'bitget',
            'bitmex',
            'deribit',
            'phemex',
            'mexc'
        ];
    }

    /**
     * Initializes the UI elements with provided IDs.
     * @param {Object} config - Configuration object with element IDs.
     */
    initUI(config = {}) {
        const {
            targetId = 'tradesContainer',
            formElId = 'new_trade_form',
            priceId = 'price',
            currentPriceId = 'currentPrice',
            qtyId = 'quantity',
            tradeValueId = 'tradeValue',
            orderTypeId = 'orderType',
            tradeTargetId = 'tradeTarget',
            sideId = 'side',
            symbolId = 'tradeSymbol',
            exchangeId = 'tradeExchange',
            testnetId = 'tradeTestnet',
            testnetRowId = 'testnet-row',
            stopLossId = 'stopLoss',
            takeProfitId = 'takeProfit',
            timeInForceId = 'timeInForce'
        } = config;

        this.targetEl = document.getElementById(targetId);
        if (!this.targetEl) {
            console.warn(`Element for displaying trades "${targetId}" not found.`);
        }

        this.formElement = document.getElementById(formElId);
        if (!this.formElement) {
            console.warn(`Trade form element "${formElId}" not found.`);
        }

        this.priceInput = document.getElementById(priceId);
        this.currentPriceDisplay = document.getElementById(currentPriceId);
        this.qtyInput = document.getElementById(qtyId);
        this.tradeValueDisplay = document.getElementById(tradeValueId);
        this.orderTypeSelect = document.getElementById(orderTypeId);
        this.targetSelect = document.getElementById(tradeTargetId);
        this.sideSelect = document.getElementById(sideId);
        this.symbolInput = document.getElementById(symbolId);
        this.exchangeSelect = document.getElementById(exchangeId);
        this.testnetCheckbox = document.getElementById(testnetId);
        this.testnetRow = document.getElementById(testnetRowId);
        this.stopLossInput = document.getElementById(stopLossId);
        this.takeProfitInput = document.getElementById(takeProfitId);
        this.timeInForceSelect = document.getElementById(timeInForceId);

        // Set up event listeners
        this._setupFormListeners();
    }

    /**
     * Set up form event listeners for price calculation.
     */
    _setupFormListeners() {
        const updateTradeValue = () => {
            if (!this.qtyInput || !this.tradeValueDisplay) return;

            let price;
            if (this.orderTypeSelect?.value === 'MARKET') {
                price = parseFloat(this.currentPriceDisplay?.value || 0);
            } else {
                price = parseFloat(this.priceInput?.value || 0);
            }
            const qty = parseFloat(this.qtyInput.value || 0);
            this.tradeValueDisplay.value = (qty * price).toFixed(2);
        };

        // Order type changes affect which price to use
        if (this.orderTypeSelect) {
            this.orderTypeSelect.addEventListener('change', () => {
                if (this.orderTypeSelect.value === 'MARKET') {
                    if (this.currentPriceDisplay) this.currentPriceDisplay.style.display = 'inline-block';
                    if (this.priceInput) this.priceInput.style.display = 'none';
                } else {
                    if (this.currentPriceDisplay) this.currentPriceDisplay.style.display = 'none';
                    if (this.priceInput) this.priceInput.style.display = 'inline-block';
                }
                updateTradeValue();
            });
        }

        // Update trade value on price/qty changes
        if (this.priceInput) {
            this.priceInput.addEventListener('change', updateTradeValue);
            this.priceInput.addEventListener('input', updateTradeValue);
        }
        if (this.qtyInput) {
            this.qtyInput.addEventListener('change', updateTradeValue);
            this.qtyInput.addEventListener('input', updateTradeValue);
        }

        // Trade target (exchange) changes affect testnet visibility and SELL availability
        if (this.targetSelect) {
            this.targetSelect.addEventListener('change', () => {
                this._updateTestnetVisibility();
                this._updateSellAvailability();
            });
        }

        // Exchange dropdown changes update symbol list
        if (this.exchangeSelect) {
            this.exchangeSelect.addEventListener('change', async () => {
                const selectedExchange = this.exchangeSelect.value;
                await this._populateSymbolDropdown(selectedExchange, null);
            });
        }

        // Symbol changes affect SELL availability
        if (this.symbolInput) {
            this.symbolInput.addEventListener('change', () => {
                this._updateSellAvailability();
            });
        }

        // Testnet checkbox changes affect broker key, thus SELL availability
        if (this.testnetCheckbox) {
            this.testnetCheckbox.addEventListener('change', () => {
                this._updateSellAvailability();
            });
        }
    }

    /**
     * Populates the symbol dropdown with trading pairs from EDM.
     * @param {string} exchange - The exchange to fetch symbols for.
     * @param {string|null} selectedSymbol - Symbol to select (or null to use first).
     */
    async _populateSymbolDropdown(exchange, selectedSymbol) {
        if (!this.symbolInput) return;

        // Popular base currencies to prioritize (most traded first)
        const popularBases = ['BTC', 'ETH', 'SOL', 'XRP', 'ADA', 'DOGE', 'AVAX', 'DOT', 'MATIC', 'LINK',
                             'LTC', 'UNI', 'ATOM', 'XLM', 'ALGO', 'FIL', 'NEAR', 'APT', 'ARB', 'OP'];

        // Common symbols as fallback
        const commonSymbols = ['BTC/USDT', 'ETH/USDT', 'BTC/USD', 'ETH/USD', 'SOL/USDT', 'XRP/USDT', 'ADA/USDT', 'DOGE/USDT'];

        let symbols = [];
        let allExchangeSymbols = [];

        // Try to fetch symbols from EDM
        try {
            const edm_url = window.bt_data?.edm_url || 'http://localhost:8080';
            const response = await fetch(`${edm_url}/exchanges/${exchange.toLowerCase()}/symbols`);
            if (response.ok) {
                const data = await response.json();
                if (data.symbols && data.symbols.length > 0) {
                    allExchangeSymbols = data.symbols;
                    console.log(`Fetched ${allExchangeSymbols.length} symbols for ${exchange}`);

                    // Prioritize: First add popular USDT pairs in order of popularity
                    for (const base of popularBases) {
                        const usdtPair = `${base}/USDT`;
                        if (allExchangeSymbols.includes(usdtPair) && !symbols.includes(usdtPair)) {
                            symbols.push(usdtPair);
                        }
                    }

                    // Then add popular USD pairs
                    for (const base of popularBases) {
                        const usdPair = `${base}/USD`;
                        if (allExchangeSymbols.includes(usdPair) && !symbols.includes(usdPair)) {
                            symbols.push(usdPair);
                        }
                    }

                    // Then add remaining USDT pairs (sorted)
                    const remainingUsdtPairs = allExchangeSymbols
                        .filter(s => s.endsWith('/USDT') && !symbols.includes(s))
                        .sort();
                    symbols.push(...remainingUsdtPairs);

                    // Then add remaining USD pairs
                    const remainingUsdPairs = allExchangeSymbols
                        .filter(s => s.endsWith('/USD') && !symbols.includes(s))
                        .sort();
                    symbols.push(...remainingUsdPairs);

                    // Finally add other pairs (BTC pairs, etc.)
                    const otherPairs = allExchangeSymbols
                        .filter(s => !symbols.includes(s))
                        .sort();
                    symbols.push(...otherPairs);
                }
            }
        } catch (error) {
            console.warn(`Failed to fetch symbols for ${exchange}, using defaults:`, error);
        }

        // Fall back to common symbols if nothing fetched
        if (symbols.length === 0) {
            symbols = [...commonSymbols];
        }

        // Ensure selected symbol is at the top of the list
        if (selectedSymbol) {
            // Remove it if it exists elsewhere in the list
            symbols = symbols.filter(s => s !== selectedSymbol);
            // Add it to the front
            symbols.unshift(selectedSymbol);
        }

        // Populate the dropdown
        this.symbolInput.innerHTML = '';
        for (const symbol of symbols) {
            const option = document.createElement('option');
            option.value = symbol;
            option.textContent = symbol;
            this.symbolInput.appendChild(option);
        }

        // Set the selected value
        if (selectedSymbol) {
            this.symbolInput.value = selectedSymbol;
        }
    }

    /**
     * Updates testnet checkbox visibility based on selected exchange.
     */
    _updateTestnetVisibility() {
        if (!this.testnetRow || !this.targetSelect) return;

        const selectedTarget = this.targetSelect.value;
        const isPaperTrade = selectedTarget === 'test_exchange';

        if (isPaperTrade) {
            // Hide testnet row for paper trading
            this.testnetRow.style.display = 'none';
        } else {
            // Show testnet row for live exchanges
            this.testnetRow.style.display = 'block';

            // Check if this exchange supports testnet
            const exchangeId = selectedTarget.toLowerCase();
            const supportsTestnet = this.testnetSupportedExchanges.includes(exchangeId);

            const warningEl = document.getElementById('testnet-warning');
            const unavailableEl = document.getElementById('testnet-unavailable');

            if (supportsTestnet) {
                // Enable testnet checkbox
                if (this.testnetCheckbox) {
                    this.testnetCheckbox.disabled = false;
                    this.testnetCheckbox.checked = true;
                }
                if (warningEl) warningEl.style.display = 'block';
                if (unavailableEl) unavailableEl.style.display = 'none';
            } else {
                // Disable testnet checkbox - this exchange doesn't support it
                if (this.testnetCheckbox) {
                    this.testnetCheckbox.disabled = true;
                    this.testnetCheckbox.checked = false;
                }
                if (warningEl) warningEl.style.display = 'none';
                if (unavailableEl) unavailableEl.style.display = 'block';
            }
        }
    }

    /**
     * Populates the exchange selector with connected exchanges.
     * @param {string[]} connectedExchanges - List of connected exchange names.
     */
    populateExchangeSelector(connectedExchanges) {
        if (!this.targetSelect) return;

        // Clear existing options except Paper Trade
        while (this.targetSelect.options.length > 1) {
            this.targetSelect.remove(1);
        }

        // Add connected exchanges
        if (connectedExchanges && connectedExchanges.length > 0) {
            for (const exchange of connectedExchanges) {
                // Skip 'default' exchange used internally
                if (exchange.toLowerCase() === 'default') continue;

                const option = document.createElement('option');
                option.value = exchange.toLowerCase();
                option.textContent = `${exchange} (Live)`;
                this.targetSelect.appendChild(option);
            }
        }
    }

    /**
     * Populates the exchange dropdown for price data source.
     * @param {string[]} availableExchanges - List of available exchange names.
     * @param {string} defaultExchange - Default exchange to select (chart view).
     */
    populateExchangeDropdown(availableExchanges, defaultExchange = null) {
        if (!this.exchangeSelect) return;

        // Clear existing options
        this.exchangeSelect.innerHTML = '';

        // Common exchanges list as fallback
        const commonExchanges = ['binance', 'kucoin', 'coinbase', 'kraken', 'bybit', 'okx', 'gemini', 'bitstamp'];
        let exchanges = (availableExchanges && availableExchanges.length > 0)
            ? [...availableExchanges]
            : [...commonExchanges];

        // Ensure chart view exchange is in the list and at the top
        if (defaultExchange) {
            const normalizedDefault = defaultExchange.toLowerCase();
            // Remove if exists elsewhere in the list
            exchanges = exchanges.filter(e => e.toLowerCase() !== normalizedDefault);
            // Add at the beginning
            exchanges.unshift(normalizedDefault);
        }

        // Add exchanges
        for (const exchange of exchanges) {
            if (exchange.toLowerCase() === 'default') continue;

            const option = document.createElement('option');
            option.value = exchange.toLowerCase();
            option.textContent = exchange.charAt(0).toUpperCase() + exchange.slice(1).toLowerCase();
            this.exchangeSelect.appendChild(option);
        }

        // Set default to chart view exchange (first option after our reordering)
        if (defaultExchange) {
            this.exchangeSelect.value = defaultExchange.toLowerCase();
        }
    }

    /**
     * Displays the trade creation form.
     * @param {number} currentPrice - Optional current price to prefill.
     * @param {string} symbol - Optional trading pair to prefill.
     * @param {string[]} connectedExchanges - Optional list of connected exchanges.
     * @param {string} chartExchange - Optional current chart view exchange.
     */
    async displayForm(currentPrice = null, symbol = null, connectedExchanges = null, chartExchange = null) {
        if (!this.formElement) {
            console.error("Form element not initialized.");
            return;
        }

        // Reset form values
        if (this.qtyInput) this.qtyInput.value = '';
        if (this.tradeValueDisplay) this.tradeValueDisplay.value = '0';
        if (this.stopLossInput) this.stopLossInput.value = '';
        if (this.takeProfitInput) this.takeProfitInput.value = '';
        if (this.timeInForceSelect) this.timeInForceSelect.value = 'GTC';

        // Set current price if available
        if (currentPrice !== null) {
            if (this.priceInput) this.priceInput.value = currentPrice;
            if (this.currentPriceDisplay) this.currentPriceDisplay.value = currentPrice;
        }

        // Populate target selector (Paper vs Live exchanges)
        if (connectedExchanges) {
            this.populateExchangeSelector(connectedExchanges);
        }

        // Populate exchange dropdown for price data source
        this.populateExchangeDropdown(connectedExchanges, chartExchange);

        // Populate symbol dropdown with the chart exchange and symbol
        const exchangeToUse = chartExchange || 'binance';
        await this._populateSymbolDropdown(exchangeToUse, symbol);

        // Reset to paper trade and hide testnet row
        if (this.targetSelect) {
            this.targetSelect.value = 'test_exchange';
        }
        if (this.testnetRow) {
            this.testnetRow.style.display = 'none';
        }
        if (this.testnetCheckbox) {
            this.testnetCheckbox.checked = true;
        }

        this.formElement.style.display = 'grid';

        // Update SELL availability based on current broker/symbol
        await this._updateSellAvailability();
    }

    /**
     * Hides the trade form.
     */
    hideForm() {
        if (this.formElement) {
            this.formElement.style.display = 'none';
        }
    }

    /**
     * Updates the current price display (for market orders).
     * @param {number} price - The current price.
     */
    updateCurrentPrice(price) {
        if (this.currentPriceDisplay) {
            this.currentPriceDisplay.value = price;
        }
    }

    /**
     * Updates the HTML representation of the trades as cards.
     * @param {Object[]} trades - The list of trades to display.
     */
    updateTradesHtml(trades) {
        if (!this.targetEl) {
            console.error("Target element for displaying trades is not set.");
            return;
        }

        // Clear existing content
        while (this.targetEl.firstChild) {
            this.targetEl.removeChild(this.targetEl.firstChild);
        }

        if (!trades || trades.length === 0) {
            const emptyMsg = document.createElement('p');
            emptyMsg.className = 'no-data-msg';
            emptyMsg.textContent = 'No active trades';
            this.targetEl.appendChild(emptyMsg);
            return;
        }

        // Create and append cards for all trades
        for (const trade of trades) {
            try {
                const tradeCard = this._createTradeCard(trade);
                this.targetEl.appendChild(tradeCard);
            } catch (error) {
                console.error(`Error processing trade:`, error, trade);
            }
        }
    }

    /**
     * Creates a trade card HTML element.
     * @param {Object} trade - The trade data.
     * @returns {HTMLElement} - The card element.
     */
    _createTradeCard(trade) {
        const tradeItem = document.createElement('div');
        tradeItem.className = 'trade-card';
        tradeItem.setAttribute('data-trade-id', trade.unique_id || trade.tbl_key);

        // Add paper/live class
        if (trade.is_paper) {
            tradeItem.classList.add('trade-paper');
        } else {
            tradeItem.classList.add('trade-live');
        }

        // Add side class
        const side = (trade.side || 'BUY').toUpperCase();
        tradeItem.classList.add(side === 'BUY' ? 'trade-buy' : 'trade-sell');

        // Close/Delete button
        const closeButton = document.createElement('button');
        closeButton.className = 'trade-close-btn';
        closeButton.innerHTML = '&#10008;';
        closeButton.title = 'Close Trade';
        closeButton.addEventListener('click', (e) => {
            e.stopPropagation();
            if (this.onCloseTrade) {
                this.onCloseTrade(trade.unique_id || trade.tbl_key);
            }
        });
        tradeItem.appendChild(closeButton);

        // Paper badge
        if (trade.is_paper) {
            const paperBadge = document.createElement('span');
            paperBadge.className = 'trade-paper-badge';
            paperBadge.textContent = 'PAPER';
            tradeItem.appendChild(paperBadge);
        } else if (trade.testnet) {
            // Testnet badge for live trades
            const testnetBadge = document.createElement('span');
            testnetBadge.className = 'trade-testnet-badge';
            testnetBadge.textContent = 'TESTNET';
            testnetBadge.style.cssText = 'background: #28a745; color: white; padding: 1px 4px; border-radius: 3px; font-size: 9px; position: absolute; top: 4px; left: 4px;';
            tradeItem.appendChild(testnetBadge);
        } else if (!trade.is_paper) {
            // Production badge for live trades (not paper, not testnet)
            const prodBadge = document.createElement('span');
            prodBadge.className = 'trade-prod-badge';
            prodBadge.textContent = 'LIVE';
            prodBadge.style.cssText = 'background: #dc3545; color: white; padding: 1px 4px; border-radius: 3px; font-size: 9px; position: absolute; top: 4px; left: 4px;';
            tradeItem.appendChild(prodBadge);
        }

        // Trade info container
        const tradeInfo = document.createElement('div');
        tradeInfo.className = 'trade-info';

        // Symbol and side
        const symbolRow = document.createElement('div');
        symbolRow.className = 'trade-symbol-row';

        const sideSpan = document.createElement('span');
        sideSpan.className = `trade-side ${side.toLowerCase()}`;
        sideSpan.textContent = side;
        symbolRow.appendChild(sideSpan);

        const symbolSpan = document.createElement('span');
        symbolSpan.className = 'trade-symbol';
        symbolSpan.textContent = trade.symbol || 'N/A';
        symbolRow.appendChild(symbolSpan);

        tradeInfo.appendChild(symbolRow);

        // Quantity
        const qtyRow = document.createElement('div');
        qtyRow.className = 'trade-row';
        qtyRow.innerHTML = `<span class="trade-label">Qty:</span><span class="trade-value">${this._formatNumber(trade.base_order_qty)}</span>`;
        tradeInfo.appendChild(qtyRow);

        // Entry price
        const entryRow = document.createElement('div');
        entryRow.className = 'trade-row';
        const stats = trade.stats || {};
        const entryPrice = stats.opening_price || trade.order_price || 0;
        entryRow.innerHTML = `<span class="trade-label">Entry:</span><span class="trade-value">${this._formatPrice(entryPrice)}</span>`;
        tradeInfo.appendChild(entryRow);

        // P/L
        const pl = stats.profit || 0;
        const plPct = stats.profit_pct || 0;
        const plRow = document.createElement('div');
        plRow.className = 'trade-row trade-pl-row';
        plRow.id = `${trade.unique_id}_pl`;

        const plClass = pl >= 0 ? 'positive' : 'negative';
        plRow.innerHTML = `<span class="trade-label">P/L:</span><span class="trade-value trade-pl ${plClass}" id="${trade.unique_id}_pl_value">${this._formatPL(pl)} (${this._formatPct(plPct)})</span>`;
        tradeInfo.appendChild(plRow);

        tradeItem.appendChild(tradeInfo);

        // Hover details panel
        const hoverPanel = document.createElement('div');
        hoverPanel.className = 'trade-hover';

        let hoverHtml = `<strong>${trade.symbol}</strong>`;
        hoverHtml += `<div class="trade-details">`;
        hoverHtml += `<span>Side: ${side}</span>`;
        hoverHtml += `<span>Type: ${trade.order_type || 'MARKET'}</span>`;
        hoverHtml += `<span>Quantity: ${this._formatNumber(trade.base_order_qty)}</span>`;
        hoverHtml += `<span>Entry Price: ${this._formatPrice(entryPrice)}</span>`;
        hoverHtml += `<span>Current Value: ${this._formatPrice(stats.current_value || 0)}</span>`;
        hoverHtml += `<span class="${plClass}">P/L: ${this._formatPL(pl)} (${this._formatPct(plPct)})</span>`;
        hoverHtml += `<span>Status: ${trade.status || 'unknown'}</span>`;
        // Show actual exchange name (use 'exchange' field for paper trades, otherwise 'target')
        const displayExchange = trade.is_paper ? (trade.exchange || trade.target || 'N/A') : (trade.target || 'N/A');
        hoverHtml += `<span>Exchange: ${displayExchange}</span>`;
        if (trade.is_paper) {
            hoverHtml += `<span class="trade-paper-indicator">Paper Trade</span>`;
        } else if (trade.testnet) {
            hoverHtml += `<span class="trade-testnet-indicator" style="color: #28a745;">Testnet</span>`;
        } else {
            hoverHtml += `<span class="trade-prod-indicator" style="color: #dc3545;">Production (Live)</span>`;
        }
        hoverHtml += `</div>`;

        hoverPanel.innerHTML = hoverHtml;
        tradeItem.appendChild(hoverPanel);

        return tradeItem;
    }

    /**
     * Updates a single trade's P/L display.
     * @param {string} tradeId - The trade ID.
     * @param {number} pl - The P/L value.
     * @param {number} plPct - The P/L percentage.
     */
    updateTradePL(tradeId, pl, plPct) {
        const plEl = document.getElementById(`${tradeId}_pl_value`);
        if (plEl) {
            const plClass = pl >= 0 ? 'positive' : 'negative';
            plEl.className = `trade-value trade-pl ${plClass}`;
            plEl.textContent = `${this._formatPL(pl)} (${this._formatPct(plPct)})`;

            // Add flash animation
            plEl.classList.add('trade-pl-flash');
            setTimeout(() => plEl.classList.remove('trade-pl-flash'), 300);
        }
    }

    /**
     * Removes a trade card from the display.
     * @param {string} tradeId - The trade ID.
     */
    removeTradeCard(tradeId) {
        const card = document.querySelector(`[data-trade-id="${tradeId}"]`);
        if (card) {
            card.classList.add('trade-card-removing');
            setTimeout(() => card.remove(), 300);
        }
    }

    // ============ Formatting helpers ============

    _formatNumber(num) {
        if (num === null || num === undefined) return 'N/A';
        return parseFloat(num).toLocaleString(undefined, { maximumFractionDigits: 6 });
    }

    _formatPrice(price) {
        if (price === null || price === undefined) return 'N/A';
        return parseFloat(price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 8 });
    }

    _formatPL(pl) {
        if (pl === null || pl === undefined) return '$0.00';
        const formatted = Math.abs(pl).toFixed(2);
        return pl >= 0 ? `+$${formatted}` : `-$${formatted}`;
    }

    _formatPct(pct) {
        if (pct === null || pct === undefined) return '0.00%';
        const formatted = Math.abs(pct).toFixed(2);
        return pct >= 0 ? `+${formatted}%` : `-${formatted}%`;
    }

    /**
     * Sets the callback function for closing a trade.
     * @param {Function} callback - The callback function.
     */
    registerCloseTradeCallback(callback) {
        this.onCloseTrade = callback;
    }

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

    /**
     * Initialize broker event listeners through Comms.
     * @param {Comms} comms - The communications instance.
     */
    initBrokerListeners(comms) {
        if (!comms) return;

        // Listen for order fill events via existing message/reply pattern
        comms.on('order_filled', (data) => {
            console.log('Order filled:', data);
            this.refreshAll();
        });

        comms.on('order_cancelled', (data) => {
            console.log('Order cancelled:', data);
            this.refreshAll();
        });

        comms.on('position_closed', (data) => {
            console.log('Position closed:', data);
            this.refreshAll();
        });

        comms.on('sltp_triggered', (data) => {
            console.log('SL/TP triggered:', data);
            const triggerName = data.trigger === 'stop_loss' ? 'Stop Loss' : 'Take Profit';
            const pnl = data.pnl != null ? data.pnl.toFixed(2) : 'N/A';
            alert(`${triggerName} triggered for ${data.symbol}\nPrice: ${data.trigger_price}\nP/L: ${pnl}`);
            this.refreshAll();
        });
    }

    // ============ Open Orders Section ============

    /**
     * Render open orders section.
     * @param {Object[]} orders - List of open order dicts.
     */
    renderOrders(orders) {
        const container = document.getElementById('openOrdersContainer');
        if (!container) return;

        container.innerHTML = '';

        if (!orders || orders.length === 0) {
            container.innerHTML = '<p class="no-data-msg">No open orders</p>';
            return;
        }

        const table = document.createElement('table');
        table.className = 'orders-table';
        table.innerHTML = `
            <tr>
                <th>Symbol</th>
                <th>Side</th>
                <th>Size</th>
                <th>Price</th>
                <th>Broker</th>
                <th>Action</th>
            </tr>
        `;

        for (const order of orders) {
            const row = document.createElement('tr');
            const sideClass = (order.side || '').toLowerCase() === 'buy' ? 'order-buy' : 'order-sell';
            row.className = `order-row ${sideClass}`;
            row.innerHTML = `
                <td>${order.symbol || 'N/A'}</td>
                <td>${(order.side || '').toUpperCase()}</td>
                <td>${this._formatNumber(order.size)}</td>
                <td>${order.price ? this._formatPrice(order.price) : 'MARKET'}</td>
                <td>${order.broker_key || 'paper'}</td>
                <td>
                    <button class="btn-cancel" onclick="UI.trade.cancelOrder('${order.order_id}', '${order.broker_key || 'paper'}')">
                        Cancel
                    </button>
                </td>
            `;
            table.appendChild(row);
        }
        container.appendChild(table);
    }

    // ============ Positions Section ============

    /**
     * Render positions section.
     * @param {Object[]} positions - List of position dicts.
     */
    renderPositions(positions) {
        const container = document.getElementById('positionsContainer');
        if (!container) return;

        container.innerHTML = '';

        if (!positions || positions.length === 0) {
            container.innerHTML = '<p class="no-data-msg">No open positions</p>';
            return;
        }

        for (const pos of positions) {
            const card = this._createPositionCard(pos);
            container.appendChild(card);
        }
    }

    _createPositionCard(position) {
        const card = document.createElement('div');
        card.className = 'position-card';

        const pl = position.unrealized_pnl || 0;
        const plClass = pl >= 0 ? 'positive' : 'negative';
        const plSign = pl >= 0 ? '+' : '';

        card.innerHTML = `
            <div class="position-header">
                <span class="position-symbol">${position.symbol || 'N/A'}</span>
                <span class="position-broker">${position.broker_key || 'paper'}</span>
            </div>
            <div class="position-details">
                <div class="position-row">
                    <span>Size:</span>
                    <span>${this._formatNumber(position.size)}</span>
                </div>
                <div class="position-row">
                    <span>Entry:</span>
                    <span>${position.entry_price ? this._formatPrice(position.entry_price) : '-'}</span>
                </div>
                <div class="position-row">
                    <span>P/L:</span>
                    <span class="position-pl ${plClass}">${plSign}${pl.toFixed(2)}</span>
                </div>
            </div>
            <div class="position-actions">
                <button class="btn-close-position" onclick="UI.trade.closePosition('${position.symbol}', '${position.broker_key || 'paper'}')">
                    Close Position
                </button>
                <button class="btn-cancel-orders" onclick="UI.trade.cancelOrdersForSymbol('${position.symbol}', '${position.broker_key || 'paper'}')" title="Cancel resting orders">
                    Cancel
                </button>
            </div>
        `;
        return card;
    }

    // ============ History Section ============

    /**
     * Render trade history section.
     * @param {Object[]} history - List of trade history dicts.
     */
    renderHistory(history) {
        const container = document.getElementById('historyContainer');
        if (!container) return;

        container.innerHTML = '';

        if (!history || history.length === 0) {
            container.innerHTML = '<p class="no-data-msg">No trade history</p>';
            return;
        }

        // Use history-specific card (no close button)
        for (const trade of history) {
            try {
                const card = this._createHistoryCard(trade);
                container.appendChild(card);
            } catch (error) {
                console.error('Error rendering history trade:', error, trade);
            }
        }
    }

    /**
     * Create a history card for settled/cancelled trades.
     * Unlike active trade cards, history cards have no close button.
     * @param {Object} trade - The trade data.
     * @returns {HTMLElement} - The history card element.
     */
    _createHistoryCard(trade) {
        const card = document.createElement('div');
        card.className = 'trade-card trade-history';
        card.setAttribute('data-trade-id', trade.unique_id || trade.tbl_key);

        // Add paper/live class
        if (trade.is_paper) {
            card.classList.add('trade-paper');
        }

        // Add side class
        const side = (trade.side || 'BUY').toUpperCase();
        card.classList.add(side === 'BUY' ? 'trade-buy' : 'trade-sell');

        // Status badge (closed/cancelled)
        const statusBadge = document.createElement('span');
        statusBadge.className = 'trade-status-badge';
        statusBadge.textContent = (trade.status || 'closed').toUpperCase();
        statusBadge.style.cssText = `
            position: absolute; top: 4px; right: 4px;
            background: ${trade.status === 'cancelled' ? '#ff9800' : '#9e9e9e'};
            color: white; padding: 1px 4px; border-radius: 3px; font-size: 9px;
        `;
        card.appendChild(statusBadge);

        // Paper badge
        if (trade.is_paper) {
            const paperBadge = document.createElement('span');
            paperBadge.className = 'trade-paper-badge';
            paperBadge.textContent = 'PAPER';
            card.appendChild(paperBadge);
        }

        // Trade info
        const info = document.createElement('div');
        info.className = 'trade-info';

        const symbolRow = document.createElement('div');
        symbolRow.className = 'trade-symbol-row';
        symbolRow.innerHTML = `
            <span class="trade-side ${side.toLowerCase()}">${side}</span>
            <span class="trade-symbol">${trade.symbol || 'N/A'}</span>
        `;
        info.appendChild(symbolRow);

        // Stats
        const stats = trade.stats || {};
        const qty = stats.qty_filled || trade.base_order_qty || 0;
        const settledPrice = stats.settled_price || stats.opening_price || trade.order_price || 0;
        const profit = stats.profit || 0;
        const profitClass = profit >= 0 ? 'positive' : 'negative';
        const profitSign = profit >= 0 ? '+' : '';

        info.innerHTML += `
            <div class="trade-row">
                <span class="trade-label">Qty:</span>
                <span class="trade-value">${this._formatNumber(qty)}</span>
            </div>
            <div class="trade-row">
                <span class="trade-label">Price:</span>
                <span class="trade-value">${this._formatPrice(settledPrice)}</span>
            </div>
            <div class="trade-row">
                <span class="trade-label">P/L:</span>
                <span class="trade-pl ${profitClass}">${profitSign}${profit.toFixed(2)}</span>
            </div>
        `;

        card.appendChild(info);
        return card;
    }

    // ============ Refresh Methods ============

    async refreshOrders() {
        try {
            const response = await fetch('/api/manual/orders');
            const data = await response.json();
            if (data.success) {
                this.renderOrders(data.orders);
            }
        } catch (e) {
            console.error('Failed to refresh orders:', e);
        }
    }

    async refreshPositions() {
        try {
            const response = await fetch('/api/manual/positions');
            const data = await response.json();
            if (data.success) {
                this.renderPositions(data.positions);
            }
        } catch (e) {
            console.error('Failed to refresh positions:', e);
        }
    }

    async refreshHistory() {
        try {
            const response = await fetch('/api/manual/history?limit=20');
            const data = await response.json();
            if (data.success) {
                this.renderHistory(data.history);
            }
        } catch (e) {
            console.error('Failed to refresh history:', e);
        }
    }

    refreshAll() {
        this.refreshOrders();
        this.refreshPositions();
        this.refreshHistory();
        this.updateBrokerStatus();
    }

    // ============ Broker Actions ============

    /**
     * Cancel a specific open order via REST API.
     */
    async cancelOrder(orderId, brokerKey) {
        try {
            const response = await fetch(`/api/manual/orders/${encodeURIComponent(orderId)}/cancel`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ broker_key: brokerKey })
            });
            const result = await response.json();
            if (result.success) {
                this.refreshAll();
            } else {
                console.error('Cancel failed:', result.message);
                alert('Failed to cancel order: ' + result.message);
            }
        } catch (error) {
            console.error('Cancel order error:', error);
        }
    }

    /**
     * Close a position (filled exposure only) via REST API.
     */
    async closePosition(symbol, brokerKey) {
        try {
            const response = await fetch(`/api/manual/positions/${encodeURIComponent(symbol)}/close`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ broker_key: brokerKey })
            });
            const result = await response.json();
            if (result.success) {
                this.refreshAll();
            } else {
                console.error('Close position failed:', result.message);
                alert('Failed to close position: ' + result.message);
            }
        } catch (error) {
            console.error('Close position error:', error);
        }
    }

    /**
     * Cancel all resting orders for a symbol (explicit user action).
     */
    async cancelOrdersForSymbol(symbol, brokerKey) {
        try {
            const response = await fetch(`/api/manual/orders/symbol/${encodeURIComponent(symbol)}/cancel`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ broker_key: brokerKey })
            });
            const result = await response.json();
            if (result.success) {
                this.refreshAll();
            } else {
                console.error('Cancel orders failed:', result.message);
            }
        } catch (error) {
            console.error('Cancel orders error:', error);
        }
    }

    // ============ Broker Status ============

    /**
     * Get current broker key based on form selection.
     */
    _getCurrentBrokerKey() {
        if (!this.targetSelect) return 'paper';
        const target = this.targetSelect.value;
        if (target === 'test_exchange' || target === 'paper') return 'paper';

        const testnet = this.testnetCheckbox?.checked ?? true;
        return `${target}_${testnet ? 'testnet' : 'production'}`;
    }

    /**
     * Update broker status bar display.
     */
    async updateBrokerStatus() {
        const brokerKey = this._getCurrentBrokerKey();

        try {
            const response = await fetch(`/api/manual/balance?broker_key=${encodeURIComponent(brokerKey)}`);
            const data = await response.json();
            if (data.success) {
                const balanceEl = document.getElementById('brokerBalance');
                const modeEl = document.getElementById('brokerModeIndicator');

                if (balanceEl) {
                    const balance = data.available ?? data.total ?? 0;
                    balanceEl.textContent = `Available: $${balance.toFixed(2)}`;
                }
                if (modeEl) {
                    if (brokerKey === 'paper') {
                        modeEl.textContent = 'PAPER';
                        modeEl.className = 'mode-badge mode-paper';
                    } else if (brokerKey.includes('testnet')) {
                        modeEl.textContent = 'TESTNET';
                        modeEl.className = 'mode-badge mode-testnet';
                    } else {
                        modeEl.textContent = 'LIVE';
                        modeEl.className = 'mode-badge mode-live';
                    }
                }
            }
        } catch (e) {
            console.warn('Could not fetch balance:', e);
        }
    }

    // ============ Broker-Aware SELL Disable ============

    /**
     * Check if position exists for symbol and broker.
     */
    async _checkPositionExists(symbol, brokerKey) {
        try {
            const response = await fetch('/api/manual/positions');
            const data = await response.json();
            if (data.success && data.positions) {
                return data.positions.some(p =>
                    p.symbol === symbol &&
                    p.broker_key === brokerKey &&
                    (p.size || 0) > 0
                );
            }
        } catch (e) {
            console.warn('Could not check position:', e);
        }
        return false;
    }

    /**
     * Update SELL option availability based on position.
     * If SELL is currently selected but becomes invalid, reset to BUY.
     */
    async _updateSellAvailability() {
        if (!this.sideSelect || !this.symbolInput) return;

        const symbol = this.symbolInput.value;
        const brokerKey = this._getCurrentBrokerKey();

        const hasPosition = await this._checkPositionExists(symbol, brokerKey);
        const sellOption = this.sideSelect.querySelector('option[value="SELL"]');

        if (sellOption) {
            sellOption.disabled = !hasPosition;
            sellOption.title = hasPosition ? '' : 'No position to sell. Buy first.';

            // If SELL is currently selected but no longer valid, reset to BUY
            if (!hasPosition && this.sideSelect.value === 'SELL') {
                this.sideSelect.value = 'BUY';
            }
        }
    }
}


/**
 * TradeDataManager - Manages in-memory trade data store
 */
class TradeDataManager {
    constructor() {
        this.trades = [];
    }

    /**
     * Fetches trades from the server.
     * @param {Object} comms - The communications instance.
     * @param {Object} data - An object containing user data.
     */
    fetchTrades(comms, data) {
        if (comms) {
            try {
                const requestData = {
                    request: 'trades',
                    user_name: data?.user_name
                };
                comms.sendToApp('request', requestData);
            } catch (error) {
                console.error("Error fetching trades:", error.message);
            }
        } else {
            throw new Error('Communications instance not available.');
        }
    }

    /**
     * Adds a new trade to the local store.
     * @param {Object} data - The trade data.
     */
    addTrade(data) {
        const tradeData = data.trade || data;
        console.log("Adding new trade:", tradeData);

        if (!tradeData.unique_id && !tradeData.tbl_key) {
            console.error("Trade data missing identifier:", tradeData);
            return;
        }

        // Check for duplicates
        const id = tradeData.unique_id || tradeData.tbl_key;
        const exists = this.trades.find(t => t.unique_id === id || t.tbl_key === id);
        if (!exists) {
            this.trades.push(tradeData);
        }
    }

    /**
     * Retrieves a trade by its ID.
     * @param {string} tradeId - The trade ID.
     * @returns {Object|null} - The trade object or null.
     */
    getTradeById(tradeId) {
        return this.trades.find(t => t.unique_id === tradeId || t.tbl_key === tradeId) || null;
    }

    /**
     * Updates trade data (including P/L updates).
     * @param {Object} updateData - The updated trade data.
     */
    updateTrade(updateData) {
        const tradeId = updateData.id || updateData.unique_id || updateData.tbl_key;
        if (!tradeId) return;

        const trade = this.getTradeById(tradeId);
        if (trade) {
            // Update stats
            if (updateData.pl !== undefined) {
                trade.stats = trade.stats || {};
                trade.stats.profit = updateData.pl;
            }
            if (updateData.pl_pct !== undefined) {
                trade.stats = trade.stats || {};
                trade.stats.profit_pct = updateData.pl_pct;
            }
            if (updateData.status) {
                trade.status = updateData.status;
            }
        }
    }

    /**
     * Removes a trade from the store.
     * @param {string} tradeId - The trade ID.
     */
    removeTrade(tradeId) {
        console.log(`Removing trade: ${tradeId}`);
        this.trades = this.trades.filter(
            t => t.unique_id !== tradeId && t.tbl_key !== tradeId
        );
    }

    /**
     * Returns all trades.
     * @returns {Object[]} - The list of trades.
     */
    getAllTrades() {
        return this.trades;
    }

    /**
     * Sets all trades (used when loading from server).
     * @param {Object[]} trades - The list of trades.
     */
    setTrades(trades) {
        this.trades = Array.isArray(trades) ? trades : [];
    }

    /**
     * Applies batch P/L updates from server.
     * @param {Object[]} updates - Array of trade update objects.
     */
    applyUpdates(updates) {
        if (!Array.isArray(updates)) return;

        for (const update of updates) {
            this.updateTrade(update);
        }
    }

    /**
     * Gets trade statistics.
     * @returns {Object} - Statistics object.
     */
    getStatistics() {
        const totalTrades = this.trades.length;
        const paperTrades = this.trades.filter(t => t.is_paper).length;
        const liveTrades = totalTrades - paperTrades;

        let totalPL = 0;
        for (const trade of this.trades) {
            totalPL += (trade.stats?.profit || 0);
        }

        return {
            totalTrades,
            paperTrades,
            liveTrades,
            totalPL
        };
    }
}


/**
 * Trade - Main coordinator class that manages TradeUIManager, TradeDataManager, and SocketIO communication
 */
class Trade {
    constructor(ui = null) {
        this.ui = ui;
        this.comms = null;
        this.data = null;

        this.dataManager = new TradeDataManager();
        this.uiManager = new TradeUIManager();

        // Set up close callback
        this.uiManager.registerCloseTradeCallback(this.closeTrade.bind(this));

        // Bind methods
        this.submitNewTrade = this.submitNewTrade.bind(this);

        this._initialized = false;
    }

    /**
     * Initializes the Trade instance.
     * Called after page load when UI.data is available.
     * @param {Object} config - Configuration object.
     */
    initialize(config = {}) {
        try {
            // Get references from global UI if not provided in constructor
            if (!this.ui && window.UI) {
                this.ui = window.UI;
            }
            this.data = this.ui?.data || window.UI?.data;
            this.comms = this.data?.comms;

            this.uiManager.initUI(config);

            if (!this.comms) {
                console.error("Communications instance not available.");
                return;
            }

            // Register handlers with Comms
            this.comms.on('trades', this.handleTradesResponse.bind(this));
            this.comms.on('trade_created', this.handleTradeCreated.bind(this));
            this.comms.on('trade_closed', this.handleTradeClosed.bind(this));
            this.comms.on('trade_error', this.handleTradeError.bind(this));
            this.comms.on('updates', this.handleUpdates.bind(this));
            this.comms.on('trade_update', this.handleTradeUpdate.bind(this));

            // Set initial price if available
            if (this.data?.price_history && this.data.price_history.length > 0) {
                const lastPrice = this.data.price_history[this.data.price_history.length - 1].close;
                this.uiManager.updateCurrentPrice(lastPrice);
            }

            // Update trading pair display
            this._updateTradingPairDisplay();

            // Fetch existing trades (legacy path)
            this.dataManager.fetchTrades(this.comms, this.data);

            // Initialize broker event listeners and refresh broker UI
            this.initBrokerListeners(this.comms);
            this.refreshAll();

            this._initialized = true;
            console.log("Trade module initialized successfully");
        } catch (error) {
            console.error("Error initializing Trade:", error);
        }
    }

    /**
     * Updates the trading pair display in the form.
     * @private
     */
    _updateTradingPairDisplay() {
        const symbolDisplay = document.getElementById('trade_symbol_display');
        if (symbolDisplay && this.data?.trading_pair) {
            symbolDisplay.textContent = this.data.trading_pair;
        }
    }

    /**
     * Handle initial trades list response from server.
     * @param {Array} data - List of trade objects.
     */
    handleTradesResponse(data) {
        console.log("Received trades list:", data);
        if (Array.isArray(data)) {
            this.dataManager.setTrades(data);
            this.uiManager.updateTradesHtml(this.dataManager.getAllTrades());
            this._updateStatistics();
        }
    }

    /**
     * Handle new trade created event.
     * @param {Object} data - Server response with trade data.
     */
    handleTradeCreated(data) {
        console.log("Trade created:", data);
        if (data.success) {
            this.dataManager.addTrade(data);
            this.uiManager.updateTradesHtml(this.dataManager.getAllTrades());
            this._updateStatistics();
            // Also refresh the new broker UI panels (Orders, Positions, History)
            this.refreshAll();
        } else {
            alert(`Failed to create trade: ${data.message}`);
        }
    }

    /**
     * Handle trade closed event.
     * @param {Object} data - Server response with closed trade info.
     */
    handleTradeClosed(data) {
        console.log("Trade closed:", data);
        if (data.success) {
            const tradeId = data.trade_id;
            this.dataManager.removeTrade(tradeId);
            this.uiManager.removeTradeCard(tradeId);
            this._updateStatistics();
            // Also refresh the new broker UI panels
            this.refreshAll();

            // Show P/L notification
            if (data.final_pl !== undefined) {
                const plText = data.final_pl >= 0
                    ? `+$${data.final_pl.toFixed(2)}`
                    : `-$${Math.abs(data.final_pl).toFixed(2)}`;
                console.log(`Trade closed with P/L: ${plText}`);
            }
        }
    }

    /**
     * Handle trade error.
     * @param {Object} data - Error data.
     */
    handleTradeError(data) {
        console.error("Trade error:", data.message);
        alert(`Trade error: ${data.message}`);
    }

    /**
     * Handle updates (including trade P/L updates).
     * @param {Object} data - Update data from server.
     */
    handleUpdates(data) {
        const { trade_updts } = data;
        if (trade_updts && Array.isArray(trade_updts)) {
            this.dataManager.applyUpdates(trade_updts);

            // Update UI for each trade
            for (const update of trade_updts) {
                const tradeId = update.id;
                if (update.pl !== undefined && update.pl_pct !== undefined) {
                    this.uiManager.updateTradePL(tradeId, update.pl, update.pl_pct);
                }
            }

            this._updateStatistics();
        }
    }

    /**
     * Handle individual trade update from execution loop.
     * @param {Object} data - Single trade update data from server.
     */
    handleTradeUpdate(data) {
        console.log('Trade update event received:', data);
        if (data && data.id) {
            // Update the trade in data manager
            this.dataManager.applyUpdates([data]);

            // Update legacy trade card UI
            if (data.pl !== undefined && data.pl_pct !== undefined) {
                this.uiManager.updateTradePL(data.id, data.pl, data.pl_pct);
            }

            // Also update position cards (for filled positions showing unrealized P/L)
            // Match by symbol + broker_key to avoid cross-broker contamination
            if (data.symbol && (data.pl !== undefined || data.current_price !== undefined)) {
                this._updatePositionPL(data.symbol, data.broker_key, data.pl, data.current_price);
            }

            this._updateStatistics();
        }
    }

    /**
     * Update P/L display in position cards for a given symbol + broker.
     * @param {string} symbol - The trading symbol.
     * @param {string} brokerKey - The broker key ('paper' or 'exchange_mode').
     * @param {number} pl - The unrealized P/L.
     * @param {number} currentPrice - The current price.
     */
    _updatePositionPL(symbol, brokerKey, pl, currentPrice) {
        const container = document.getElementById('positionsContainer');
        if (!container) return;

        // Find position card matching this symbol AND broker_key
        const cards = container.querySelectorAll('.position-card');
        for (const card of cards) {
            const symbolEl = card.querySelector('.position-symbol');
            const brokerEl = card.querySelector('.position-broker');

            // Match both symbol and broker_key to avoid cross-broker contamination
            const symbolMatch = symbolEl && symbolEl.textContent === symbol;
            const brokerMatch = !brokerKey || (brokerEl && brokerEl.textContent === brokerKey);

            if (symbolMatch && brokerMatch) {
                const plEl = card.querySelector('.position-pl');
                if (plEl && pl !== undefined) {
                    const plClass = pl >= 0 ? 'positive' : 'negative';
                    const plSign = pl >= 0 ? '+' : '';
                    plEl.textContent = `${plSign}${pl.toFixed(2)}`;
                    plEl.className = `position-pl ${plClass}`;
                    // Flash animation
                    plEl.classList.add('trade-pl-flash');
                    setTimeout(() => plEl.classList.remove('trade-pl-flash'), 300);
                }
            }
        }
    }

    // ================ Form Methods ================

    /**
     * Opens the trade creation form.
     */
    async open_tradeForm() {
        // Get current price if available
        let currentPrice = null;
        if (this.data?.price_history && this.data.price_history.length > 0) {
            currentPrice = this.data.price_history[this.data.price_history.length - 1].close;
        }

        // Get symbol from chart
        const symbol = this.data?.trading_pair || '';

        // Get current chart view exchange
        const chartExchange = this.data?.exchange || 'binance';

        // Get connected exchanges from UI.exchanges
        const connectedExchanges = window.UI?.exchanges?.connected_exchanges || [];

        await this.uiManager.displayForm(currentPrice, symbol, connectedExchanges, chartExchange);
    }

    /**
     * Sets the symbol dropdown to the current chart symbol.
     */
    async useChartSymbol() {
        if (this.uiManager.symbolInput && this.data?.trading_pair) {
            const chartExchange = this.data?.exchange || 'binance';
            // Re-populate dropdown with chart symbol at top
            await this.uiManager._populateSymbolDropdown(chartExchange, this.data.trading_pair);
        }
    }

    /**
     * Closes the trade form.
     */
    close_tradeForm() {
        this.uiManager.hideForm();
    }

    /**
     * Submits a new trade.
     */
    submitNewTrade() {
        if (!this.comms) {
            console.error("Comms instance not available.");
            return;
        }

        const formElement = this.uiManager.formElement;
        if (!formElement) {
            console.error("Form element not available.");
            return;
        }

        const target = this.uiManager.targetSelect?.value || 'test_exchange';
        const symbol = this.uiManager.symbolInput?.value || this.data?.trading_pair || '';
        const orderType = this.uiManager.orderTypeSelect?.value || 'MARKET';
        const side = this.uiManager.sideSelect?.value || 'buy';
        const exchange = this.uiManager.exchangeSelect?.value || this.data?.exchange || 'binance';

        // Get testnet setting (only relevant for live exchanges)
        const isPaperTrade = target === 'test_exchange';
        const testnet = isPaperTrade ? false : (this.uiManager.testnetCheckbox?.checked ?? true);

        let price;
        if (orderType === 'MARKET') {
            price = parseFloat(this.uiManager.currentPriceDisplay?.value || 0);
        } else {
            price = parseFloat(this.uiManager.priceInput?.value || 0);
        }

        const quantity = parseFloat(this.uiManager.qtyInput?.value || 0);

        // Get SL/TP and TIF
        const stopLossVal = this.uiManager.stopLossInput?.value;
        const takeProfitVal = this.uiManager.takeProfitInput?.value;
        const stopLoss = stopLossVal ? parseFloat(stopLossVal) : null;
        const takeProfit = takeProfitVal ? parseFloat(takeProfitVal) : null;
        const timeInForce = this.uiManager.timeInForceSelect?.value || 'GTC';

        // Validation
        if (!symbol) {
            alert('Please enter a trading pair.');
            return;
        }
        if (quantity <= 0) {
            alert('Please enter a valid quantity.');
            return;
        }
        if (orderType === 'LIMIT' && price <= 0) {
            alert('Please enter a valid price for limit orders.');
            return;
        }

        // SL/TP validation
        if (side.toUpperCase() === 'BUY') {
            if (stopLoss && stopLoss >= price) {
                alert('Stop Loss must be below entry price for BUY orders.');
                return;
            }
            if (takeProfit && takeProfit <= price) {
                alert('Take Profit must be above entry price for BUY orders.');
                return;
            }
        } else {
            // SELL
            if (stopLoss && stopLoss <= price) {
                alert('Stop Loss must be above entry price for SELL orders.');
                return;
            }
            if (takeProfit && takeProfit >= price) {
                alert('Take Profit must be below entry price for SELL orders.');
                return;
            }
        }

        // Show confirmation for production live trades
        if (!isPaperTrade && !testnet) {
            const proceed = confirm(
                "WARNING: PRODUCTION MODE\n\n" +
                "You are about to execute a LIVE trade with REAL MONEY.\n\n" +
                `Exchange: ${target}\n` +
                `Symbol: ${symbol}\n` +
                `Side: ${side.toUpperCase()}\n` +
                `Quantity: ${quantity}\n\n` +
                "Are you sure you want to proceed?"
            );
            if (!proceed) {
                return;
            }
        }

        const tradeData = {
            target,
            exchange,
            symbol,
            price,
            side,
            orderType,
            quantity,
            testnet,
            stopLoss,
            takeProfit,
            timeInForce,
            user_name: this.data?.user_name
        };

        console.log("Submitting trade:", tradeData);
        this.comms.sendToApp('new_trade', tradeData);
        this.close_tradeForm();
    }

    /**
     * Closes a trade.
     * @param {string} tradeId - The trade ID.
     */
    closeTrade(tradeId) {
        if (!this.comms) {
            console.error("Comms instance not available.");
            return;
        }

        console.log(`Closing trade: ${tradeId}`);
        this.comms.sendToApp('close_trade', { trade_id: tradeId });
    }

    /**
     * Fetches trades from server.
     */
    fetchTrades() {
        this.dataManager.fetchTrades(this.comms, this.data);
    }

    /**
     * Updates the statistics panel with trade data.
     * @private
     */
    _updateStatistics() {
        const stats = this.dataManager.getStatistics();

        // Update statistics panel if available
        const activeTradesEl = document.getElementById('stat_active_trades');
        const totalPLEl = document.getElementById('stat_trades_pl');
        const paperCountEl = document.getElementById('stat_paper_trades');
        const liveCountEl = document.getElementById('stat_live_trades');

        if (activeTradesEl) {
            activeTradesEl.textContent = stats.totalTrades;
        }
        if (totalPLEl) {
            const plClass = stats.totalPL >= 0 ? 'positive' : 'negative';
            totalPLEl.className = `stat-value ${plClass}`;
            totalPLEl.textContent = stats.totalPL >= 0
                ? `+$${stats.totalPL.toFixed(2)}`
                : `-$${Math.abs(stats.totalPL).toFixed(2)}`;
        }
        if (paperCountEl) {
            paperCountEl.textContent = stats.paperTrades;
        }
        if (liveCountEl) {
            liveCountEl.textContent = stats.liveTrades;
        }
    }

    // ================ Legacy Methods (for backwards compatibility) ================

    /**
     * Legacy method: Connect elements (calls initUI).
     */
    connectElements(config = {}) {
        this.uiManager.initUI({
            priceId: config.price || 'price',
            currentPriceId: config.currentPrice || 'currentPrice',
            qtyId: config.quantity || 'quantity',
            tradeValueId: config.tradeValue || 'tradeValue',
            orderTypeId: config.orderType || 'orderType',
            tradeTargetId: config.target || 'tradeTarget',
            sideId: config.side || 'side',
            formElId: config.ntf || 'new_trade_form',
            targetId: config.atl || 'tradesContainer'
        });
    }

    /**
     * Legacy method: Set data (handles trades response).
     * @param {Array} trades - List of trades.
     */
    set_data(trades) {
        this.handleTradesResponse(trades);
    }

    /**
     * Legacy method: Update received (handles updates).
     * @param {Array} trade_updts - Trade updates.
     */
    update_received(trade_updts) {
        this.handleUpdates({ trade_updts });
    }

    /**
     * Legacy: Open trade details form.
     */
    open_tradeDetails_Form() {
        const el = document.getElementById("trade_details_form");
        if (el) el.style.display = "grid";
    }

    /**
     * Legacy: Close trade details form.
     */
    close_tradeDetails_Form() {
        const el = document.getElementById("trade_details_form");
        if (el) el.style.display = "none";
    }

    /**
     * Gets all trades.
     * @returns {Object[]} - The list of trades.
     */
    get trades() {
        return this.dataManager.getAllTrades();
    }
}
