"""Genetic algorithm optimization."""

from typing import Dict, List, Any, Callable
import random
from src.core.logger import get_logger

logger = get_logger(__name__)


class GeneticOptimizer:
    """Genetic algorithm parameter optimization."""
    
    def __init__(self):
        """Initialize genetic optimizer."""
        self.logger = get_logger(__name__)
    
    def optimize(
        self,
        param_ranges: Dict[str, tuple],
        objective_function: Callable[[Dict[str, Any]], float],
        population_size: int = 50,
        generations: int = 100,
        maximize: bool = True
    ) -> Dict[str, Any]:
        """Run genetic algorithm optimization.
        
        Args:
            param_ranges: Dictionary of parameter -> (min, max) range
            objective_function: Objective function
            population_size: Population size
            generations: Number of generations
            maximize: True to maximize, False to minimize
            
        Returns:
            Best parameters and score
        """
        # Simplified genetic algorithm implementation
        best_score = float('-inf') if maximize else float('inf')
        best_params = None
        
        # Initialize population
        population = self._initialize_population(param_ranges, population_size)
        
        for generation in range(generations):
            # Evaluate fitness
            fitness_scores = []
            for individual in population:
                try:
                    score = objective_function(individual)
                    fitness_scores.append((individual, score))
                except Exception:
                    continue
            
            # Sort by fitness
            fitness_scores.sort(key=lambda x: x[1], reverse=maximize)
            
            # Update best
            if fitness_scores:
                best_individual, best_gen_score = fitness_scores[0]
                if (maximize and best_gen_score > best_score) or (not maximize and best_gen_score < best_score):
                    best_score = best_gen_score
                    best_params = best_individual.copy()
            
            # Create next generation (simplified)
            population = self._evolve_population(fitness_scores, param_ranges, population_size)
        
        return {
            "best_params": best_params,
            "best_score": best_score,
        }
    
    def _initialize_population(self, param_ranges: Dict, size: int) -> List[Dict]:
        """Initialize random population."""
        population = []
        for _ in range(size):
            individual = {}
            for param, (min_val, max_val) in param_ranges.items():
                if isinstance(min_val, int):
                    individual[param] = random.randint(min_val, max_val)
                else:
                    individual[param] = random.uniform(min_val, max_val)
            population.append(individual)
        return population
    
    def _evolve_population(self, fitness_scores: List, param_ranges: Dict, size: int) -> List[Dict]:
        """Evolve population (crossover and mutation)."""
        # Simplified evolution
        new_population = []
        elite_size = size // 10
        
        # Keep elite
        for i in range(min(elite_size, len(fitness_scores))):
            new_population.append(fitness_scores[i][0].copy())
        
        # Generate rest through mutation
        while len(new_population) < size:
            parent = random.choice(fitness_scores[:size//2])[0]
            child = parent.copy()
            
            # Mutate
            param = random.choice(list(param_ranges.keys()))
            min_val, max_val = param_ranges[param]
            if isinstance(min_val, int):
                child[param] = random.randint(min_val, max_val)
            else:
                child[param] = random.uniform(min_val, max_val)
            
            new_population.append(child)
        
        return new_population[:size]

