import json
import logging
import websockets
from datetime import datetime
from typing import Dict, Any
from PyQt6.QtCore import pyqtSignal, QObject
from PyQt6.QtWidgets import (QHeaderView, QPushButton, QTableWidget, QTableWidgetItem)
from .config import config
import aiohttp
import asyncio 

class TokenScanner:
    def __init__(self, config):
        self.config = config
        self.helius_ws = None
        self.active_tokens = set()
        self.min_volume = float(config['trading']['min_volume'])
        self.min_liquidity = float(config['trading']['min_liquidity'])
        self.min_bs_ratio = float(config['trading']['min_bs_ratio'])
        self.max_holder_pct = float(config['trading']['max_holder_pct'])
        self.liquidity_lock_min = float(config['trading']['liquidity_lock_min'])
        self.mint_authority_check = config['trading']['mint_authority_check']

    async def start_scanning(self):
        """Initialize websocket connection and start scanning"""
        try:
            uri = self.config['helius']['ws_endpoint']
            async with websockets.connect(uri) as websocket:
                self.helius_ws = websocket
                
                # Subscribe to SPL token transactions
                await websocket.send(json.dumps({
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "tokenAccountsSubscribe",
                    "params": [
                        {"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},
                        {"encoding": "jsonParsed"}
                    ]
                }))

                while True:
                    msg = await websocket.recv()
                    await self.process_token_event(json.loads(msg))
                    
        except Exception as e:
            logging.error(f"Websocket connection error: {e}")
            
    async def process_token_event(self, event):
        """Process incoming token events and evaluate trading opportunities"""
        try:
            # Extract token data
            token_data = await self.get_token_data(event)
            if not token_data:
                return
                
            # Check if token meets requirements
            if await self.evaluate_token(token_data):
                await self.signal_trading_opportunity(token_data)
                
        except Exception as e:
            logging.error(f"Error processing token event: {e}")
            
    async def evaluate_token(self, token):
        """Evaluate if token meets trading criteria"""
        try:
            # Volume check
            if token['volume_24h'] < self.min_volume:
                return False
                
            # Liquidity check    
            if token['liquidity'] < self.min_liquidity:
                return False
                
            # Buy/Sell ratio check
            if token['buy_sell_ratio'] < self.min_bs_ratio:
                return False
                
            # Holder concentration check
            if token['top_holder_percentage'] > self.max_holder_pct:
                return False
                
            # Liquidity lock check    
            if token['liquidity_locked_percent'] < self.liquidity_lock_min:
                return False
                
            # Mint authority check if enabled
            if self.mint_authority_check and token['mint_authority'] is not None:
                return False
                
            return True
            
        except Exception as e:
            logging.error(f"Token evaluation error: {e}")
            return False
            
    async def signal_trading_opportunity(self, token):
        """Signal a trading opportunity to the trading engine"""
        try:
            logging.info(f"Trading opportunity found: {token['address']}")
            
            signal = {
                "token": token['address'],
                "price": token['price'],
                "volume": token['volume_24h'],
                "liquidity": token['liquidity'],
                "confidence": self.calculate_confidence(token),
                "timestamp": datetime.now().timestamp()
            }
            
            # Emit trading signal
            self.trading_signal.emit(signal)
            
        except Exception as e:
            logging.error(f"Error signaling trade opportunity: {e}")
    async def get_token_data(self, event):
        """Extract and process token data from event"""
        try:
            # Extract token address from event
            token_address = event.get('params', {}).get('result', {}).get('value', {}).get('mint')
        
            if not token_address:
                return None
            
            # Get token data from Helius API
            async with aiohttp.ClientSession() as session:
                async with session.get(
                    f"{self.config['helius']['rpc_endpoint']}/token/{token_address}",
                    headers={"Authorization": f"Bearer {self.config['helius']['api_key']}"}
                ) as response:
                    if response.status == 200:
                        data = await response.json()
                        return {
                            'address': token_address,
                            'price': data.get('price', 0),
                            'volume_24h': data.get('volume24h', 0),
                            'liquidity': data.get('liquidity', 0),
                            'buy_sell_ratio': data.get('buyToSellRatio', 0),
                            'top_holder_percentage': data.get('topHolderPercentage', 100),
                            'liquidity_locked_percent': data.get('liquidityLocked', 0),
                            'mint_authority': data.get('mintAuthority')
                        }
            return None
        
        except Exception as e:
            logging.error(f"Error getting token data: {e}")
            return None
    def _create_monitor_panel(self):
        """Create real-time trading monitor panel"""
        monitor_group = self._create_group("Live Trading Monitor")
        self.monitor_table = QTableWidget()
        self.monitor_table.setColumnCount(6)
        self.monitor_table.setHorizontalHeaderLabels([
            "Token", "Volume (5m)", "Buy/Sell", "Confidence",
            "Liquidity", "Action"
        ])
        self.monitor_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.monitor_table.verticalHeader().setDefaultSectionSize(30)
        monitor_group.layout().addWidget(self.monitor_table)
        return monitor_group

    async def update_monitor(self):
        """Update trading monitor with token scanner data"""
        while True:
            try:
                active_tokens = await self.token_scanner.get_active_tokens()
                self.monitor_table.setRowCount(len(active_tokens))
            
                for i, token in enumerate(active_tokens):
                    self.monitor_table.setItem(i, 0, self._create_table_item(token.address))
                    self.monitor_table.setItem(i, 1, self._create_table_item(f"${token.volume_5min:,.2f}"))
                    self.monitor_table.setItem(i, 2, self._create_table_item(f"{token.buyer_ratio:.2f}"))
                    self.monitor_table.setItem(i, 3, self._create_table_item(f"{token.confidence*100:.1f}%"))
                    self.monitor_table.setItem(i, 4, self._create_table_item(f"${token.liquidity:,.2f}"))
                
                    action_cell = QPushButton("BUYING" if token.confidence > 0.8 else "WATCHING")
                    action_cell.setStyleSheet(
                        "background-color: #4CAF50;" if token.confidence > 0.8 
                        else "background-color: #FFA726;"
                    )
                    self.monitor_table.setCellWidget(i, 5, action_cell)
                
                await asyncio.sleep(0.2)
            
            except Exception as e:
                logging.error(f"Monitor update error: {e}")
                await asyncio.sleep(1) please add logging