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:
    """
    Short Burst Reset Anti-Human Non-Standard Strategy
    Focuses on short, aggressive profit taking sequences with frequent resets
    to avoid pattern detection and long-term negative variance.
    """

    def __init__(self, config_manager=None):
        self.config = config_manager or ConfigManager()
        self.base_bet = self.config.get("base_bet")
        self.bankroll = 1.0
        self.peak_bankroll = 1.0
        self.drawdown = 0.0
        
        # Performance tracking
        self.trade_history = deque(maxlen=100)
        self.short_term_memory = deque(maxlen=10) # For circuit breaker
        self.win_rate = 0.5
        self.sharpe_ratio = 0.0
        
        # Burst Strategy State
        self.burst_active = False
        self.burst_step = 0
        self.burst_history = []
        self.cooldown_steps = 0
        self.circuit_breaker_active = False
        self.circuit_breaker_steps = 0
        self.retrain_requested = False # Request model retraining
        
        # Configuration
        self.max_burst_length = 4
        self.burst_multiplier = 2.5  # Aggressive start
        self.compound_rate = 1.5     # Reinvest 50% of winnings in burst
        self.reset_on_loss = True    # Anti-Martingale (Reset immediately on loss)
        
        # Anti-Human Parameters
        self.jitter_factor = 0.13    # Add randomness to bet size
        self.random_reset_prob = 0.05 # Randomly reset burst
        
        # Flaw Detection / Risk Management
        self.min_confidence_threshold = 0.55
        self.max_drawdown_pct = 0.15 # Tightened stop loss
        
        self.apply_risk_profile()

    def apply_risk_profile(self):
        """Adjust parameters based on risk profile"""
        profile = self.config.get("risk_level")
        if profile == "conservative":
            self.burst_multiplier = 1.5
            self.compound_rate = 1.1
            self.min_confidence_threshold = 0.65
            self.max_drawdown_pct = 0.10
        elif profile == "aggressive":
            self.burst_multiplier = 3.0
            self.compound_rate = 1.8
            self.min_confidence_threshold = 0.50
            self.max_drawdown_pct = 0.25
        else: # balanced
            self.burst_multiplier = 2.5
            self.compound_rate = 1.5
            self.min_confidence_threshold = 0.55
            self.max_drawdown_pct = 0.15

    def get_bet_size(self, prediction_data):
        """Calculate bet size based on Short Burst Reset Strategy"""
        # Refresh base bet from config in case it changed
        self.base_bet = self.config.get("base_bet")
        
        if not prediction_data:
            return self.base_bet

        confidence = prediction_data['confidence']
        model_health = prediction_data.get('model_health', 100.0)
        micro_regime = prediction_data.get('micro_regime', 'NORMAL')
        
        if self.circuit_breaker_active:
            self.circuit_breaker_steps -= 1
            if self.circuit_breaker_steps <= 0:
                self.circuit_breaker_active = False
            return self.base_bet
            
        if self.cooldown_steps > 0:
            self.cooldown_steps -= 1
            return self.base_bet
            
        if not self.burst_active:
            threshold = self.min_confidence_threshold
            if model_health < 70:
                threshold += 0.1
            if micro_regime == "CHAOS":
                threshold += 0.15
                
            if confidence > threshold or (random.random() < 0.10 and model_health > 80):
                self.burst_active = True
                self.burst_step = 1
                bet = self.base_bet * self.burst_multiplier
            else:
                return self.base_bet
        else:
            if self.burst_step == 1:
                bet = self.base_bet * self.burst_multiplier
            else:
                bet = self.base_bet * (self.burst_multiplier * (self.compound_rate ** (self.burst_step - 1)))
                
            bet = min(bet, self.base_bet * 100.0)

        jitter = bet * (random.uniform(-self.jitter_factor, self.jitter_factor))
        final_bet = bet + jitter
        final_bet = max(self.base_bet, final_bet)
        
        if self.drawdown > self.max_drawdown_pct:
            final_bet = self.base_bet
            self.burst_active = False

        return final_bet

    def update(self, bet_size, won, profit):
        """Update state based on result"""
        self.bankroll += profit
        self.peak_bankroll = max(self.peak_bankroll, self.bankroll)
        self.drawdown = (self.peak_bankroll - self.bankroll) / self.peak_bankroll
        
        self.trade_history.append({'profit': profit, 'bet': bet_size})
        self.short_term_memory.append(1 if won else 0)
        
        if len(self.short_term_memory) >= 5:
            recent_wins = sum(list(self.short_term_memory)[-5:])
            if recent_wins <= 1:
                self.circuit_breaker_active = True
                self.circuit_breaker_steps = 10
                self.burst_active = False
                self.retrain_requested = True
        
        if self.burst_active:
            if won:
                self.burst_step += 1
                if self.burst_step > self.max_burst_length:
                    self.burst_active = False
                    self.cooldown_steps = random.randint(2, 5)
            else:
                self.burst_active = False
                self.cooldown_steps = random.randint(1, 3)
                
        if self.burst_active and random.random() < self.random_reset_prob:
             self.burst_active = False
             self.cooldown_steps = 1

        wins = [t for t in self.trade_history if t['profit'] > 0]
        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]
            self.sharpe_ratio = np.mean(profits) / (np.std(profits) + 1e-9)
