from typing import Dict, Any
import re

def apply_strategy(cfg_dict: Dict[str, Any]) -> Dict[str, Any]:
    """
    Applies configured agent strategies to the configuration dictionary.
    
    Strategies are composable (e.g., "deep exploitation", "wide exploration").
    
    Modifiers:
    - Base Strategies (Population/Generations):
        - balanced (default): Multiplier = 1.0
        - deep: Pop Size *= 0.25, Generations *= 4.0
        - wide: Pop Size *= 4.7, Generations *= 0.2
        
    - Mode Strategies (Variation/Thermostat):
        - exploitation: Min Mutations=1, Crossover=0.05, Temp=0.01 (Greedy)
        - exploration: Min Mutations=3, Crossover=0.4, Temp=0.1 (Dynamic)
    """
    # Defensive check for agentic section
    if "agentic" not in cfg_dict:
        return cfg_dict
        
    raw_strategy = cfg_dict.get("agentic", {}).get("strategy", "balanced")
    if not isinstance(raw_strategy, str):
        raw_strategy = "balanced"
        
    # Split by comma or space and normalize
    strategies = [s.strip().lower() for s in re.split(r'[,\s]+', raw_strategy) if s.strip()]
    
    # Initialize multipliers (multiplicative)
    pop_mult = 1.0
    gen_mult = 1.0
    
    # Initialize overrides (last wins)
    variation_overrides = {}
    thermostat_overrides = {}

    for strat in strategies:
        if strat == "balanced":
            continue
            
        # --- Base Strategies ---
        elif strat == "deep":
            pop_mult *= 0.25
            gen_mult *= 4.0
        elif strat == "wide":
            pop_mult *= 4.7
            gen_mult *= 0.2
            
        # --- Mode Strategies ---
        elif strat == "exploitation":
            variation_overrides["min_mutation_rate"] = 1
            variation_overrides["crossover_probability"] = 0.05
            thermostat_overrides["initial_temperature"] = 0.00 # Greedy
            
        elif strat == "exploration":
            variation_overrides["min_mutation_rate"] = 3
            variation_overrides["initial_mutation_rate"] = 5
            variation_overrides["crossover_probability"] = 0.40
            thermostat_overrides["initial_temperature"] = 0.10 # Hotter

    # --- Apply Base Multipliers ---
    if "multiobjective" in cfg_dict and "size" in cfg_dict["multiobjective"]:
        original_size = cfg_dict["multiobjective"]["size"]
        new_size = int(original_size * pop_mult)
        cfg_dict["multiobjective"]["size"] = max(10, new_size)
        
    if "max_generations" in cfg_dict:
        cfg_dict["max_generations"] = int(cfg_dict["max_generations"] * gen_mult)
        
    if "hise" in cfg_dict and "overrides" in cfg_dict["hise"]:
        overrides = cfg_dict["hise"]["overrides"]
        if "max_generations" in overrides:
            gens_list = overrides["max_generations"]
            if isinstance(gens_list, list):
                overrides["max_generations"] = [max(1, int(g * gen_mult)) for g in gens_list]

    # --- Apply Mode Overrides ---
    if variation_overrides:
        if "variation" not in cfg_dict:
            cfg_dict["variation"] = {}
        cfg_dict["variation"].update(variation_overrides)
        
    if thermostat_overrides:
        if "thermostat" not in cfg_dict:
            cfg_dict["thermostat"] = {}
        cfg_dict["thermostat"].update(thermostat_overrides)

    return cfg_dict
