"""
IntervalScheduler - Simple interval calculations for trigger nodes.
"""

from datetime import datetime, timedelta
from typing import Dict, Any, Optional
from enum import Enum


class IntervalType(Enum):
    """Supported interval types for scheduling."""
    MINUTES = "minutes"
    HOURS = "hours"
    DAYS = "days"
    WEEKS = "weeks"
    MONTHS = "months"


class IntervalScheduler:
    """
    Handles simple interval calculations for trigger node scheduling.
    
    Supports interval types: minutes, hours, days, weeks, months with numeric values.
    Provides methods to calculate next execution times and validate intervals.
    """
    
    def __init__(self):
        """Initialize the interval scheduler."""
        self.supported_intervals = {
            IntervalType.MINUTES.value: self._calculate_minutes,
            IntervalType.HOURS.value: self._calculate_hours,
            IntervalType.DAYS.value: self._calculate_days,
            IntervalType.WEEKS.value: self._calculate_weeks,
            IntervalType.MONTHS.value: self._calculate_months,
        }
    
    def calculate_next_execution(
        self, 
        interval_type: str, 
        interval_value: int, 
        last_execution: Optional[datetime] = None
    ) -> datetime:
        """
        Calculate the next execution time based on interval configuration.
        
        Args:
            interval_type: Type of interval (minutes, hours, days, weeks, months)
            interval_value: Numeric value for the interval
            last_execution: Last execution time (defaults to now if None)
            
        Returns:
            Next execution datetime
            
        Raises:
            ValueError: If interval type is not supported or value is invalid
        """
        if interval_type not in self.supported_intervals:
            raise ValueError(f"Unsupported interval type: {interval_type}")
        
        if not isinstance(interval_value, int) or interval_value <= 0:
            raise ValueError(f"Interval value must be a positive integer, got: {interval_value}")
        
        base_time = last_execution if last_execution else datetime.utcnow()
        calculator = self.supported_intervals[interval_type]
        
        return calculator(base_time, interval_value)
    
    def validate_interval_config(self, config: Dict[str, Any]) -> bool:
        """
        Validate interval configuration.
        
        Args:
            config: Configuration dictionary containing interval_type and interval_value
            
        Returns:
            True if configuration is valid, False otherwise
        """
        try:
            interval_type = config.get("interval_type")
            interval_value = config.get("interval_value")
            
            if not interval_type or not interval_value:
                return False
            
            if interval_type not in self.supported_intervals:
                return False
            
            if not isinstance(interval_value, int) or interval_value <= 0:
                return False
            
            return True
        except (TypeError, AttributeError):
            return False
    
    def get_supported_interval_types(self) -> list:
        """
        Get list of supported interval types.
        
        Returns:
            List of supported interval type strings
        """
        return list(self.supported_intervals.keys())
    
    def _calculate_minutes(self, base_time: datetime, value: int) -> datetime:
        """Calculate next execution for minute intervals."""
        return base_time + timedelta(minutes=value)
    
    def _calculate_hours(self, base_time: datetime, value: int) -> datetime:
        """Calculate next execution for hour intervals."""
        return base_time + timedelta(hours=value)
    
    def _calculate_days(self, base_time: datetime, value: int) -> datetime:
        """Calculate next execution for day intervals."""
        return base_time + timedelta(days=value)
    
    def _calculate_weeks(self, base_time: datetime, value: int) -> datetime:
        """Calculate next execution for week intervals."""
        return base_time + timedelta(weeks=value)
    
    def _calculate_months(self, base_time: datetime, value: int) -> datetime:
        """
        Calculate next execution for month intervals.
        
        Note: This is an approximation using 30-day months.
        For production use, consider using dateutil.relativedelta for precise month calculations.
        """
        return base_time + timedelta(days=value * 30)
    
    def is_execution_due(
        self, 
        interval_type: str, 
        interval_value: int, 
        last_execution: datetime,
        current_time: Optional[datetime] = None
    ) -> bool:
        """
        Check if execution is due based on interval configuration.
        
        Args:
            interval_type: Type of interval
            interval_value: Numeric value for the interval
            last_execution: Last execution time
            current_time: Current time (defaults to now if None)
            
        Returns:
            True if execution is due, False otherwise
        """
        if current_time is None:
            current_time = datetime.utcnow()
        
        try:
            next_execution = self.calculate_next_execution(
                interval_type, interval_value, last_execution
            )
            return current_time >= next_execution
        except ValueError:
            return False