import json
import os
import random
from collections import deque
import numpy as np

CONFIG_FILE = "auditor_config.json"

class ConfigManager:
    """Manages persistent settings"""
    def __init__(self, filename=CONFIG_FILE):
        self.filename = filename
        self.config = {
            "base_bet": 0.0000001,
            "risk_level": "balanced", # conservative, balanced, aggressive
            "stop_loss_pct": 0.15,
            "take_profit_pct": 0.50,
            "auto_retrain": True
        }
        self.load()

    def load(self):
        if os.path.exists(self.filename):
            try:
                with open(self.filename, 'r') as f:
                    loaded = json.load(f)
                    self.config.update(loaded)
            except:
                pass

    def save(self):
        try:
            with open(self.filename, 'w') as f:
                json.dump(self.config, f, indent=4)
        except:
            pass

    def get(self, key):
        return self.config.get(key)

    def set(self, key, value):
        self.config[key] = value
        self.save()

class AdvancedBettingSystem:
    """
    Sniper Flat Betting Strategy (V3.7)
    Focuses on securing mathematical edge by flat betting,
    only doubling down when Pattern Engine confidence is high.
    """

    def __init__(self, config_manager=None):
        self.config = config_manager or ConfigManager()
        self.base_bet = self.config.get("base_bet")
        self.bankroll = 0.0
        self.peak_bankroll = 0.0
        self.drawdown = 0.0
        
        # Performance tracking
        self.trade_history = deque(maxlen=1000)
        self.win_rate = 0.0
        self.sharpe_ratio = 0.0

    def get_bet_size(self, prediction_data):
        """Calculate bet size based on True Sniper Logic"""
        # Refresh base bet from config in case it changed
        self.base_bet = self.config.get("base_bet")
        
        if not prediction_data:
            return 0.0 # Wait for models

        pat_conf = prediction_data.get('pattern_conf', 0.0)
        pat_prob = prediction_data.get('pattern_prob', 0.5)
        ml_conf = prediction_data.get('confidence', 0.5)
        
        # Only bet when we have a distinct mathematical advantage
        edge_size = abs(pat_prob - 0.5)
        
        # TIER 1: Extremely high confidence pattern (High Wager)
        if pat_conf > 0.5 and edge_size >= 0.05:
            return self.base_bet * 3.0
            
        # TIER 2: Moderate confidence pattern OR very strong ML (Normal Wager)
        elif pat_conf > 0.3 and edge_size >= 0.02:
            return self.base_bet
        elif ml_conf > 0.80:
            return self.base_bet
            
        # Do not throw away edge on low confidence 50/50 rolls
        return 0.0

    def update(self, bet_size, won, profit):
        """Update state based on result"""
        self.bankroll += profit
        self.peak_bankroll = max(self.peak_bankroll, self.bankroll)
        
        if self.peak_bankroll > 0:
            self.drawdown = (self.peak_bankroll - self.bankroll) / self.peak_bankroll
        elif self.bankroll < 0:
             self.drawdown = abs(self.bankroll) / self.base_bet # arbitrary drawdown scale if purely negative
        
        self.trade_history.append({'profit': profit, 'bet': bet_size, 'won': won})

        wins = [t for t in self.trade_history if t['won']]
        self.win_rate = len(wins) / len(self.trade_history) if self.trade_history else 0
        
        if len(self.trade_history) > 10:
            profits = [t['profit'] for t in self.trade_history]
            std = np.std(profits)
            self.sharpe_ratio = np.mean(profits) / (std if std > 0 else 1e-9)
