do you have any idea why this says no route for the quote ? use anyhow::{anyhow, Result};
use colored::*;
use config::{Config, File};
use env_logger::Env;
use futures_util::{SinkExt, StreamExt};
use log::{debug, error, info, warn};
use reqwest::Client as HttpClient;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
    commitment_config::CommitmentConfig,
    signature::{Keypair, Signer},
};
use std::{
    collections::HashMap,
    fs,
    sync::Arc,
    time::{Duration, Instant},
};
use tokio::{
    sync::{broadcast, Mutex},
    time::interval,
};
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message as WsMessage};
use url::Url;

// Constants
const JUPITER_API: &str = "https://quote-api.jup.ag/v6";
const SOL_MINT: &str = "So11111111111111111111111111111111111111112";
const MIN_PRIORITY_FEE: u64 = 15000;
const STATE_SAVE_INTERVAL: u64 = 30;
const MAX_RETRIES: u8 = 3;

// Log prefixes
const LOG_PREFIX_TRADE: &str = "[TRADE]";
const LOG_PREFIX_ERROR: &str = "[ERROR]";
const LOG_PREFIX_WALLET: &str = "[WALLET]";
const LOG_PREFIX_WS: &str = "[WS]";
const LOG_PREFIX_DEBUG: &str = "[DEBUG]";
const LOG_PREFIX_METRIC: &str = "[METRICS]";
const LOG_PREFIX_STATE: &str = "[STATE]";

#[derive(Debug, Clone, Serialize, Deserialize)]
struct TradeState {
    active_trades: HashMap<String, Trade>,
    last_update: chrono::DateTime<chrono::Utc>,
    metrics: BotMetrics,
}

#[derive(Debug, Deserialize, Clone)]
struct BotConfig {
    rpc: RpcConfig,
    wallet: WalletConfig,
    trading: TradingConfig,
    token_requirements: TokenRequirements,
    logging: LoggingConfig,
    websocket: WebsocketConfig,
}

#[derive(Debug, Deserialize, Clone)]
struct RpcConfig {
    solana_rpc_url: String,
    fallback_url: String,
    ws_url: String,
}

#[derive(Debug, Deserialize, Clone)]
struct WalletConfig {
    keypair_path: String,
    public_key: String,
}

#[derive(Debug, Deserialize, Clone)]
struct TradingConfig {
    snipe_amount: u64,
    max_slippage: f64,
    priority_fee: u64,
    profit_target_percent: f64,
    stop_loss_percent: f64,
    max_concurrent_trades: usize,
    retry_interval: u64,
    max_buy_attempts: u32,
}

#[derive(Debug, Deserialize, Clone)]
struct TokenRequirements {
    min_supply: u64,
    mutable: bool,
    burnt: bool,
    frozen: bool,
}

#[derive(Debug, Deserialize, Clone)]
struct WebsocketConfig {
    reconnect_interval: u64,
    heartbeat_interval: u64,
}

#[derive(Debug, Deserialize, Clone)]
struct LoggingConfig {
    show_balances: bool,
    debug_mode: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Trade {
    token_address: String,
    amount: u64,
    buy_price: f64,
    take_profit_price: f64,
    stop_loss_price: f64,
    timestamp: i64,
    status: TradeStatus,
    signature: String,
    last_price_check: Option<i64>,
    attempts: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum TradeStatus {
    Active,
    Pending,
    PendingSell(String),
    Completed(f64),
    Failed(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct BotMetrics {
    total_trades: u32,
    successful_trades: u32,
    failed_trades: u32,
    total_profit: f64,
    last_update: i64,
    last_heartbeat: i64,
    total_ws_reconnects: u32,
    avg_execution_time: f64,
}

impl BotMetrics {
    fn new() -> Self {
        Self {
            total_trades: 0,
            successful_trades: 0,
            failed_trades: 0,
            total_profit: 0.0,
            last_update: chrono::Utc::now().timestamp(),
            last_heartbeat: chrono::Utc::now().timestamp(),
            total_ws_reconnects: 0,
            avg_execution_time: 0.0,
        }
    }

    fn log_metrics(&self) {
        info!("{} ==================", LOG_PREFIX_METRIC);
        info!("{} Total Trades: {}", LOG_PREFIX_METRIC, self.total_trades);
        info!("{} Successful: {}", LOG_PREFIX_METRIC, self.successful_trades);
        info!("{} Failed: {}", LOG_PREFIX_METRIC, self.failed_trades);
        info!("{} Total Profit: {:.4} SOL", LOG_PREFIX_METRIC, self.total_profit);
        info!("{} Avg Execution: {:.2}ms", LOG_PREFIX_METRIC, self.avg_execution_time);
    }
}

struct Bot {
    config: BotConfig,
    rpc_client: Arc<RpcClient>,
    fallback_rpc: Arc<RpcClient>,
    keypair: Arc<Keypair>,
    active_trades: Arc<Mutex<HashMap<String, Trade>>>,
    pending_trades: Arc<Mutex<HashMap<String, Trade>>>,
    http_client: HttpClient,
    metrics: Arc<Mutex<BotMetrics>>,
    shutdown_sender: broadcast::Sender<()>,
}

impl Bot {
    async fn new() -> Result<Self> {
        println!("{}", "\nInitializing Solana Sniper Elite v5.0".bright_green().bold());

        let config = Config::builder()
            .add_source(File::with_name("config.toml"))
            .build()?
            .try_deserialize::<BotConfig>()?;

        info!("{} Initializing RPC connections", LOG_PREFIX_WALLET);
        let rpc_client = Arc::new(RpcClient::new_with_commitment(
            &config.rpc.solana_rpc_url,
            CommitmentConfig::confirmed(),
        ));

        let fallback_rpc = Arc::new(RpcClient::new_with_commitment(
            &config.rpc.fallback_url,
            CommitmentConfig::confirmed(),
        ));

        info!("{} Loading wallet keypair", LOG_PREFIX_WALLET);
        let key_file_content = fs::read_to_string(&config.wallet.keypair_path)?;
        let key_bytes: Vec<u8> = serde_json::from_str(&key_file_content)?;

        if key_bytes.len() != 64 {
            return Err(anyhow!("Invalid keypair length: expected 64 bytes, got {}", key_bytes.len()));
        }

        let keypair = Arc::new(Keypair::from_bytes(&key_bytes)?);

        let loaded_pubkey = keypair.pubkey().to_string();
        if loaded_pubkey != config.wallet.public_key {
            return Err(anyhow!("Keypair mismatch: loaded {} but config specified {}", loaded_pubkey, config.wallet.public_key));
        }

        info!("{} Loaded wallet: {}", LOG_PREFIX_WALLET, keypair.pubkey());

        let http_client = HttpClient::builder()
            .timeout(Duration::from_secs(5))
            .pool_idle_timeout(Duration::from_secs(30))
            .pool_max_idle_per_host(32)
            .build()?;

        let (shutdown_sender, _) = broadcast::channel(1);

        Ok(Self {
            config,
            rpc_client,
            fallback_rpc,
            keypair,
            active_trades: Arc::new(Mutex::new(HashMap::new())),
            pending_trades: Arc::new(Mutex::new(HashMap::new())),
            http_client,
            metrics: Arc::new(Mutex::new(BotMetrics::new())),
            shutdown_sender,
        })
    }

    async fn start_bot_cycle(&self) -> Result<()> {
        info!("Starting Solana Sniper Elite v5.0");

        let response = self
            .http_client
            .get("https://quote-api.jup.ag/v6/quote")
            .send()
            .await?
            .json::<serde_json::Value>()
            .await?;

        match response {
            serde_json::Value::Object(map) => {
                // Process the map
                self.process_response(&map).await?;
            }
            _ => {
                info!("No new tokens found in this cycle");
            }
        }

        Ok(())
    }

    async fn verify_setup(&self) -> Result<()> {
        info!("{} Verifying setup...", LOG_PREFIX_WALLET);

        // Verify RPC connection
        let blockhash = self.rpc_client.get_latest_blockhash()?;
        info!("{} RPC connection verified", LOG_PREFIX_WALLET);

        // Verify fallback RPC
        let fallback_blockhash = self.fallback_rpc.get_latest_blockhash()?;
        info!("{} Fallback RPC connection verified", LOG_PREFIX_WALLET);

        // Verify both RPCs are in sync
        if blockhash != fallback_blockhash {
            warn!("{} RPCs are not in sync", LOG_PREFIX_WALLET);
        }

        // Check wallet balance
        let balance = self.rpc_client.get_balance(&self.keypair.pubkey())?;
        let sol_balance = balance as f64 / 1e9;
        info!("{} Wallet balance: {} SOL", LOG_PREFIX_WALLET, sol_balance);

        // Verify minimum balance
        let min_required = (self.config.trading.snipe_amount as f64 / 1e9) + 0.01;
        if sol_balance < min_required {
            return Err(anyhow!("Insufficient balance. Have: {} SOL, Need: {} SOL", sol_balance, min_required));
        }

        // Jupiter API verification - consider empty routes as valid
        match self
            .get_jupiter_quote(
                SOL_MINT,
                "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                1_000_000,
            )
            .await
        {
            Ok(_) | Err(_) => {
                info!("{} Jupiter API connection verified", LOG_PREFIX_WALLET);
                Ok(())
            }
        }
    }

    async fn process_response(
        &self,
        response: &serde_json::Map<String, serde_json::Value>,
    ) -> Result<()> {
        // Extract token data from response
        if let Some(data) = response.get("data") {
            if let Some(token_info) = data.as_object() {
                // Process token information
                if let Some(token_address) = token_info.get("address").and_then(|v| v.as_str()) {
                    if let Some(supply) = token_info.get("supply").and_then(|v| v.as_u64()) {
                        let mutable = token_info.get("mutable").and_then(|v| v.as_bool()).unwrap_or(true);
                        let burnt = token_info.get("burnt").and_then(|v| v.as_bool()).unwrap_or(false);
                        let frozen = token_info.get("frozen").and_then(|v| v.as_bool()).unwrap_or(false);

                        self.process_new_token(token_address, supply, mutable, burnt, frozen).await?;
                    }
                }
            }
        }
        Ok(())
    }

    async fn execute_trade(&self, is_buy: bool) -> Result<String> {
        let start = Instant::now();
        let trade_type = if is_buy { "BUY" } else { "SELL" };

        info!("{} Attempting {} for {} tokens", LOG_PREFIX_TRADE, trade_type, self.config.trading.snipe_amount);

        // Check SOL balance for buys
        if is_buy {
            let sol_balance = self.rpc_client.get_balance(&self.keypair.pubkey())? as f64 / 1e9;
            let required_sol = (self.config.trading.snipe_amount as f64 / 1e9) + 0.01;

            if sol_balance < required_sol {
                return Err(anyhow!("Insufficient SOL balance for trade. Have: {} SOL, Need: {} SOL", sol_balance, required_sol));
            }
        }

        let (input_mint, output_mint) = if is_buy {
            (SOL_MINT.to_string(), self.config.trading.snipe_amount.to_string())
        } else {
            (self.config.trading.snipe_amount.to_string(), SOL_MINT.to_string())
        };

        // Try to get quote
        info!("Getting quote...");
        let quote = match self.get_jupiter_quote(&input_mint, &output_mint, self.config.trading.snipe_amount).await {
            Ok(q) => q,
            Err(e) => {
                debug!("{} Quote failed: {}", LOG_PREFIX_DEBUG, e);
                return Err(anyhow!("Quote unavailable: {}", e));
        }
    };
        // Check if route exists
        if !quote["data"]["routesInfos"].as_array().map_or(true, |r| r.is_empty()) {
            return Err(anyhow!("No valid routes found - possible liquidity issue"));
        }

        // Build swap
        info!("Building swap...");
        let swap_data = self.build_atomic_swap(&quote).await?;

        // Send priority transaction
        info!("Sending priority transaction...");
        let signature = self.send_priority_transaction(swap_data).await?;

        let elapsed = start.elapsed();
        info!("{} executed in {:?}", trade_type, elapsed);

        // Update metrics
        let mut metrics = self.metrics.lock().await;
        metrics.avg_execution_time = (metrics.avg_execution_time + elapsed.as_millis() as f64) / 2.0;

        if is_buy {
            metrics.total_trades += 1;
        }

        Ok(signature)
    }

    async fn get_jupiter_quote(&self, input_mint: &str, output_mint: &str, amount: u64) -> Result<Value> {
        let url = format!("{}/quote?inputMint={}&outputMint={}&amount={}&slippageBps={}&onlyDirectRoutes=true",
            JUPITER_API,
            input_mint,
            output_mint,
            amount,
            (self.config.trading.max_slippage * 100.0) as u64
        );

        let response = self.http_client.get(&url).send().await?.json::<Value>().await?;

        if response["data"]["routesInfos"].as_array().map_or(true, |r| r.is_empty()) {
            return Err(anyhow!("No routes available"));
        }

        Ok(response)
    }

    async fn build_atomic_swap(&self, quote: &Value) -> Result<String> {
        let swap_request = json!({
            "quoteResponse": quote,
            "userPublicKey": self.config.wallet.public_key,
            "computeUnitPriceMicroLamports": MIN_PRIORITY_FEE,
            "priorityFeeLamports": MIN_PRIORITY_FEE,
            "asLegacyTransaction": false,
            "maxAccounts": 64,
            "verifyWallet": true
        });

        let response = self.http_client
            .post(format!("{}/swap", JUPITER_API))
            .json(&swap_request)
            .send().await?
            .json::<Value>().await?;

        match response.get("swapTransaction") {
            Some(tx) => Ok(tx.as_str().ok_or_else(|| anyhow!("Invalid transaction format"))?.to_string()),
            None => {
                error!("{} Swap Response: {:?}", LOG_PREFIX_ERROR, response);
                Err(anyhow!("No swap transaction in response"))
            }
        }
    }

    async fn send_priority_transaction(&self, transaction_data: String) -> Result<String> {
        let helius_request = json!({
            "jsonrpc": "2.0",
            "id": "helius-priority",
            "method": "sendTransaction",
            "params": [
                transaction_data,
                {
                    "encoding": "base64",
                    "maxRetries": 0,
                    "skipPreflight": true,
                    "preflightCommitment": "processed",
                    "priorityFee": MIN_PRIORITY_FEE,
                    "minContextSlot": "max",
                    "maxAccountLocks": 64
                }
            ]
        });

        let response = self.http_client.post(&self.config.rpc.solana_rpc_url)
            .json(&helius_request)
            .send().await?
            .json::<Value>().await?;

        match response.get("result") {
            Some(result) => {
                let signature = result.as_str().unwrap_or_default().to_string();
                info!("{} Priority TX sent: {}", LOG_PREFIX_TRADE, signature);
                Ok(signature)
            }
            None => {
                if let Some(error) = response.get("error") {
                    Err(anyhow!("Helius error: {:?}", error))
                } else {
                    Err(anyhow!("Transaction failed without error details"))
                }
            }
        }
    }

    async fn validate_token(&self, token_address: &str, supply: u64, mutable: bool, burnt: bool, frozen: bool) -> Result<bool> {
        info!("{} New token detected:", LOG_PREFIX_TRADE);
        info!("Address: {}", token_address);
        info!("Supply: {}", supply);
        info!("Burnt: {}", burnt);
        info!("Mutable: {}", mutable);
        info!("Frozen: {}", frozen);

        if supply < self.config.token_requirements.min_supply {
            debug!("{} Rejected: Supply {} < minimum {}", LOG_PREFIX_DEBUG, supply, self.config.token_requirements.min_supply);
            return Ok(false);
        }

        if mutable != self.config.token_requirements.mutable {
            debug!("{} Rejected: Wrong mutability", LOG_PREFIX_DEBUG);
            return Ok(false);
        }

        if burnt != self.config.token_requirements.burnt {
            debug!("{} Rejected: Wrong burn status", LOG_PREFIX_DEBUG);
            return Ok(false);
        }

        if frozen != self.config.token_requirements.frozen {
            debug!("{} Rejected: Wrong freeze status", LOG_PREFIX_DEBUG);
            return Ok(false);
        }

        Ok(true)
    }

    pub async fn process_new_token(&self, token_address: &str, supply: u64, mutable: bool, burnt: bool, frozen: bool) -> Result<()> {
        {
            let pending = self.pending_trades.lock().await;
            let active = self.active_trades.lock().await;

            if pending.contains_key(token_address) || active.contains_key(token_address) {
                return Ok(());
            }
        }

        // Validate token attributes
        if !self.validate_token(token_address, supply, mutable, burnt, frozen).await? {
            return Ok(());
        }

        let trades = self.active_trades.lock().await;
        if trades.len() >= self.config.trading.max_concurrent_trades {
            debug!("{} Maximum concurrent trades reached", LOG_PREFIX_DEBUG);
            return Ok(());
        }

        // Create a new trade
        let trade = Trade {
            token_address: token_address.to_string(),
            amount: self.config.trading.snipe_amount,
            buy_price: 0.0,
            take_profit_price: 0.0,
            stop_loss_price: 0.0,
            timestamp: chrono::Utc::now().timestamp(),
            status: TradeStatus::Pending,
            signature: String::new(),
            last_price_check: None,
            attempts: 0,
        };

        {
            let mut pending = self.pending_trades.lock().await;
            pending.insert(token_address.to_string(), trade);
        }

        // Create proper Arc<Bot> and start buy retry
        let bot = Arc::new(Bot {
            config: self.config.clone(),
            rpc_client: self.rpc_client.clone(),
            fallback_rpc: self.fallback_rpc.clone(),
            keypair: self.keypair.clone(),
            active_trades: self.active_trades.clone(),
            pending_trades: self.pending_trades.clone(),
            http_client: self.http_client.clone(),
            metrics: self.metrics.clone(),
            shutdown_sender: self.shutdown_sender.clone(),
        });

        bot.start_buy_retry(token_address.to_string()).await;

        Ok(())
    }

    async fn start_buy_retry(self: Arc<Self>, token_address: String) {
        let bot = self.clone();
        tokio::spawn(async move {
            loop {
                let should_continue = {
                    let pending = bot.pending_trades.lock().await;
                    if let Some(trade) = pending.get(&token_address) {
                        trade.attempts < bot.config.trading.max_buy_attempts
                    } else {
                        false
                    }
                };

                if !should_continue {
                    let mut pending = bot.pending_trades.lock().await;
                    pending.remove(&token_address);
                    break;
                }

                match bot.execute_trade(true).await {
                    Ok(signature) => {
                        info!("{} Buy successful! TX: {}", LOG_PREFIX_TRADE, signature);

                        if let Ok(entry_price) = bot.get_token_price(&token_address).await {
                            let trade = Trade {
                                token_address: token_address.clone(),
                                amount: bot.config.trading.snipe_amount,
                                buy_price: entry_price,
                                take_profit_price: entry_price * (1.0 + bot.config.trading.profit_target_percent / 100.0),
                                stop_loss_price: entry_price * (1.0 - bot.config.trading.stop_loss_percent / 100.0),
                                timestamp: chrono::Utc::now().timestamp(),
                                status: TradeStatus::Active,
                                signature,
                                last_price_check: Some(chrono::Utc::now().timestamp()),
                                attempts: 1,
                            };

                            let mut pending = bot.pending_trades.lock().await;
                            pending.remove(&token_address);

                            let mut active = bot.active_trades.lock().await;
                            active.insert(token_address.clone(), trade);

                            bot.save_state().await.ok();
                        }
                        break;
                    }
                    Err(e) => {
                        let mut pending = bot.pending_trades.lock().await;
                        if let Some(trade) = pending.get_mut(&token_address) {
                            trade.attempts += 1;
                            debug!("{} Buy attempt {} failed: {}", LOG_PREFIX_DEBUG, trade.attempts, e);
                        }
                        drop(pending);

                        tokio::time::sleep(Duration::from_secs(bot.config.trading.retry_interval)).await;
                    }
                }
            }
        });
    }

    async fn monitor_trades(&self) -> Result<()> {
        let trades = self.active_trades.lock().await;
        let trade_list = trades.clone();
        drop(trades);

        for (token_address, trade) in trade_list {
            match trade.status {
                TradeStatus::Active => match self.get_token_price(&token_address).await {
                    Ok(current_price) => {
                        let profit_percent = ((current_price - trade.buy_price) / trade.buy_price * 100.0).round();

                        let status = if profit_percent >= 0.0 {
                            format!("Profit: +{:.2}%", profit_percent).green()
                        } else {
                            format!("Loss: {:.2}%", profit_percent).red()
                        };

                        info!("{} {}: {}", LOG_PREFIX_TRADE, token_address, status);

                        if current_price >= trade.take_profit_price {
                            info!("{} Take profit triggered for {}", LOG_PREFIX_TRADE, token_address);
                            self.execute_sell(&token_address, &trade, "Take Profit").await?;
                        } else if current_price <= trade.stop_loss_price {
                            warn!("{} Stop loss triggered for {}", LOG_PREFIX_TRADE, token_address);
                            self.execute_sell(&token_address, &trade, "Stop Loss").await?;
                        }
                    }
                    Err(e) => {
                        warn!("{} Failed to get price for {}: {}", LOG_PREFIX_ERROR, token_address, e);
                    }
                },
                _ => continue,
            }
        }

        Ok(())
    }

    async fn get_token_price(&self, token_address: &str) -> Result<f64> {
        let url = format!("https://price.jup.ag/v6/price?ids={}&vsToken=SOL", token_address);

        let response = self.http_client.get(&url).send().await?.json::<Value>().await?;

        response["data"][token_address]["price"]
            .as_f64()
            .ok_or_else(|| anyhow!("Price not found"))
    }

    async fn execute_sell(&self, token_address: &str, trade: &Trade, reason: &str) -> Result<()> {
        info!("{} Executing sell for token: {}, reason: {}", LOG_PREFIX_TRADE, token_address, reason);

        // Execute the sell trade
        match self.execute_trade(false).await {
            Ok(signature) => {
                info!("{} Sell successful! TX: {}", LOG_PREFIX_TRADE, signature);

                // Update trade status and metrics
                let mut active = self.active_trades.lock().await;
                if let Some(trade) = active.remove(token_address) {
                    let mut metrics = self.metrics.lock().await;

                    // Calculate profit/loss
                    if let Ok(exit_price) = self.get_token_price(token_address).await {
                        let profit = (exit_price - trade.buy_price) * (trade.amount as f64 / 1e9);
                        metrics.total_profit += profit;

                        let profit_percent = ((exit_price - trade.buy_price) / trade.buy_price * 100.0).round();

                        if profit > 0.0 {
                            metrics.successful_trades += 1;
                            info!("{} Trade closed with +{:.2}% profit ({:.4} SOL)", LOG_PREFIX_TRADE, profit_percent, profit);
                        } else {
                            metrics.failed_trades += 1;
                            info!("{} Trade closed with {:.2}% loss ({:.4} SOL)", LOG_PREFIX_TRADE, profit_percent, profit);
                        }
                    }

                    // Save updated state
                    self.save_state().await?;
                }

                Ok(())
            }
            Err(e) => {
                error!("{} Sell failed: {}", LOG_PREFIX_ERROR, e);
                Err(anyhow!("Sell execution failed: {}", e))
            }
        }
    }

    async fn run_websocket(&self) -> Result<()> {
        info!("{} Connecting to WebSocket...", LOG_PREFIX_WS);

        let ws_url = Url::parse(&self.config.rpc.ws_url)?;
        let (ws_stream, _) = connect_async(&ws_url).await?;
        let (mut write, mut read) = ws_stream.split();

        let subscribe_msg = json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "programSubscribe",
            "params": [
                "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
                {
                    "encoding": "jsonParsed",
                    "commitment": "processed"
                }
            ]
        });

        write.send(WsMessage::Text(subscribe_msg.to_string())).await?;
        info!("{} Subscribed to Raydium program", LOG_PREFIX_WS);

        let last_msg = Arc::new(Mutex::new(Instant::now()));
        let last_msg_clone = last_msg.clone();

        let heartbeat_handle = {
            let max_interval = Duration::from_secs(self.config.websocket.heartbeat_interval);
            tokio::spawn(async move {
                let mut interval = interval(Duration::from_secs(1));
                loop {
                    interval.tick().await;
                    let elapsed = last_msg_clone.lock().await.elapsed();
                    if elapsed > max_interval {
                        error!("{} WebSocket timeout after {:?}", LOG_PREFIX_ERROR, elapsed);
                        break;
                    }
                }
            })
        };

        let mut message_counter = 0u64;
        while let Some(msg_result) = read.next().await {
            *last_msg.lock().await = Instant::now();
            message_counter += 1;

            if message_counter % 1000 == 0 {
                info!("{} Processed {} messages", LOG_PREFIX_WS, message_counter);
            }

            match msg_result {
                Ok(msg) => match msg {
                    WsMessage::Text(text) => {
                        if let Err(e) = self.handle_ws_message(&text).await {
                            warn!("{} Message processing error: {}", LOG_PREFIX_ERROR, e);
                        }
                    }
                    WsMessage::Ping(_) => {
                        if let Err(e) = write.send(WsMessage::Pong(vec![])).await {
                            warn!("Failed to respond to ping: {}", e);
                        }
                    }
                    WsMessage::Close(frame) => {
                        info!("{} WebSocket closed: {:?}", LOG_PREFIX_WS, frame);
                        break;
                    }
                    _ => {}
                },
                Err(e) => {
                    error!("{} WebSocket error: {}", LOG_PREFIX_ERROR, e);
                    break;
                }
            }
        }

        heartbeat_handle.abort();
        Err(anyhow!("WebSocket closed"))
    }

    async fn handle_ws_message(&self, text: &str) -> Result<()> {
        debug!("🔍 Processing WS message");
    
        let value: Value = serde_json::from_str(text)?;
        
        // Check if this is a program notification
        if let Some(params) = value.get("params") {
            if let Some(result) = params.get("result") {
                if let Some(value) = result.get("value") {
                    if let Some(account) = value.get("account") {
                        if let Some(data) = account.get("data") {
                            // Extract the base64 data
                            if let Some(data_array) = data.as_array() {
                                if let Some(base64_data) = data_array.get(0).and_then(|v| v.as_str()) {
                                    // Decode base64 data
                                    if let Ok(decoded) = base64::decode(base64_data) {
                                        // Extract token info from decoded data
                                        if decoded.len() >= 32 { // Minimum size for token data
                                            let token_info = TokenInfo {
                                                address: value["pubkey"].as_str()
                                                    .unwrap_or_default()
                                                    .to_string(),
                                                supply: u64::from_le_bytes(
                                                    decoded[8..16].try_into().unwrap_or_default()
                                                ),
                                                decimals: decoded[16],
                                                is_mutable: (decoded[17] & 1) != 0,
                                                is_burnt: (decoded[17] & 2) != 0,
                                                is_frozen: (decoded[17] & 4) != 0,
                                            };
    
                                            info!("🎯 Found Token: {}", token_info.address);
                                            info!("💰 Supply: {}", token_info.supply);
                                            info!("🔢 Decimals: {}", token_info.decimals);
                                            info!("🔒 Mutable: {}", token_info.is_mutable);
                                            info!("🔥 Burnt: {}", token_info.is_burnt);
                                            info!("❄️ Frozen: {}", token_info.is_frozen);
    
                                            // Process the token
                                            self.process_new_token(
                                                &token_info.address,
                                                token_info.supply,
                                                token_info.is_mutable,
                                                token_info.is_burnt,
                                                token_info.is_frozen,
                                            ).await?;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    
        Ok(())
    }
    

    async fn save_state(&self) -> Result<()> {
        let trades = self.active_trades.lock().await;
        let metrics = self.metrics.lock().await;

        let state = TradeState {
            active_trades: trades.clone(),
            last_update: chrono::Utc::now(),
            metrics: metrics.clone(),
        };

        let state_json = serde_json::to_string_pretty(&state)?;
        tokio::fs::write("bot_state.json", state_json).await?;
        debug!("{} State saved successfully", LOG_PREFIX_STATE);
        Ok(())
    }

    async fn load_state(&self) -> Result<()> {
        match tokio::fs::read_to_string("bot_state.json").await {
            Ok(content) => {
                let state: TradeState = serde_json::from_str(&content)?;
                let mut trades = self.active_trades.lock().await;
                *trades = state.active_trades;

                let mut metrics = self.metrics.lock().await;
                *metrics = state.metrics;

                info!("{} Loaded {} active trades", LOG_PREFIX_STATE, trades.len());
                metrics.log_metrics();
                Ok(())
            }
            Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
                info!("{} No existing state found", LOG_PREFIX_STATE);
                self.save_state().await
            }
            Err(e) => Err(e.into()),
        }
    }

    async fn run(self: Arc<Self>) -> Result<()> {
        info!("Starting Solana Sniper Elite v5.0");

        self.load_state().await?;

        // Start monitoring tasks
        let trade_monitor = {
            let bot = self.clone();
            tokio::spawn(async move {
                let mut interval = interval(Duration::from_secs(1));
                loop {
                    interval.tick().await;
                    if let Err(e) = bot.monitor_trades().await {
                        error!("{} Trade monitoring error: {}", LOG_PREFIX_ERROR, e);
                    }
                }
            })
        };

        let state_saver = {
            let bot = self.clone();
            tokio::spawn(async move {
                let mut interval = interval(Duration::from_secs(STATE_SAVE_INTERVAL));
                loop {
                    interval.tick().await;
                    if let Err(e) = bot.save_state().await {
                        error!("{} State saving error: {}", LOG_PREFIX_ERROR, e);
                    }
                }
            })
        };

        let mut consecutive_failures = 0;
        loop {
            match self.run_websocket().await {
                Ok(_) => {
                    consecutive_failures = 0;
                    continue;
                }
                Err(e) => {
                    consecutive_failures += 1;
                    error!("{} WebSocket error (attempt {}): {}", LOG_PREFIX_ERROR, consecutive_failures, e);

                    if consecutive_failures >= MAX_RETRIES {
                        error!("Too many consecutive errors, saving state and restarting...");
                        if let Err(e) = self.save_state().await {
                            error!("{} Failed to save state before restart: {}", LOG_PREFIX_ERROR, e);
                        }
                        break;
                    }

                    let delay = self.config.websocket.reconnect_interval * consecutive_failures as u64;
                    info!("Waiting {} seconds before reconnect...", delay);
                    tokio::time::sleep(Duration::from_secs(delay)).await;
                }
            }
        }

        trade_monitor.abort();
        state_saver.abort();

        Ok(())
    }
}

#[derive(Debug)]
struct TokenInfo {
    address: String,
    supply: u64,
    decimals: u8,
    is_mutable: bool,
    is_burnt: bool,
    is_frozen: bool,
}

#[tokio::main]
async fn main() -> Result<()> {
    env_logger::Builder::from_env(Env::default().default_filter_or("info"))
        .format(|buf, record| {
            use std::io::Write;
            writeln!(buf, "{} [{}] {}", chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), record.level(), record.args())
        })
        .init();

    println!("{}", "=====================================".bright_blue());
    println!("{}", "SOLANA SNIPER ELITE v5.0".bright_green().bold());
    println!("{}", "=====================================".bright_blue());
    println!("{}", "Starting with Phantom Wallet...".bright_yellow());

    let bot = match Bot::new().await {
        Ok(b) => {
            let bot = Arc::new(b);
            if let Err(e) = bot.verify_setup().await {
                error!("Setup verification failed: {}", e);
                std::process::exit(1);
            }
            bot
        }
        Err(e) => {
            error!("Failed to initialize bot: {}", e);
            std::process::exit(1);
        }
    };

    let shutdown_bot = bot.clone();
    ctrlc::set_handler(move || {
        let bot = shutdown_bot.clone();
        tokio::runtime::Runtime::new().unwrap().block_on(async move {
            info!("{} Initiating graceful shutdown...", LOG_PREFIX_STATE);
            if let Err(e) = bot.save_state().await {
                error!("{} Failed to save state during shutdown: {}", LOG_PREFIX_ERROR, e);
            }
            println!("{}", "Saving state and shutting down...".bright_yellow());
            std::process::exit(0);
        });
    })?;

    let mut consecutive_errors = 0;
    loop {
        info!("Starting bot cycle...");

        match bot.clone().run().await {
            Ok(_) => {
                consecutive_errors = 0;
            }
            Err(e) => {
                error!("{} Bot error: {}", LOG_PREFIX_ERROR, e);
                consecutive_errors += 1;

                if consecutive_errors >= MAX_RETRIES {
                    error!("Too many consecutive errors, forcing restart...");
                    if let Err(e) = bot.save_state().await {
                        error!("{} Failed to save state before restart: {}", LOG_PREFIX_ERROR, e);
                    }
                    std::process::exit(1);
                }

                info!("Waiting 5 seconds before retry...");
                tokio::time::sleep(Duration::from_secs(5)).await;
            }
        }
    }
}