import os
from pathlib import Path
from dotenv import load_dotenv
import json
import win32security  # For Windows permissions

class ConfigLoader:
    def __init__(self):
        # Set root directory and load environment variables
        self.root_dir = Path(r"C:\solana_rust_bot")
        load_dotenv(self.root_dir / ".env")
        
        # Set and verify keypair path with Windows security
        self.keypair_path = self.root_dir / "id.json"
        self._verify_file_permissions()
        
        if not self.keypair_path.exists():
            raise FileNotFoundError(f"Keypair not found at {self.keypair_path}")

    def _verify_file_permissions(self):
        """Verify and set proper Windows file permissions"""
        try:
            # Get current user's SID
            user_sid = win32security.GetTokenInformation(
                win32security.OpenProcessToken(
                    win32security.GetCurrentProcess(),
                    win32security.TOKEN_QUERY
                ),
                win32security.TokenUser
            )[0]

            # Set proper permissions on keypair file
            if self.keypair_path.exists():
                security_descriptor = win32security.GetFileSecurity(
                    str(self.keypair_path),
                    win32security.DACL_SECURITY_INFORMATION
                )
                dacl = security_descriptor.GetSecurityDescriptorDacl()
                
                # Add full control for current user only
                dacl.AddAccessAllowedAce(
                    win32security.ACL_REVISION,
                    win32security.FILE_ALL_ACCESS,
                    user_sid
                )
                
                security_descriptor.SetSecurityDescriptorDacl(1, dacl, 0)
                win32security.SetFileSecurity(
                    str(self.keypair_path),
                    win32security.DACL_SECURITY_INFORMATION,
                    security_descriptor
                )
        except Exception as e:
            print(f"Warning: Could not verify file permissions: {e}")

    def get_keypair_bytes(self) -> bytes:
        """Load keypair with proper Windows file handling"""
        try:
            with open(self.keypair_path, 'r') as f:
                keypair_json = json.load(f)
                if isinstance(keypair_json, list) and len(keypair_json) == 64:
                    return bytes(keypair_json)
                else:
                    raise ValueError("Invalid keypair format - must be array of 64 bytes")
        except Exception as e:
            raise RuntimeError(f"Error reading keypair file: {str(e)}")

    def get_network_config(self) -> dict:
        return {
            "rpc_url": os.getenv("RPC_URL"),
            "ws_url": os.getenv("HELIUS_WS_URL"),
            "api_key": os.getenv("API_KEY"),
        }

    def get_market_accounts(self) -> dict:
        return {
            "market": os.getenv("MARKET"),
            "amm_authority": os.getenv("AMM_AUTHORITY"),
            "amm_open_orders": os.getenv("AMM_OPEN_ORDERS"),
            "amm_target": os.getenv("AMM_TARGET"),
            "serum_market": os.getenv("MARKET"),
            "serum_bids": os.getenv("SERUM_BIDS"),
            "serum_asks": os.getenv("SERUM_ASKS"),
            "event_queue": os.getenv("EVENT_QUEUE"),
            "base_vault": os.getenv("BASE_VAULT"),
            "quote_vault": os.getenv("QUOTE_VAULT"),
            "vault_signer": os.getenv("VAULT_SIGNER")
        }

    def get(self, key: str, default: str = None) -> str:
        return os.getenv(key, default)

# Global config instance
config = ConfigLoader()    whats the difference import os
from pathlib import Path
from dotenv import load_dotenv
import json
from typing import Dict, Any, Optional

class ConfigLoader:
    def __init__(self):
        # Set root directory and load environment variables
        self.root_dir = Path(r"C:\solana_rust_bot")
        load_dotenv(self.root_dir / ".env")
        
        # Set keypair path and validate
        self.keypair_path = self.root_dir / "id.json"
        if not self.keypair_path.exists():
            raise FileNotFoundError(f"Keypair not found at {self.keypair_path}")
        
        # Core markets configuration
        self.markets_config = {
            "SOL-WSOL": {
                "market": "HWHvQhFmJB3NUcu1aihKmrKegfVxBEHzwVX6yZCKEsi1",
                "amm_authority": "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1",
                "amm_open_orders": "6MxERzqEY8gqvz1NmYMjKZsxewt4RdrRyNndiEQXS1kz",
                "amm_target": "GthHCSx1SyTiF4sVjUEfdWc7dhvhQyeFn3mWcEGaeLMv",
                "serum_bids": "HD6tQGwPx8zybLxQDsasSgGZ8Kishf8MbnaNVxhRqJHy",
                "serum_asks": "CTzh1Gy5xkfGSaQJqm5qwmmTVhcr1RKTDesVcJe8ge1N",
                "event_queue": "HdevpYz4AkpD7NPuHXVevEjdB7kYrRxJ2Dr7cHccaGPz",
                "base_vault": "GthHCSx1SyTiF4sVjUEfdWc7dhvhQyeFn3mWcEGaeLMv",
                "quote_vault": "5pUTGvN2AA2BEzBDU4CNDh3LHER15WS6J8oJf5XeZFD8",
                "vault_signer": "3D49QorJyNaL4rcpiynbuS3pRH4Y7EXEM6v6ZGaqfFGK"
            }
        }
        
        # Initialize core accounts configuration
        self.accounts_config = {
            # Core accounts
            "wallet": os.getenv("SOLANA_PUBLIC_KEY"),
            "wsol_token_account": os.getenv("WSOL_TOKEN_ACCOUNT"),
            
            # Program IDs
            "raydium": os.getenv("RAYDIUM_PROGRAM_ID"),
            "token": os.getenv("TOKEN_PROGRAM_ID"),
            "system": os.getenv("SYSTEM_PROGRAM_ID"),
            "associated_token": os.getenv("ASSOCIATED_TOKEN_PROGRAM_ID"),
        }
        
        # Add market accounts to config
        self.accounts_config.update(self.get_market_accounts())

        # Validate critical configurations
        self._validate_critical_config()

    def _validate_critical_config(self):
        """Validate critical configuration parameters"""
        critical_programs = [
            ("raydium", "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"),
            ("token", "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
            ("system", "11111111111111111111111111111111"),
            ("associated_token", "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"),
        ]
        
        for name, expected_id in critical_programs:
            current_id = self.accounts_config.get(name)
            
            if current_id != expected_id:
                raise ValueError(
                    f"Invalid {name} program ID: {current_id}\n"
                    f"Expected: {expected_id}\n"
                    "Update your .env file with the correct program IDs"
                )

    def get_keypair_bytes(self) -> bytes:
        """Load keypair from JSON file"""
        try:
            with open(self.keypair_path, 'r') as f:
                keypair_json = json.load(f)
                if isinstance(keypair_json, list) and len(keypair_json) == 64:
                    return bytes(keypair_json)
                else:
                    raise ValueError("Invalid keypair format - must be array of 64 bytes")
        except Exception as e:
            raise RuntimeError(f"Error reading keypair file: {str(e)}")

    def get_network_config(self) -> Dict[str, str]:
        """Get network configuration"""
        return {
            "rpc_url": os.getenv("RPC_URL"),
            "ws_url": os.getenv("HELIUS_WS_URL"),
            "api_key": os.getenv("API_KEY"),
        }

    def get_trade_config(self) -> Dict[str, Any]:
        """Get trading configuration"""
        return {
            "front_run_amount": float(os.getenv("FRONT_RUN_AMOUNT", "0.4")),
            "min_victim_size": float(os.getenv("MIN_VICTIM_SIZE", "10.0")),
            "max_victim_size": float(os.getenv("MAX_VICTIM_SIZE", "50.0")),
            "min_profit": float(os.getenv("MIN_PROFIT", "0.003")),
            "compute_limit": int(os.getenv("COMPUTE_LIMIT", "50000")),
            "priority_fee": int(os.getenv("PRIORITY_FEE", "750000")),
        }

    def get_performance_config(self) -> Dict[str, Any]:
        """Get performance configuration"""
        return {
            "gpu_memory_fraction": float(os.getenv("GPU_MEMORY_FRACTION", "0.95")),
            "stream_priority": int(os.getenv("STREAM_PRIORITY", "-3")),
            "allow_tf32": os.getenv("ALLOW_TF32", "true").lower() == "true",
            "cuda_tensor_cores": os.getenv("CUDA_TENSOR_CORES", "true").lower() == "true",
        }

    def get_market_accounts(self, market_name: str = "SOL-WSOL") -> Dict[str, str]:
        """Get market-specific account configuration"""
        if market_name not in self.markets_config:
            raise ValueError(f"Market {market_name} not found in configuration")
        
        market_data = self.markets_config[market_name]
        
        # Map to exact keys needed by the trading core
        return {
            "market": market_data["market"],
            "amm_authority": market_data["amm_authority"],
            "amm_open_orders": market_data["amm_open_orders"],
            "amm_target": market_data["amm_target"],
            "serum_market": market_data["market"],  # Same as market
            "serum_bids": market_data["serum_bids"],
            "serum_asks": market_data["serum_asks"],
            "event_queue": market_data["event_queue"],
            "base_vault": market_data["base_vault"],
            "quote_vault": market_data["quote_vault"],
            "vault_signer": market_data["vault_signer"]
        }

    def get_balance_config(self) -> Dict[str, float]:
        """Get balance management configuration"""
        return {
            "min_sol_balance": float(os.getenv("MIN_SOL_BALANCE", "0.03")),
            "wsol_target_ratio": float(os.getenv("WSOL_TARGET_RATIO", "0.95")),
        }

    def get(self, key: str, default: Optional[Any] = None) -> Any:
        """Get configuration value by key"""
        if key in self.accounts_config:
            return self.accounts_config[key]
        return os.getenv(key, default)

# Global config instance
config = ConfigLoader()