import asyncio
import logging
import json
import time
import os
import base64
import websockets
import aiohttp
from decimal import Decimal
from typing import Dict, Optional, List
from solana_rust_bot import TradingCore

# Hardcoded URLs
HELIUS_RPC = "https://marga-e56m84-fast-mainnet.helius-rpc.com/"
QUICKNODE_RPC = "https://prettiest-bold-cherry.solana-mainnet.quiknode.pro/8144a2ac13c8301886abcf2ac35ad129d478b554/"
QUICKNODE_WS = "wss://prettiest-bold-cherry.solana-mainnet.quiknode.pro/8144a2ac13c8301886abcf2ac35ad129d478b554"
RAYDIUM_PROGRAM = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"

# Set up logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s.%(msecs)03d [%(levelname)s] %(funcName)s: %(message)s',
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler('profit_trading.log')
    ]
)
logger = logging.getLogger(__name__)

class ProfitTrader:
    def __init__(self):
        if not os.getenv('SOLANA_PRIVATE_KEY'):
            raise ValueError("SOLANA_PRIVATE_KEY not set!")

        # Initialize trading cores
        secret_key = os.getenv('SOLANA_PRIVATE_KEY')
        self.marga = TradingCore(
            secret_key=secret_key,
            rpc_url=HELIUS_RPC
        )
        
        self.jupiter = TradingCore(
            secret_key=secret_key,
            rpc_url=QUICKNODE_RPC
        )
        
        # Trading settings
        self.position_size = 0.015
        self.min_profit = 0.001  # 0.1% min profit
        self.max_slippage = 0.001
        
        # Performance tracking
        self.total_profit = 0.0
        self.trades_this_minute = 0
        self.last_trade_time = 0
        self.successful_trades = 0
        
        # Token paths for arbitrage
        self.arb_paths = [
            ["SOL", "USDC", "mSOL", "BONK"],
            ["SOL", "RAY", "USDC", "BONK"],
            ["SOL", "USDT", "USDC", "MSOL"]
        ]
        
        logger.info("Profit trader initialized")

    async def get_jupiter_route(self, input_mint: str, output_mint: str, amount: int) -> Optional[dict]:
        """Get optimal route from Jupiter"""
        try:
            url = "https://quote-api.jup.ag/v6/quote"
            params = {
                "inputMint": input_mint,
                "outputMint": output_mint,
                "amount": str(amount),
                "slippageBps": int(self.max_slippage * 10000)
            }
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url, params=params) as response:
                    if response.status == 200:
                        data = await response.json()
                        return data
                    return None
                    
        except Exception as e:
            logger.error(f"Jupiter route error: {e}")
            return None

    async def execute_marga_trade(self, opportunity: dict) -> bool:
        """Execute trade on Marga"""
        try:
            current_time = time.time()
            if current_time - self.last_trade_time < 0.2:  # 5 TPS max
                return False

            trade_params = {
                "pool_address": RAYDIUM_PROGRAM,  # Changed from "pool" to "pool_address"
                "amount_in": self.position_size,  # Changed from "amount" to "amount_in"
                "min_amount_out": self.position_size * (1 + self.min_profit)  # Changed from "min_out" to "min_amount_out"
            }

            signature = self.marga.execute_trade(trade_params)
            
            if signature:
                self.last_trade_time = current_time
                self.trades_this_minute += 1
                self.successful_trades += 1
                self.total_profit += opportunity['profit']
                
                profit_usd = opportunity['profit'] * 200  # SOL price ~$200
                logger.info(f"Marga Profit: ${profit_usd:.2f} | Total: ${self.total_profit*200:.2f}")
                return True

            return False

        except Exception as e:
            logger.error(f"Marga trade error: {e}")
            return False

    async def process_marga_opportunity(self, tx_data: dict):
        """Process Marga trade opportunity"""
        try:
            logs = tx_data.get('value', {}).get('logs', [])
            
            for log in logs:
                if "ray_log:" in log:
                    b64_str = log.split('ray_log: ')[1].strip()
                    data = base64.b64decode(b64_str)
                    
                    amount_in = int.from_bytes(data[0:8], 'little')
                    amount_out = int.from_bytes(data[8:16], 'little')
                    
                    if amount_in == 0 or amount_out == 0:
                        continue
                    
                    profit = (amount_out - amount_in) / amount_in
                    if profit > self.min_profit:
                        await self.execute_marga_trade({
                            'profit': profit
                        })

        except Exception as e:
            logger.error(f"Opportunity processing error: {e}")

    async def monitor_profit_rate(self):
        """Monitor and log profit rate"""
        while True:
            try:
                await asyncio.sleep(60)  # Check every minute
                profit_per_minute = self.total_profit * 200  # SOL price $200
                logger.info(f"""
                === Profit Metrics ===
                Profit Rate: ${profit_per_minute:.2f}/minute
                Successful Trades: {self.successful_trades}
                Trades This Minute: {self.trades_this_minute}
                Total Profit: ${self.total_profit * 200:.2f}
                """)
                
                self.trades_this_minute = 0

            except Exception as e:
                logger.error(f"Monitoring error: {e}")

    async def run(self):
        """Main trading loop"""
        logger.info("Starting profit trading system...")
        
        # Start profit monitoring
        monitor_task = asyncio.create_task(self.monitor_profit_rate())
        
        try:
            async with websockets.connect(
                QUICKNODE_WS,
                ping_interval=115,
                ping_timeout=60,
                close_timeout=60,
                max_size=2**24
            ) as ws:
                subscribe_msg = {
                    "jsonrpc": "2.0",
                    "id": "profit-trading",
                    "method": "logsSubscribe",
                    "params": [
                        {
                            "mentions": [RAYDIUM_PROGRAM]
                        },
                        {
                            "commitment": "confirmed"
                        }
                    ]
                }

                await ws.send(json.dumps(subscribe_msg))
                response = await ws.recv()
                
                if "error" not in json.loads(response):
                    logger.info("Connected to Marga mempool")

                    while True:
                        msg = await ws.recv()
                        data = json.loads(msg)

                        if data.get("method") == "logsNotification":
                            result = data.get("params", {}).get("result", {})
                            if result:
                                await self.process_marga_opportunity(result)

        except websockets.exceptions.ConnectionClosed:
            logger.warning("WebSocket disconnected - reconnecting...")
            await asyncio.sleep(1)
        except Exception as e:
            logger.error(f"Connection error: {e}")
            await asyncio.sleep(1)
        finally:
            monitor_task.cancel()

async def main():
    """Entry point"""
    os.environ['RUST_BACKTRACE'] = 'full'
    
    try:
        trader = ProfitTrader()
        
        # Log initial balances
        marga_balance = trader.marga.get_balance()
        jupiter_balance = trader.jupiter.get_balance()
        
        logger.info(f"""
        Starting profit trading:
        Marga Balance: {marga_balance} SOL
        Jupiter Balance: {jupiter_balance} SOL
        Using Position Size: {trader.position_size} SOL
        """)
        
        await trader.run()
        
    except KeyboardInterrupt:
        logger.info("Shutting down...")
    except Exception as e:
        logger.error(f"Fatal error: {e}")

if __name__ == "__main__":
    asyncio.run(main()) give me clean debug logging please professional grade