"""Bayesian optimization."""

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

logger = get_logger(__name__)


class BayesianOptimizer:
    """Bayesian optimization using scikit-optimize."""
    
    def __init__(self):
        """Initialize Bayesian optimizer."""
        self.logger = get_logger(__name__)
    
    def optimize(
        self,
        param_space: Dict[str, Any],
        objective_function: Callable[[Dict[str, Any]], float],
        n_calls: int = 50,
        maximize: bool = True
    ) -> Dict[str, Any]:
        """Run Bayesian optimization.
        
        Args:
            param_space: Parameter space definition
            objective_function: Objective function
            n_calls: Number of optimization iterations
            maximize: True to maximize, False to minimize
            
        Returns:
            Best parameters and score
        """
        try:
            from skopt import gp_minimize
            from skopt.space import Real, Integer
            
            # Convert param_space to skopt format
            dimensions = []
            param_names = []
            for name, space in param_space.items():
                param_names.append(name)
                if isinstance(space, tuple):
                    if isinstance(space[0], int):
                        dimensions.append(Integer(space[0], space[1], name=name))
                    else:
                        dimensions.append(Real(space[0], space[1], name=name))
            
            # Wrapper function
            def objective(params):
                param_dict = dict(zip(param_names, params))
                score = objective_function(param_dict)
                return -score if maximize else score
            
            result = gp_minimize(
                objective,
                dimensions,
                n_calls=n_calls,
                random_state=42
            )
            
            best_params = dict(zip(param_names, result.x))
            best_score = -result.fun if maximize else result.fun
            
            return {
                "best_params": best_params,
                "best_score": best_score,
            }
        except ImportError:
            logger.warning("scikit-optimize not available, using grid search fallback")
            from .grid_search import GridSearchOptimizer
            optimizer = GridSearchOptimizer()
            # Convert param_space to grid format
            param_grid = {k: [v[0], v[1], (v[0] + v[1]) / 2] for k, v in param_space.items()}
            return optimizer.optimize(param_grid, objective_function, maximize)

