import time

class LoopHealthMonitor:
    def __init__(self, threshold=0.7):
        self.iteration_times = []
        self.resource_usages = []
        self.error_count = 0
        self.threshold = threshold
        self.last_updated = time.time()

    def update_iteration_time(self, iteration_time):
        self.iteration_times.append(iteration_time)
        # Keep only the last 10 iteration times for calculation
        self.iteration_times = self.iteration_times[-10:]
        self.last_updated = time.time()

    def update_resource_usage(self, resource_usage):
        self.resource_usages.append(resource_usage)
        # Keep only the last 10 resource usages for calculation
        self.resource_usages = self.resource_usages[-10:]
        self.last_updated = time.time()

    def increment_error_count(self):
        self.error_count += 1
        self.last_updated = time.time()

    def get_health_score(self):
        # Calculate health score based on iteration time, resource usage, and error rate
        iteration_time_score = self.calculate_iteration_time_score()
        resource_usage_score = self.calculate_resource_usage_score()
        error_rate_score = self.calculate_error_rate_score()

        # Combine the scores with weights
        health_score = (0.5 * iteration_time_score + 0.3 * resource_usage_score + 0.2 * error_rate_score)
        return health_score

    def calculate_iteration_time_score(self):
        if not self.iteration_times:
            return 1.0  # Assume healthy if no data yet

        avg_iteration_time = sum(self.iteration_times) / len(self.iteration_times)
        # Normalize the score so that lower times are better
        # You might need to adjust the normalization factor (e.g., 0.1) based on your typical iteration times
        return max(0, 1 - (avg_iteration_time / 0.1)) # Cap at 0

    def calculate_resource_usage_score(self):
        if not self.resource_usages:
            return 1.0  # Assume healthy if no data yet

        avg_resource_usage = sum(self.resource_usages) / len(self.resource_usages)
        # Normalize the score so that lower resource usage is better
        return max(0, 1 - avg_resource_usage) # Cap at 0

    def calculate_error_rate_score(self):
        # Calculate error rate over a period (e.g., last 60 seconds)
        time_since_last_update = time.time() - self.last_updated
        # Adjust the error rate based on how frequently the monitor is updated.
        if time_since_last_update > 60:
            error_rate = 0 #Reset error rate if no updates in a while
        else:
            error_rate = self.error_count / max(1, time_since_last_update) #Errors per Second

        # Normalize the score so that lower error rates are better
        return max(0, 1 - error_rate) # Cap at 0

    def is_healthy(self):
        return self.get_health_score() >= self.threshold