import logging
import time
from aiva.workload_analyzer import WorkloadAnalyzer
from aiva.config import Config

logger = logging.getLogger(__name__)

class Scaler:
    def __init__(self, config: Config, workload_analyzer: WorkloadAnalyzer):
        self.config = config
        self.workload_analyzer = workload_analyzer
        self.hysteresis_duration = self.config.initial_hysteresis_duration
        self.last_scaling_decision = None
        self.last_scaled_at = None

    def should_scale(self, cpu_load):  # Simplified for demonstration
        volatility, burstiness = self.workload_analyzer.analyze(cpu_load)

        if self.config.enable_hysteresis_logging:
            logger.info(f"[HYSTERESIS LOG] Current Hysteresis Duration: {self.hysteresis_duration}, Volatility: {volatility}, Burstiness: {burstiness}, CPU Load: {cpu_load}")

        if self.last_scaling_decision is None:
            # Initial decision, scale up if load is high
            if cpu_load > self.config.scale_up_threshold:
                self.last_scaling_decision = 'up'
                self.last_scaled_at = time.time()
                logger.info(f"[SCALE DECISION] Initial Scale Up triggered by CPU load {cpu_load} > {self.config.scale_up_threshold}")
                return True
            elif cpu_load < self.config.scale_down_threshold:
                self.last_scaling_decision = 'down'
                self.last_scaled_at = time.time()
                logger.info(f"[SCALE DECISION] Initial Scale Down triggered by CPU load {cpu_load} < {self.config.scale_down_threshold}")
                return True
            else:
                return False # no scaling

        if self.last_scaling_decision == 'up':
            if cpu_load < self.config.scale_down_threshold:
                if self.last_scaled_at is None or (time.time() - self.last_scaled_at) > self.hysteresis_duration:
                    self.last_scaling_decision = 'down'
                    self.last_scaled_at = time.time()
                    logger.info(f"[SCALE DECISION] Scale Down triggered by CPU load {cpu_load} < {self.config.scale_down_threshold} after hysteresis")
                    return True
                else:
                    logger.debug(f"[SCALE DECISION] Scale Down blocked by hysteresis. Remaining time: {self.hysteresis_duration - (time.time() - self.last_scaled_at)}")
                    return False  # Hysteresis prevents scaling
            else:
                return False
        else:
            if cpu_load > self.config.scale_up_threshold:
                if self.last_scaled_at is None or (time.time() - self.last_scaled_at) > self.hysteresis_duration:
                    self.last_scaling_decision = 'up'
                    self.last_scaled_at = time.time()
                    logger.info(f"[SCALE DECISION] Scale Up triggered by CPU load {cpu_load} > {self.config.scale_up_threshold} after hysteresis")
                    return True
                else:
                    logger.debug(f"[SCALE DECISION] Scale Up blocked by hysteresis. Remaining time: {self.hysteresis_duration - (time.time() - self.last_scaled_at)}")
                    return False  # Hysteresis prevents scaling
            else:
                return False

    def adjust_hysteresis(self, volatility, burstiness):
        # Placeholder for adaptive hysteresis logic.  This is a very basic example.
        if volatility > self.config.high_volatility_threshold:
            self.hysteresis_duration = min(self.hysteresis_duration * (1 + self.config.hysteresis_adjustment_factor), self.config.max_hysteresis_duration)
            logger.warning(f"[HYSTERESIS ADJUSTMENT] Increasing hysteresis duration to {self.hysteresis_duration} due to high volatility: {volatility}")
        elif burstiness > self.config.high_burstiness_threshold:
            self.hysteresis_duration = min(self.hysteresis_duration * (1 + self.config.hysteresis_adjustment_factor), self.config.max_hysteresis_duration)
            logger.warning(f"[HYSTERESIS ADJUSTMENT] Increasing hysteresis duration to {self.hysteresis_duration} due to high burstiness: {burstiness}")
        else:
            self.hysteresis_duration = max(self.hysteresis_duration * (1 - self.config.hysteresis_adjustment_factor), self.config.min_hysteresis_duration)
            logger.info(f"[HYSTERESIS ADJUSTMENT] Decreasing hysteresis duration to {self.hysteresis_duration}")

    def run(self, cpu_load_data):
        for cpu_load in cpu_load_data:
            should_scale = self.should_scale(cpu_load)
            if should_scale:
                print("Scaling...") # Replace with actual scaling logic.

            volatility, burstiness = self.workload_analyzer.analyze(cpu_load)
            if self.config.enable_hysteresis_adjustment:
                self.adjust_hysteresis(volatility, burstiness)

            time.sleep(self.config.analysis_interval)
