from PyQt6.QtWidgets import (
    QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
    QPushButton, QLineEdit, QTabWidget, QGridLayout, QFrame,
    QTableWidget, QTableWidgetItem, QProgressBar, QStatusBar,
    QHeaderView, QSplitter, QApplication
)
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QObject, QSize
from PyQt6.QtGui import QPalette, QColor
import pyqtgraph as pg
import numpy as np
from datetime import datetime
from typing import Dict, List, Any, Optional
import logging
from queue import Queue
import pandas as pd
import os
import sys
from .token_scanner import TokenScanner
import asyncio
from .config import config

class DarkTheme:
    """Professional dark theme color scheme"""
    BACKGROUND = "#1C1C1C"
    DARKER_BACKGROUND = "#141414"
    LIGHTER_BACKGROUND = "#2A2A2A"
    TEXT_PRIMARY = "#E0E0E0"
    TEXT_SECONDARY = "#A0A0A0"
    ACCENT_BLUE = "#2196F3"
    ACCENT_GREEN = "#4CAF50"
    ACCENT_RED = "#F44336"
    ACCENT_YELLOW = "#FFD700"
    CHART_BACKGROUND = "#1C1C1C"
    GRID_COLOR = "#323232"
    PRICE_LINE = "#00BCD4"
    VOLUME_BAR = "#2196F3"
    SUCCESS = "#43A047"
    WARNING = "#FFA000"
    ERROR = "#D32F2F"
    TABLE_HEADER = "#252525"
    TABLE_ALTERNATE = "#202020"

    @staticmethod
    def get_stylesheet():
        return f"""
            QMainWindow {{
                background-color: {DarkTheme.BACKGROUND};
                color: {DarkTheme.TEXT_PRIMARY};
            }}
            QLabel {{
                color: {DarkTheme.TEXT_PRIMARY};
                font-size: 12px;
            }}
            QLineEdit {{
                background-color: {DarkTheme.DARKER_BACKGROUND};
                border: 1px solid {DarkTheme.LIGHTER_BACKGROUND};
                border-radius: 3px;
                padding: 5px;
                color: {DarkTheme.TEXT_PRIMARY};
                font-size: 12px;
            }}
            QPushButton {{
                background-color: {DarkTheme.ACCENT_BLUE};
                color: {DarkTheme.TEXT_PRIMARY};
                border: none;
                border-radius: 3px;
                padding: 8px;
                font-size: 12px;
                font-weight: bold;
            }}
            QPushButton:hover {{
                background-color: #1E88E5;
            }}
            QPushButton:pressed {{
                background-color: #1976D2;
            }}
            QTableWidget {{
                background-color: {DarkTheme.BACKGROUND};
                alternate-background-color: {DarkTheme.TABLE_ALTERNATE};
                color: {DarkTheme.TEXT_PRIMARY};
                gridline-color: {DarkTheme.GRID_COLOR};
                font-size: 12px;
            }}
            QHeaderView::section {{
                background-color: {DarkTheme.TABLE_HEADER};
                color: {DarkTheme.TEXT_PRIMARY};
                padding: 5px;
                border: none;
                font-weight: bold;
            }}
            QTabWidget::pane {{
                border: 1px solid {DarkTheme.LIGHTER_BACKGROUND};
                background: {DarkTheme.BACKGROUND};
            }}
            QTabBar::tab {{
                background: {DarkTheme.DARKER_BACKGROUND};
                color: {DarkTheme.TEXT_PRIMARY};
                padding: 8px 12px;
                margin-right: 2px;
            }}
            QTabBar::tab:selected {{
                background: {DarkTheme.ACCENT_BLUE};
            }}
            QProgressBar {{
                border: 1px solid {DarkTheme.LIGHTER_BACKGROUND};
                border-radius: 2px;
                text-align: center;
                background-color: {DarkTheme.DARKER_BACKGROUND};
            }}
            QProgressBar::chunk {{
                background-color: {DarkTheme.ACCENT_BLUE};
            }}
            QStatusBar {{
                background-color: {DarkTheme.DARKER_BACKGROUND};
                color: {DarkTheme.TEXT_PRIMARY};
            }}
            QFrame {{
                background-color: {DarkTheme.BACKGROUND};
                border: 1px solid {DarkTheme.LIGHTER_BACKGROUND};
                border-radius: 3px;
            }}
        """

class QuantumGUI(QMainWindow):
    """Professional Quantum Trading Interface"""
    # Signals
    balance_updated = pyqtSignal(float)
    price_updated = pyqtSignal(float)
    volume_updated = pyqtSignal(float)
    trade_executed = pyqtSignal(str)
    error_occurred = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.config = config
        self.setWindowTitle("Quantum Trading Engine")
        self.setGeometry(100, 100, 1920, 1080)

        # Initialize state
        self.price_history = []
        self.volume_history = []
        self.trades = []

        # Setup UI
        self._init_ui()
        self._setup_update_handler()
        self._setup_timers()

        # Apply theme
        self.setStyleSheet(DarkTheme.get_stylesheet())
        self.statusBar().showMessage("System Ready")
        logging.info("Quantum GUI initialized")

    def _init_ui(self):
        """Initialize the main UI layout"""
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        main_layout = QHBoxLayout(self.central_widget)
        h_splitter = QSplitter(Qt.Orientation.Horizontal)
        h_splitter.addWidget(self._create_left_panel())
        h_splitter.addWidget(self._create_center_panel())
        h_splitter.addWidget(self._create_right_panel())
        h_splitter.setSizes([300, 1000, 300])
        main_layout.addWidget(h_splitter)

    def _setup_update_handler(self):
        """Initialize the update handler"""
        self.update_handler = GuiUpdateHandler(self)
        self.connect_trade_handlers()
        self.connect_wallet_signals()

    def _setup_timers(self):
        """Initialize update timers"""
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self._update_displays)
        self.update_timer.start(1000)  # 1 second updates

    def _create_section(self, title: str) -> tuple[QFrame, QVBoxLayout]:
        """Create a styled section with title"""
        section = QFrame()
        section.setFrameStyle(QFrame.Shape.StyledPanel)
        section.setStyleSheet(f"""
            QFrame {{
                background-color: {DarkTheme.DARKER_BACKGROUND};
                border: 1px solid {DarkTheme.LIGHTER_BACKGROUND};
                border-radius: 5px;
                margin: 5px;
            }}
        """)
        layout = QVBoxLayout()
        if title:
            header = QLabel(title)
            header.setStyleSheet(f"""
                font-weight: bold;
                color: {DarkTheme.TEXT_PRIMARY};
                font-size: 13px;
            """)
            layout.addWidget(header)
        section.setLayout(layout)
        return section, layout

    def _create_center_panel(self):
        """Create the center panel with charts"""
        panel = QFrame()
        layout = QVBoxLayout(panel)

        charts_tabs = QTabWidget()
        self.price_chart, self.price_line = self._create_chart("Price", DarkTheme.PRICE_LINE)
        charts_tabs.addTab(self.price_chart, "Price")
        
        self.volume_chart, self.volume_bar = self._create_volume_chart()
        charts_tabs.addTab(self.volume_chart, "Volume")
        
        self.indicators_chart, self.rsi_line, self.macd_line, self.signal_line = self._create_indicators_chart()
        charts_tabs.addTab(self.indicators_chart, "Indicators")

        layout.addWidget(charts_tabs)

        signals_frame, signals_layout = self._create_section("Trading Signals")
        signals_layout.addLayout(self._create_signals_layout())
        layout.addWidget(signals_frame)

        return panel

    def _create_volume_chart(self):
        """Create volume chart"""
        chart = pg.PlotWidget(title="Volume")
        chart.setBackground(DarkTheme.CHART_BACKGROUND)
        chart.showGrid(x=True, y=True, alpha=0.2)
        chart.getAxis('bottom').setPen(pg.mkPen(DarkTheme.TEXT_SECONDARY))
        chart.getAxis('left').setPen(pg.mkPen(DarkTheme.TEXT_SECONDARY))
    
        bar = pg.BarGraphItem(x=[], height=[], width=0.8, brush=DarkTheme.VOLUME_BAR)
        chart.addItem(bar)
        return chart, bar

    def _create_indicators_chart(self):
        """Create indicators chart"""
        chart = pg.PlotWidget(title="Technical Indicators")
        chart.setBackground(DarkTheme.CHART_BACKGROUND)
        chart.showGrid(x=True, y=True, alpha=0.2)
        chart.getAxis('bottom').setPen(pg.mkPen(DarkTheme.TEXT_SECONDARY))
        chart.getAxis('left').setPen(pg.mkPen(DarkTheme.TEXT_SECONDARY))
    
        rsi_line = chart.plot(pen=pg.mkPen(DarkTheme.ACCENT_YELLOW, width=2))
        macd_line = chart.plot(pen=pg.mkPen(DarkTheme.ACCENT_BLUE, width=2))
        signal_line = chart.plot(pen=pg.mkPen(DarkTheme.ACCENT_RED, width=2))
        return chart, rsi_line, macd_line, signal_line

    def _create_signals_layout(self):
        """Create Trading Signals layout"""
        grid_layout = QGridLayout()
        self.signal_indicators = {
            "strength": self._create_progress_bar(),
            "direction": self._create_direction_label(),
            "confidence": self._create_progress_bar(),
        }
        grid_layout.addWidget(QLabel("Signal Strength:"), 0, 0)
        grid_layout.addWidget(self.signal_indicators["strength"], 0, 1)
        grid_layout.addWidget(QLabel("Direction:"), 1, 0)
        grid_layout.addWidget(self.signal_indicators["direction"], 1, 1)
        grid_layout.addWidget(QLabel("AI Confidence:"), 2, 0)
        grid_layout.addWidget(self.signal_indicators["confidence"], 2, 1)
        return grid_layout

    def _create_right_panel(self):
        """Create the right panel with positions and trades"""
        panel = QFrame()
        layout = QVBoxLayout(panel)

        # Increase row height and padding for better text visibility
        positions_frame, positions_layout = self._create_section("Active Positions")
        self.positions_table = self._create_table(
            headers=["Token", "Size", "Entry", "PnL"],
            column_widths=[150, 100, 100, 100],
            row_height=30  # Increased row height
        )
        positions_layout.addWidget(self.positions_table)
        layout.addWidget(positions_frame)

        trades_frame, trades_layout = self._create_section("Trade History")
        self.trades_table = self._create_table(
        headers=["Time", "Token", "Side", "Size", "PnL"],
        column_widths=[150, 150, 80, 100, 100],
        row_height=30  # Increased row height
        )
        trades_layout.addWidget(self.trades_table)
        layout.addWidget(trades_frame)

        # Add padding at the bottom
        layout.addSpacing(20)
    
        return panel

    def _create_left_panel(self):
        """Create the left control panel"""
        panel = QFrame()
        main_layout = QVBoxLayout(panel)
        main_layout.setSpacing(10)

        # Wallet Section
        wallet_frame = self._init_wallet_section()
        main_layout.addWidget(wallet_frame)

        # Trading Controls
        controls_frame, controls_layout = self._create_section("Trading Controls")
        controls_layout.addLayout(self._create_trade_controls_layout())
        main_layout.addWidget(controls_frame)

        # Status Indicators
        status_frame, status_layout = self._create_section("Market Status")
        status_layout.addLayout(self._create_status_labels_layout())
        main_layout.addWidget(status_frame)

        # Auto-Trading Controls
        auto_frame, auto_layout = self._create_section("Automated Trading")
        auto_layout.addWidget(self._create_auto_trade_button())
        main_layout.addWidget(auto_frame)

        main_layout.addStretch()
        return panel

    def _create_trade_controls_layout(self) -> QGridLayout:
        """Create layout for trading controls"""
        grid_layout = QGridLayout()
        self.token_input = QLineEdit()
        self.token_input.setPlaceholderText("Token Address")
        self.amount_input = QLineEdit()
        self.amount_input.setPlaceholderText("Amount (SOL)")
        
        self.buy_button = QPushButton("BUY")
        self.sell_button = QPushButton("SELL")
        self._setup_trade_buttons()

        grid_layout.addWidget(QLabel("Token:"), 0, 0)
        grid_layout.addWidget(self.token_input, 0, 1)
        grid_layout.addWidget(QLabel("Amount:"), 1, 0)
        grid_layout.addWidget(self.amount_input, 1, 1)
        grid_layout.addWidget(self.buy_button, 2, 0)
        grid_layout.addWidget(self.sell_button, 2, 1)
        return grid_layout

    def _setup_trade_buttons(self):
        """Setup the trade buttons"""
        self.buy_button.setStyleSheet(f"""
            QPushButton {{
                background-color: {DarkTheme.ACCENT_GREEN};
                min-height: 30px;
            }}
            QPushButton:hover {{
                background-color: {DarkTheme.SUCCESS};
            }}
        """)
        self.sell_button.setStyleSheet(f"""
            QPushButton {{
                background-color: {DarkTheme.ACCENT_RED};
                min-height: 30px;
            }}
            QPushButton:hover {{
                background-color: {DarkTheme.ERROR};
            }}
        """)

    def _create_status_labels_layout(self) -> QGridLayout:
        """Create layout for status indicators"""
        grid_layout = QGridLayout()
        self.status_labels = {
            "price": QLabel("Price: $0.00"),
            "volume": QLabel("Volume: $0"),
            "trades": QLabel("Trades: 0"),
            "win_rate": QLabel("Win Rate: 0%"),
            "pnl": QLabel("PnL: $0.00"),
            "liquidity": QLabel("Liquidity: $0"),
            "buyer_ratio": QLabel("Buy Ratio: 50%"),
            "lp_locked": QLabel("LP Locked: 0%"),
        }
        for i, label in enumerate(self.status_labels.values()):
            label.setStyleSheet(f"color: {DarkTheme.TEXT_PRIMARY}; font-size: 12px;")
            grid_layout.addWidget(label, i, 0)
        return grid_layout

    def _create_auto_trade_button(self):
        """Create the auto trading button"""
        auto_layout = QVBoxLayout()
    
        self.auto_trade_button = QPushButton("Start Auto-Trading")
        self.auto_trade_button.setCheckable(True)
        self.auto_trade_button.setStyleSheet(f"""
            QPushButton {{
                background-color: {DarkTheme.ACCENT_BLUE};
                min-height: 35px;
            }}
            QPushButton:checked {{
                background-color: {DarkTheme.SUCCESS};
            }}
        """)
    
        self.stop_button = QPushButton("Emergency Stop")
        self.stop_button.setStyleSheet(f"""
            QPushButton {{
                background-color: {DarkTheme.ERROR};
                min-height: 35px;
            }}
            QPushButton:hover {{
                background-color: {DarkTheme.ACCENT_RED};
            }}
        """)
    
        auto_layout.addWidget(self.auto_trade_button)
        auto_layout.addWidget(self.stop_button)
    
        container = QWidget()
        container.setLayout(auto_layout)
        return container
    def update_real_time_data(self):
        """Update real-time data displays"""
        try:
            # Update price chart
            self.price_line.setData(self.price_history[-1000:])
        
            # Update volume chart
            if self.volume_history:
                x = np.arange(len(self.volume_history))
                self.volume_bar.setOpts(x=x, height=self.volume_history)
        
            # Update signal strength
            if hasattr(self, 'signal_indicators'):
                current_signal = self.signals.get_current_signals_sync()
                strength = int(current_signal.get('confidence', 0) * 100)
                self.signal_indicators["strength"].setValue(strength)
            
                # Update direction indicator
                direction = current_signal.get('direction', 0)
                direction_text = "BUY" if direction > 0 else "SELL" if direction < 0 else "NEUTRAL"
                self.signal_indicators["direction"].setText(direction_text)
            
            # Trigger technical indicators update
            self._update_indicators_chart()
        
        except Exception as e:
            logging.error(f"Real-time update error: {e}")

    def _update_indicators_chart(self):
        """Update technical indicators chart with real data"""
        try:
            if len(self.price_history) >= 14:
                price_array = np.array(self.price_history)
            
                # Calculate RSI
                delta = np.diff(price_array)
                gains = np.where(delta > 0, delta, 0)
                losses = np.where(delta < 0, -delta, 0)
            
                avg_gain = np.mean(gains[-14:])
                avg_loss = np.mean(losses[-14:])
                rs = avg_gain / avg_loss if avg_loss != 0 else 0
                rsi = 100 - (100 / (1 + rs))
            
                # Calculate MACD
                ema12 = self._calculate_ema(price_array, 12)
                ema26 = self._calculate_ema(price_array, 26)
                macd = ema12 - ema26
                signal = self._calculate_ema(macd, 9)
            
                # Update indicator plots
                x = np.arange(len(price_array))
                self.rsi_line.setData(x=x, y=[rsi] * len(price_array))
                self.macd_line.setData(x=x, y=macd)
                self.signal_line.setData(x=x, y=signal)
            
        except Exception as e:
            logging.error(f"Indicators update error: {e}")

    def connect_signals(self, signals: Dict[str, Any]):
        """Connect all trading signals"""
        try:
            # Connect market data updates
            if "market_data" in signals:
                signals["market_data"].connect(self._update_market_data)
                self.update_timer = QTimer()
                self.update_timer.timeout.connect(self.update_real_time_data)
                self.update_timer.start(100)  # 10 Hz updates
        
            # Connect trade execution signals
            if "trade_executed" in signals:
                signals["trade_executed"].connect(self._handle_trade)
            
            # Connect wallet updates
            if "wallet_update" in signals:
                signals["wallet_update"].connect(self.update_wallet)
            
            # Connect trading signals
            if "trading_signals" in signals:
                signals["trading_signals"].connect(self._update_signals)
            logging.info("All GUI signals connected successfully")
        
        except Exception as e:
            logging.error(f"Signal connection error: {e}")
            raise
    def _create_chart(self, title: str, pen_color: Optional[str] = None) -> pg.PlotWidget:
        """Create a styled pyqtgraph plot widget"""
        logging.info(f"Creating chart: {title}")
        chart = pg.PlotWidget(title=title)
        chart.setBackground(DarkTheme.CHART_BACKGROUND)
        chart.showGrid(x=True, y=True, alpha=0.2)
        chart.getAxis('bottom').setPen(pg.mkPen(DarkTheme.TEXT_SECONDARY))
        chart.getAxis('left').setPen(pg.mkPen(DarkTheme.TEXT_SECONDARY))
    
        if pen_color:
            line = chart.plot(pen=pg.mkPen(pen_color, width=2))
            return chart, line
        return chart

    def _create_table(self, headers: List[str], column_widths: List[int], row_height: int = 30) -> QTableWidget:
        """Create a styled table widget with proper spacing"""
        table = QTableWidget(0, len(headers))
        table.setHorizontalHeaderLabels(headers)
    
        # Set column widths
        for i, width in enumerate(column_widths):
            table.setColumnWidth(i, width)
    
        # Style improvements
        table.verticalHeader().setDefaultSectionSize(row_height)
        table.setShowGrid(True)
        table.setGridStyle(Qt.PenStyle.SolidLine)
        table.verticalHeader().setVisible(False)
    
        header = table.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.ResizeMode.Fixed)
        header.setDefaultAlignment(Qt.AlignmentFlag.AlignLeft)
        header.setStyleSheet(f"""
            QHeaderView::section {{
                background-color: {DarkTheme.TABLE_HEADER};
                padding: 6px;
                border: 1px solid {DarkTheme.GRID_COLOR};
                font-weight: bold;
            }}
        """)
    
        return table

    def _create_progress_bar(self) -> QProgressBar:
        """Create a styled progress bar"""
        bar = QProgressBar()
        bar.setMinimum(0)
        bar.setMaximum(100)
        bar.setTextVisible(True)
        bar.setFormat("%v%")
        logging.info("Progress bar created.")
        return bar

    def _create_direction_label(self) -> QLabel:
        """Create a styled direction label"""
        label = QLabel("NEUTRAL")
        label.setStyleSheet(f"""
            font-weight: bold;
            font-size: 13px;
            padding: 5px;
            color: {DarkTheme.TEXT_SECONDARY};
        """)
        return label

  
    def process_market_data(self, data: Dict):
        """Process and display incoming market data"""
        try:
            # Update price chart
            if "price" in data:
                price = float(data["price"])
                self.price_history.append(price)
                self.price_line.setData(y=self.price_history)
            
            # Update volume chart
            if "volume" in data:
                volume = float(data["volume"])
                self.volume_history.append(volume)
                self.volume_bar.setOpts(height=self.volume_history)
            
            # Update metrics
            self._update_metrics({
                "price": data.get("price", 0),
                "volume": data.get("volume", 0),
                "liquidity": data.get("liquidity", 0)
            })
        
            logging.info("Market data processed successfully")
        
        except Exception as e:
            logging.error(f"Market data processing error: {e}")

    def _update_displays(self):
        """Update all display components"""
        try:
            # Update charts if there's data
            if self.price_history:
                self._update_price_chart()

            # Update technical indicators
            if len(self.price_history) > 14:
                self._update_indicators_chart()

            # Update status indicators with latest data
            if hasattr(self, 'last_price'):
                self.update_price(self.last_price)

            # Refresh position and trade tables
            self.update_positions_display(self.trades)
            self.update_trades_display(self.trades)

            logging.info("Display components updated successfully")
        except Exception as e:
            logging.error(f"Display update error: {e}")
            self.error_occurred.emit(str(e))
    def _update_market_data(self, data: Dict):
        """Update market data displays"""
        try:
            if "price" in data:
                self.update_price(data["price"], data.get("volume", 0))
            if "metrics" in data:
                self._update_metrics(data["metrics"])
            if "wallet" in data:
                wallet_data = data["wallet"]
                if "address" in wallet_data:
                    self.update_wallet(wallet_data["address"])
                if "balance" in wallet_data:
                    self.update_balance(float(wallet_data["balance"]))
        except Exception as e:
            logging.error(f"Market data update error: {e}")
            self.error_occurred.emit(str(e))
    def update_price(self, price: float, volume: float = 0):
        """Update price and volume displays with type safety"""
        try:
            current_price = float(price)
            self.price_history.append(current_price)

            # Initialize last_price if needed
            if not hasattr(self, 'last_price'):
                self.last_price = current_price

            # Update price color based on movement
            if current_price > self.last_price:
                self.status_labels["price"].setStyleSheet(f"color: {DarkTheme.ACCENT_GREEN};")
            else:
                self.status_labels["price"].setStyleSheet(f"color: {DarkTheme.ACCENT_RED};")

            # Store for next comparison
            self.last_price = current_price

            # Handle volume updates
            if volume > 0:
                self.volume_history.append(float(volume))

            # Maintain history length
            if len(self.price_history) > 1000:
                self.price_history = self.price_history[-1000:]
                self.volume_history = self.volume_history[-1000:]

            # Update display labels
            self.status_labels["price"].setText(f"Price: ${self._format_number(current_price, 4)}")
            if volume > 0:
                self.status_labels["volume"].setText(f"Volume: ${self._format_number(volume)}")

        except Exception as e:
            logging.error(f"Price update error: {e}")
    def queue_update(self, data: Dict):
        try:
            # Update price chart with live data
            if "price_history" in data:
                active_token = self.get_active_token()
                if active_token in data["price_history"]:
                    prices = data["price_history"][active_token]
                    self.price_chart.clear()
                    self.price_chart.plot(prices, pen='g')

            # Update volume chart
            if "volume_data" in data:
                active_token = self.get_active_token()
                if active_token in data["volume_data"]:
                    volume = data["volume_data"][active_token]
                    self.volume_chart.clear()
                    self.volume_chart.plot([volume], pen='b')

            # Update trading metrics display
            if "metrics" in data:
                self.update_metrics_display(data["metrics"])
            
           # Update active trades panel
            if "pools" in data:
                self.update_pools_display(data["pools"])
            
        except Exception as e:
            logging.error(f"GUI update error: {e}")

    def _update_indicators_chart(self):
        """Update technical indicators chart"""
        try:
            if len(self.price_history) > 14:
                price_array = np.array(self.price_history)
                self._calculate_and_update_indicators(price_array)
        except Exception as e:
            logging.error(f"Indicators chart update error: {e}")

    def _calculate_and_update_indicators(self, price_array: np.ndarray):
        """Calculate and update technical indicators"""
        try:
            # Calculate RSI
            changes = np.diff(price_array)
            gains = np.where(changes > 0, changes, 0)
            losses = np.where(changes < 0, -changes, 0)

            if len(gains) >= 14:  # Need at least 14 periods
                avg_gain = np.mean(gains[-14:])
                avg_loss = np.mean(losses[-14:])
                rs = avg_gain / avg_loss if avg_loss != 0 else 0
                rsi = 100 - (100 / (1 + rs))

                # Calculate MACD
                ema12 = self._calculate_ema(price_array, 12)
                ema26 = self._calculate_ema(price_array, 26)
                macd = ema12 - ema26
                signal = self._calculate_ema(macd, 9)

                # Update indicator lines
                timestamps = np.arange(len(price_array))
                self.rsi_line.setData(x=timestamps, y=np.array([rsi] * len(price_array)))
                self.macd_line.setData(x=timestamps, y=macd)
                self.signal_line.setData(x=timestamps, y=signal)

        except Exception as e:
            logging.error(f"Indicator calculation error: {e}")
 
    def _calculate_ema(self, data: np.ndarray, periods: int) -> np.ndarray:
        """Calculate Exponential Moving Average"""
        alpha = 2 / (periods + 1)
        return np.array(pd.Series(data).ewm(alpha=alpha, adjust=False).mean())

    def _update_price_chart(self):
        """Update price chart with latest data"""
        try:
            if len(self.price_history) > 1:
                timestamps = np.arange(len(self.price_history))
                self.price_line.setData(x=timestamps, y=self.price_history)

                if self.volume_history:
                    self.volume_bar.setOpts(
                        x=timestamps[-len(self.volume_history):],
                        height=self.volume_history,
                        width=0.8
                    )
            logging.info("Price chart updated successfully")
        except Exception as e:
            logging.error(f"Chart update error: {e}")
    def queue_update(self, update_data: Dict[str, Any]):
        """Queue updates for the GUI to process asynchronously"""
        try:
            if hasattr(self, 'update_handler'):
                self.update_handler.queue_update(update_data)
                logging.debug(f"Update queued: {update_data.keys()}")
            else:
                logging.error("Update handler not initialized")
            
        except Exception as e:
            logging.error(f"Failed to queue update: {e}")
            self.error_occurred.emit(str(e))

    def _update_metrics(self, metrics: Dict[str, Any]):
        """Update dashboard metrics"""
        try:
            if "win_rate" in metrics:
                self.status_labels["win_rate"].setText(f"Win Rate: {metrics['win_rate']:.1f}%")
        
            if "total_pnl" in metrics:
                pnl = metrics["total_pnl"]
                color = DarkTheme.ACCENT_GREEN if pnl >= 0 else DarkTheme.ACCENT_RED
                self.status_labels["pnl"].setStyleSheet(f"color: {color};")
                self.status_labels["pnl"].setText(f"PnL: ${self._format_number(pnl, 2)}")
            
            if "total_trades" in metrics:
                self.status_labels["trades"].setText(f"Trades: {metrics['total_trades']}")
            
            if "liquidity" in metrics:
                self.status_labels["liquidity"].setText(
                    f"Liquidity: ${self._format_number(metrics['liquidity'])}"
                )
            
            if "buyer_ratio" in metrics:
                self.status_labels["buyer_ratio"].setText(
                    f"Buy Ratio: {metrics['buyer_ratio']:.1f}%"
                )
            
            if "lp_locked" in metrics:
                self.status_labels["lp_locked"].setText(
                    f"LP Locked: {metrics['lp_locked']:.1f}%"
                )
            
            logging.debug("Dashboard metrics updated")
        
        except Exception as e:
            logging.error(f"Dashboard update error: {e}")
    def update_trades_display(self, trades: List[Dict]):
        """Update trade history display"""
        try:
            logging.debug(f"Updating trades display with {len(trades)} trades")
            self.trades_table.setRowCount(len(trades))
            for i, trade in enumerate(trades):
                time_str = datetime.fromtimestamp(trade.get("timestamp", 0)).strftime("%Y-%m-%d %H:%M:%S")
                self.trades_table.setItem(i, 0, self._create_table_item(time_str))
                self.trades_table.setItem(i, 1, self._create_table_item(trade.get("token", "")))

                side = trade.get("side", "")
                side_color = DarkTheme.ACCENT_GREEN if side == "BUY" else DarkTheme.ACCENT_RED
                self.trades_table.setItem(i, 2, self._create_table_item(side, side_color))
                self.trades_table.setItem(i, 3, self._create_table_item(self._format_number(trade.get("size", 0), 4)))
                
                pnl = trade.get("pnl", 0)
                pnl_color = DarkTheme.ACCENT_GREEN if pnl >= 0 else DarkTheme.ACCENT_RED
                self.trades_table.setItem(i, 4, self._create_table_item(f"${self._format_number(pnl, 2)}", pnl_color))

            logging.info("Trades display updated successfully")
        except Exception as e:
            logging.error(f"Trades display update error: {e}")

    def update_positions_display(self, positions: List[Dict]):
        """Update active positions display"""
        try:
            self.positions_table.setRowCount(len(positions))
            for i, position in enumerate(positions):
                self.positions_table.setItem(i, 0, self._create_table_item(position.get("token", "")))
                self.positions_table.setItem(i, 1, self._create_table_item(self._format_number(position.get("size", 0), 4)))
                self.positions_table.setItem(i, 2, self._create_table_item(f"${self._format_number(position.get('entry', 0), 4)}"))
                
                pnl = position.get("pnl", 0)
                pnl_color = DarkTheme.ACCENT_GREEN if pnl >= 0 else DarkTheme.ACCENT_RED
                self.positions_table.setItem(i, 3, self._create_table_item(f"${self._format_number(pnl, 2)}", pnl_color))

        except Exception as e:
            logging.error(f"Positions display update error: {e}")

    def _format_number(self, number: float, decimals: int = 2) -> str:
        """Format numbers with thousand separators and fixed decimals"""
        try:
            return f"{number:,.{decimals}f}"
        except Exception as e:
            logging.error(f"Number formatting error: {e}")
            return str(number)

    def _create_table_item(self, text: str, color: Optional[str] = None) -> QTableWidgetItem:
        """Create a styled table item"""
        item = QTableWidgetItem(str(text))
        if color:
            item.setForeground(QColor(color))
        item.setTextAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        return item

    def _init_wallet_section(self):
        """Initialize wallet section of the GUI"""
        try:
            wallet_frame, wallet_layout = self._create_section("Wallet Information")
            address_layout = QHBoxLayout()
            self.wallet_address = QLineEdit()
            self.wallet_address.setReadOnly(True)
            self.wallet_address.setPlaceholderText("Connect Wallet")
            copy_button = QPushButton("Copy")
            copy_button.clicked.connect(lambda: self._copy_to_clipboard(self.wallet_address.text()))

            address_layout.addWidget(QLabel("Address:"))
            address_layout.addWidget(self.wallet_address)
            address_layout.addWidget(copy_button)

            self.balance_label = QLabel("Balance: 0.00 SOL")
            self.balance_label.setStyleSheet(f"color: {DarkTheme.TEXT_PRIMARY}; font-weight: bold;")
            wallet_layout.addLayout(address_layout)
            wallet_layout.addWidget(self.balance_label)
            return wallet_frame

        except Exception as e:
            logging.error(f"Wallet section initialization error: {e}")
            raise

    def _copy_to_clipboard(self, text: str):
        """Copy text to clipboard"""
        try:
            QApplication.clipboard().setText(text)
            self.update_status_message("Address copied to clipboard", DarkTheme.ACCENT_GREEN)
        except Exception as e:
            logging.error(f"Clipboard error: {e}")
            self.error_occurred.emit(str(e))

    def connect_wallet_signals(self):
        """Connect wallet-related signals"""
        try:
            if hasattr(self, 'balance_updated'):
                self.balance_updated.connect(self.update_balance)            
            logging.info("Wallet signals connected")
        
        except Exception as e:
            logging.error(f"Wallet signal connection error: {e}")
            raise

    def _handle_trade(self, trade_info: str):
        """Handle trade execution notifications"""
        try:
            token, side, amount, price = trade_info.split(":")
            trade = {
                "timestamp": datetime.now().timestamp(),
                "token": token,
                "side": side.upper(),
                "size": float(amount),
                "price": float(price),
                "pnl": 0.0
            }
            self.trades.append(trade)
            self.update_trades_display(self.trades)
            status_color = DarkTheme.ACCENT_GREEN if side.upper() == "BUY" else DarkTheme.ACCENT_RED
            self.update_status_message(f"Trade executed: {side.upper()} {amount} @ ${price}", status_color)
            self.balance_updated.emit(0.0)  # Trigger balance update
        
        except Exception as e:
            logging.error(f"Trade handling error: {e}")
            self.error_occurred.emit(str(e))

    def _calculate_pnl(self) -> float:
        """Calculate total PnL from trades"""
        try:
            return sum(trade.get("pnl", 0.0) for trade in self.trades)
        except Exception as e:
            logging.error(f"PnL calculation error: {e}")
            return 0.0

    def update_wallet(self, address: str):
        """Update wallet address display"""
        try:
            if hasattr(self, 'wallet_address'):
                self.wallet_address.setText(address)
                logging.info(f"Wallet address updated: {address}")
                self.update_status_message("Wallet connected", DarkTheme.ACCENT_GREEN)
        except Exception as e:
            logging.error(f"Wallet update error: {e}")
            self.error_occurred.emit(str(e))

    def update_balance(self, balance: float):
        """Update wallet balance display"""
        try:
            if hasattr(self, 'balance_label'):
                self.balance_label.setText(f"Balance: {self._format_number(balance, 4)} SOL")
                logging.info(f"Balance updated: {balance:.4f} SOL")
        except Exception as e:
            logging.error(f"Balance update error: {e}")
            self.error_occurred.emit(str(e))

    def get_trade_params(self) -> Dict:
        """Get current trading parameters from inputs"""
        return {
            "token": self.token_input.text().strip(),
            "amount": float(self.amount_input.text() or 0),
        }
    def connect_signals(self, signals: Dict[str, Any]):
        """Connect all GUI signals to their handlers"""
        try:
            # Connect market data signals
            if "market_data" in signals:
                signals["market_data"].connect(self._update_market_data)
        
            # Connect trade signals
            if "trade_signal" in signals:
                signals["trade_signal"].connect(self._handle_trade)
        
            # Connect wallet signals
            if "wallet_update" in signals:
                signals["wallet_update"].connect(self.update_wallet)
        
            # Connect balance signals
            if "balance_update" in signals:
                signals["balance_update"].connect(self.update_balance)
        
            # Connect trading signals
            if "trading_signals" in signals:
                signals["trading_signals"].connect(self._update_signals)
            
            logging.info("GUI signals connected successfully")
        except Exception as e:
            logging.error(f"Failed to connect GUI signals: {e}")
            raise

    def show_message(self, message: str, color: Optional[str] = None):
        """Display a message in the status bar with optional color"""
        try:
            if color == "yellow":
               color = DarkTheme.WARNING
            elif color == "red":
                color = DarkTheme.ERROR
            elif color == "green":
                color = DarkTheme.SUCCESS
            else:
                color = DarkTheme.TEXT_PRIMARY
            
            self.update_status_message(message, color)
            logging.info(f"Status message: {message}")
        except Exception as e:
            logging.error(f"Failed to show message: {e}")
    def update_status_message(self, message: str, color: str = DarkTheme.TEXT_PRIMARY):
        """Update status bar message with color"""
        self.statusBar().setStyleSheet(f"color: {color};")
        self.statusBar().showMessage(message)

    def _update_signals(self, signals: Dict):
        """Update trading signals display"""
        try:
            direction = signals.get("direction", "NEUTRAL")
            strength = int(signals.get("strength", 0))
            confidence = int(signals.get("confidence", 0))
            direction_color = {
                "LONG": DarkTheme.ACCENT_GREEN,
                "SHORT": DarkTheme.ACCENT_RED,
                "NEUTRAL": DarkTheme.TEXT_SECONDARY
            }.get(direction, DarkTheme.TEXT_SECONDARY)

            self.signal_indicators["direction"].setText(direction)
            self.signal_indicators["direction"].setStyleSheet(f"color: {direction_color};")
            self.signal_indicators["strength"].setValue(strength)
            self.signal_indicators["confidence"].setValue(confidence)

        except Exception as e:
            logging.error(f"Signal update error: {e}")
    def connect_trade_handlers(self):
        """Connect trading event handlers and signals"""
        try:
            # Connect trade execution signals
            self.trade_executed.connect(self._handle_trade)
            
            # Connect trading buttons
            self.buy_button.clicked.connect(lambda: self._execute_trade("BUY"))
            self.sell_button.clicked.connect(lambda: self._execute_trade("SELL"))
            
            # Connect auto-trading buttons
            self.auto_trade_button.toggled.connect(self._toggle_auto_trading)
            self.stop_button.clicked.connect(self._emergency_stop)
            
            logging.info("Trade handlers connected successfully")
        except Exception as e:
            logging.error(f"Failed to connect trade handlers: {e}")
            raise

    def _execute_trade(self, side: str):
        """Execute a manual trade"""
        try:
            params = self.get_trade_params()
            if not params["token"] or not params["amount"]:
                self.update_status_message("Please enter token and amount", DarkTheme.WARNING)
                return
                
            # Format trade notification
            trade_info = f"{params['token']}:{side}:{params['amount']}:{self.last_price}"
            self.trade_executed.emit(trade_info)
            
            logging.info(f"Trade executed: {side} {params['amount']} {params['token']}")
        except Exception as e:
            logging.error(f"Trade execution error: {e}")
            self.error_occurred.emit(str(e))

    def _toggle_auto_trading(self, enabled: bool):
        """Handle auto-trading toggle"""
        try:
            if enabled:
                # Start scanning process
                self.scanner = TokenScanner(self.config)
                asyncio.create_task(self.scanner.start_scanning())
            
                # Update UI
                self.auto_trade_button.setText("Stop Auto-Trading")
                self.update_status_message("Auto-trading enabled - Scanning for opportunities", 
                    DarkTheme.SUCCESS)
                
                # Enable real-time updates
                self.status_labels["trades"].setText("Scanner: Active")
            
            else:
                # Stop scanning process
                if hasattr(self, 'scanner'):
                    self.scanner.stop()
                
                # Update UI
                self.auto_trade_button.setText("Start Auto-Trading")
                self.update_status_message("Auto-trading disabled", 
                    DarkTheme.WARNING)
                
                self.status_labels["trades"].setText("Scanner: Inactive")
            
            logging.info(f"Auto-trading {'enabled' if enabled else 'disabled'}")
        
        except Exception as e:
            logging.error(f"Auto-trading toggle error: {e}")
            self.error_occurred.emit(str(e))

    def _emergency_stop(self):
        """Handle emergency stop button press"""
        try:
            # Disable auto-trading
            self.auto_trade_button.setChecked(False)
            
            # Cancel any pending orders
            self.update_status_message("Emergency stop activated - cancelling all orders", 
                DarkTheme.ERROR)
            
            # Clear any active positions (in practice, you'd want to close them properly)
            self.positions_table.setRowCount(0)
            
            logging.warning("Emergency stop activated")
        except Exception as e:
            logging.error(f"Emergency stop error: {e}")
            self.error_occurred.emit(str(e))
    def closeEvent(self, event):
        """Handle application closure"""
        try:
            self.update_handler.update_timer.stop()
            self.update_timer.stop()
            logging.info("GUI closed gracefully")
        except Exception as e:
            logging.error(f"Error during GUI closure: {e}")
        event.accept()


class GuiUpdateHandler(QObject):
    """Handles asynchronous GUI updates"""
    update_signal = pyqtSignal(dict)

    def __init__(self, gui: 'QuantumGUI'):
        super().__init__()
        self.gui = gui
        self.update_queue = Queue()
        self.update_signal.connect(self._process_update)
        self._setup_update_timer()

    def _setup_update_timer(self):
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self._check_queue)
        self.update_timer.start(50)  # 20 Hz update rate

    def _check_queue(self):
        """Process updates from queue"""
        try:
            while not self.update_queue.empty():
                update_data = self.update_queue.get_nowait()
                self._process_update(update_data)
                self.update_queue.task_done()
        except Exception as e:
            logging.error(f"Queue processing error: {e}")

    def _process_update(self, data: Dict[str, Any]):
        """Process updates synchronously"""
        try:
            if "market_data" in data:
                self.gui._update_market_data(data["market_data"])
            if "signals" in data:
                self.gui._update_signals(data["signals"])
            if "metrics" in data:
                self.gui._update_metrics(data["metrics"])
            if "wallet" in data:
                self.gui._update_wallet(data["wallet"])
            if "trades" in data:
                self.gui._update_trades(data["trades"])
        except Exception as e:
            logging.error(f"Update processing error: {e}")
            self.gui.error_occurred.emit(str(e))

    def queue_update(self, data: Dict[str, Any]):
        """Queue an update to be processed"""
        try:
            data_copy = {k: v.copy() if isinstance(v, dict) else v for k, v in data.items()}
            self.update_queue.put(data_copy)
        except Exception as e:
            logging.error(f"Update queueing error: {e}") how much redudant code is in here ??