"""
Multi-granularity variance algorithms for adjacent period differences.

Extracted from existing pipeline generate package. Implements the core variance
algorithms that create noticeable differences between adjacent time periods at
hourly, daily, weekly, and monthly granularities.

These algorithms follow the "error on side of crazy" philosophy, creating
50-800% differences between consecutive periods for compelling demo data.

Simplified Profile Support:
- Supports 5 high-value variance profiles with maximum demo distinctiveness
- Handles timing patterns: always_on, weekend_heavy
- Supports seasonal periods: daily, weekly, monthly, quarterly, yearly
- Supports growth types: none, linear
- Maintains mathematical rigor and cost conservation
"""

import hashlib
import math
from datetime import datetime
from typing import Dict, List, Tuple
from functools import lru_cache

import numpy as np
import polars as pl


def hash_deterministic_seed(resource_id: str, base_seed: str = "variance") -> int:
    """
    Create deterministic seed from resource ID for reproducible variance patterns.

    Args:
        resource_id: Unique resource identifier
        base_seed: Base seed string for different pattern types

    Returns:
        Deterministic integer seed for this resource
    """
    combined = f"{base_seed}_{resource_id}"
    hash_value = hashlib.md5(combined.encode()).hexdigest()
    return int(hash_value[:8], 16)


def calculate_adjacent_period_variance(
    base_costs: List[float],
    timestamps: List[str],
    variance_config: Dict[str, float],
    resource_id: str,
    use_vectorized: bool = True
) -> List[float]:
    """
    Apply multi-granularity variance using vectorized operations by default.

    OPTIMIZED: Uses vectorized Polars operations and cached timestamp parsing
    for dramatically improved performance on large datasets.

    Args:
        base_costs: Original flat cost values
        timestamps: ISO timestamp strings
        variance_config: Enhanced variance configuration from core profiles
        resource_id: Unique resource identifier for deterministic patterns
        use_vectorized: Use optimized vectorized implementation (default: True)

    Returns:
        Enhanced costs with adjacent period variance applied
    """
    if not base_costs or not variance_config:
        return base_costs

    # Use vectorized implementation by default for better performance
    if use_vectorized and len(base_costs) > 10:  # Vectorization threshold
        # Use vectorized operations with Polars for better performance
        df = create_variance_dataframe(base_costs, timestamps, resource_id)
        
        # Set up deterministic random state for consistency
        np.random.seed(hash_deterministic_seed(resource_id, "variance"))

        # Apply variance transformations using vectorized operations
        df = apply_vectorized_variance_transformations(df, variance_config, resource_id)
        
        # Extract enhanced costs and preserve total cost
        enhanced_costs = df["cost"].to_list()
        original_total = sum(base_costs)
        enhanced_total = sum(enhanced_costs)

        if enhanced_total > 0 and original_total > 0:
            normalization_factor = original_total / enhanced_total
            enhanced_costs = [cost * normalization_factor for cost in enhanced_costs]

        return enhanced_costs
    
    # Fall back to legacy implementation for small datasets or if vectorized fails
    return calculate_adjacent_period_variance_legacy(
        base_costs, timestamps, variance_config, resource_id
    )


def apply_hourly_variance(
    costs: List[float],
    timestamps: List[datetime],
    variance_factor: float,
    resource_id: str,
) -> List[float]:
    """
    Apply hourly variance ensuring adjacent hours differ noticeably.

    Creates variance in the range of 0.8x-1.2x + jitter for adjacent hour differences.
    FIXED: Apply variance around base cost to prevent exponential growth.
    """
    if variance_factor <= 0:
        return costs

    np.random.seed(hash_deterministic_seed(resource_id, "hourly"))
    enhanced = costs.copy()
    base_cost = (
        np.mean(costs) if costs else 1.0
    )  # Use average as base to prevent exponential growth

    # Calculate safe variance bounds to prevent extreme values
    max_variance = min(variance_factor, 0.5)  # Cap at 50% variance

    for i in range(len(enhanced)):
        # Apply variance around the base cost, not multiplicatively
        # Range: base_cost * (1 ± max_variance)
        min_multiplier = 1.0 - max_variance
        max_multiplier = 1.0 + max_variance

        multiplier = np.random.uniform(min_multiplier, max_multiplier)

        # Apply variance to base cost, ensuring bounded results
        enhanced[i] = base_cost * multiplier

        # Add small chaos for organic feel (limited to prevent extreme values)
        chaos_factor = 1 + np.random.uniform(-0.05, 0.05)  # Max 5% additional chaos
        enhanced[i] *= chaos_factor

        # Safety bounds: ensure cost stays within reasonable limits
        enhanced[i] = max(enhanced[i], base_cost * 0.1)  # Min 10% of base
        enhanced[i] = min(enhanced[i], base_cost * 3.0)  # Max 300% of base

    return enhanced


def apply_daily_variance(
    costs: List[float],
    timestamps: List[datetime],
    variance_factor: float,
    resource_id: str,
) -> List[float]:
    """
    Apply daily variance ensuring adjacent days differ significantly.

    Groups hours by day and applies day-level variance patterns.
    FIXED: Apply variance around base cost to prevent exponential growth.
    """
    if variance_factor <= 0 or len(costs) < 24:
        return costs

    np.random.seed(hash_deterministic_seed(resource_id, "daily"))
    enhanced = costs.copy()
    base_cost = np.mean(costs) if costs else 1.0  # Use overall average as base

    # Group by day
    daily_groups = group_by_period(timestamps, costs, "day")

    # Calculate safe variance bounds
    max_variance = min(variance_factor, 0.6)  # Cap at 60% variance for daily

    # Apply daily variance patterns around base cost, not multiplicatively
    for day_key in sorted(daily_groups.keys()):
        day_indices, day_costs = daily_groups[day_key]

        # Generate day-level variance around base cost
        # Range: base_cost * (1 ± max_variance)
        min_multiplier = 1.0 - max_variance
        max_multiplier = 1.0 + max_variance

        day_multiplier = np.random.uniform(min_multiplier, max_multiplier)
        target_avg = base_cost * day_multiplier

        # Calculate current day average and adjustment needed
        current_day_avg = sum(day_costs) / len(day_costs)
        adjustment = target_avg / current_day_avg if current_day_avg > 0 else 1.0

        # Apply bounded adjustment to all hours in this day
        for idx in day_indices:
            enhanced[idx] *= adjustment
            # Safety bounds: ensure cost stays within reasonable limits
            enhanced[idx] = max(enhanced[idx], base_cost * 0.1)  # Min 10% of base
            enhanced[idx] = min(enhanced[idx], base_cost * 3.0)  # Max 300% of base

    return enhanced


def apply_weekly_variance(
    costs: List[float],
    timestamps: List[datetime],
    variance_factor: float,
    resource_id: str,
) -> List[float]:
    """
    Apply weekly variance ensuring adjacent weeks show optimization opportunities.

    Creates week-to-week patterns that demonstrate cost optimization scenarios.
    FIXED: Apply variance around base cost to prevent exponential growth.
    """
    if variance_factor <= 0 or len(costs) < 168:  # Less than a week of hours
        return costs

    np.random.seed(hash_deterministic_seed(resource_id, "weekly"))
    enhanced = costs.copy()
    base_cost = np.mean(costs) if costs else 1.0  # Use overall average as base

    # Group by week
    weekly_groups = group_by_period(timestamps, costs, "week")

    # Calculate safe variance bounds
    max_variance = min(variance_factor, 0.7)  # Cap at 70% variance for weekly

    for week_key in sorted(weekly_groups.keys()):
        week_indices, week_costs = weekly_groups[week_key]

        # Generate week-level variance around base cost
        # Bias toward either optimization (lower) or scaling (higher) events
        if np.random.random() < 0.4:  # 40% chance of optimization
            # Lower range: 30% to 80% of base
            week_multiplier = np.random.uniform(0.3, 0.8)
        else:  # 60% chance of scaling/growth
            # Higher range: 120% to 170% of base
            week_multiplier = np.random.uniform(1.2, 1.0 + max_variance)

        target_avg = base_cost * week_multiplier

        # Calculate current week average and adjustment needed
        current_week_avg = sum(week_costs) / len(week_costs) if week_costs else 1.0
        adjustment = target_avg / current_week_avg if current_week_avg > 0 else 1.0

        # Apply bounded adjustment to all hours in this week
        for idx in week_indices:
            enhanced[idx] *= adjustment
            # Safety bounds: ensure cost stays within reasonable limits
            enhanced[idx] = max(enhanced[idx], base_cost * 0.1)  # Min 10% of base
            enhanced[idx] = min(enhanced[idx], base_cost * 3.0)  # Max 300% of base

    return enhanced


def apply_monthly_variance(
    costs: List[float],
    timestamps: List[datetime],
    variance_factor: float,
    resource_id: str,
) -> List[float]:
    """
    Apply monthly variance for dramatic business cycle demonstrations.

    Creates month-to-month patterns that showcase business seasonality and major changes.
    FIXED: Apply variance around base cost to prevent exponential growth.
    """
    if variance_factor <= 0 or len(costs) < 720:  # Less than 30 days of hours
        return costs

    np.random.seed(hash_deterministic_seed(resource_id, "monthly"))
    enhanced = costs.copy()
    base_cost = np.mean(costs) if costs else 1.0  # Use overall average as base

    # Group by month
    monthly_groups = group_by_period(timestamps, costs, "month")

    # Calculate safe variance bounds
    max_variance = min(variance_factor, 0.8)  # Cap at 80% variance for monthly

    for month_key in sorted(monthly_groups.keys()):
        month_indices, month_costs = monthly_groups[month_key]

        # Bias toward quarterly patterns and major business events
        # Handle both string and date object inputs
        ts = timestamps[month_indices[0]]
        if hasattr(ts, "isoformat"):
            ts = ts.isoformat()
        month_num = datetime.fromisoformat(ts).month

        if month_num % 3 == 0:  # Quarter end months (March, June, September, December)
            # Higher chance of spikes for quarter-end activity
            if np.random.random() < 0.7:
                # Quarter-end spike: 150% to 250% of base
                month_multiplier = np.random.uniform(1.5, 2.5)
            else:
                # Quarter-end dip: 30% to 70% of base
                month_multiplier = np.random.uniform(0.3, 0.7)
        else:
            # Regular monthly variation around base cost
            # Range: 40% to 160% of base
            month_multiplier = np.random.uniform(0.4, 1.0 + max_variance)

        target_avg = base_cost * month_multiplier

        # Calculate current month average and adjustment needed
        current_month_avg = sum(month_costs) / len(month_costs) if month_costs else 1.0
        adjustment = target_avg / current_month_avg if current_month_avg > 0 else 1.0

        # Apply bounded adjustment to all hours in this month
        for idx in month_indices:
            enhanced[idx] *= adjustment
            # Safety bounds: ensure cost stays within reasonable limits
            enhanced[idx] = max(enhanced[idx], base_cost * 0.1)  # Min 10% of base
            enhanced[idx] = min(enhanced[idx], base_cost * 3.0)  # Max 300% of base

    return enhanced


def apply_phase_jitter(
    costs: List[float],
    timestamps: List[datetime],
    jitter_factor: float,
    resource_id: str,
) -> List[float]:
    """
    Apply random phase jitter for organic timing variations.

    Adds 0-1 hour random phase shifts to create realistic resource timing differences.
    """
    if jitter_factor <= 0:
        return costs

    np.random.seed(hash_deterministic_seed(resource_id, "jitter"))
    enhanced = costs.copy()

    # Apply small random adjustments to simulate organic variations
    for i in range(len(enhanced)):
        jitter = np.random.uniform(-jitter_factor * 0.2, jitter_factor * 0.2)
        enhanced[i] *= 1 + jitter

    return enhanced


def group_by_period(
    timestamps: List[datetime], costs: List[float], period_type: str
) -> Dict[str, Tuple[List[int], List[float]]]:
    """
    Group timestamps and costs by time period.

    Args:
        timestamps: List of datetime objects
        costs: Corresponding cost values
        period_type: "day", "week", or "month"

    Returns:
        Dict mapping period keys to (indices, costs) tuples
    """
    groups = {}

    for i, dt in enumerate(timestamps):
        if period_type == "day":
            key = dt.strftime("%Y-%m-%d")
        elif period_type == "week":
            # Use ISO week number
            year, week, _ = dt.isocalendar()
            key = f"{year}-W{week:02d}"
        elif period_type == "month":
            key = dt.strftime("%Y-%m")
        else:
            raise ValueError(f"Unknown period_type: {period_type}")

        if key not in groups:
            groups[key] = ([], [])

        indices, period_costs = groups[key]
        indices.append(i)
        period_costs.append(costs[i])

    return groups


def validate_adjacent_differences(
    costs: List[float], timestamps: List[str], min_difference_pct: float = 10.0
) -> Dict[str, Dict[str, float]]:
    """
    Validate that adjacent periods have sufficient differences for compelling demos.

    Args:
        costs: Enhanced cost values
        timestamps: ISO timestamp strings
        min_difference_pct: Minimum percentage difference between adjacent periods

    Returns:
        Validation results with statistics for each granularity
    """
    # Handle both string and date object inputs
    dt_timestamps = []
    for ts in timestamps:
        if hasattr(ts, "isoformat"):
            ts = ts.isoformat()
        dt_timestamps.append(datetime.fromisoformat(ts))
    results = {}

    # Validate hourly differences
    hourly_diffs = []
    for i in range(1, len(costs)):
        if costs[i - 1] > 0:
            diff_pct = abs(costs[i] - costs[i - 1]) / costs[i - 1] * 100
            hourly_diffs.append(diff_pct)

    results["hourly"] = {
        "avg_difference_pct": sum(hourly_diffs) / len(hourly_diffs)
        if hourly_diffs
        else 0,
        "min_difference_pct": min(hourly_diffs) if hourly_diffs else 0,
        "max_difference_pct": max(hourly_diffs) if hourly_diffs else 0,
        "periods_meeting_threshold": sum(
            1 for d in hourly_diffs if d >= min_difference_pct
        ),
        "total_periods": len(hourly_diffs),
    }

    # Validate daily differences
    daily_groups = group_by_period(dt_timestamps, costs, "day")
    daily_averages = []
    for day_key in sorted(daily_groups.keys()):
        _, day_costs = daily_groups[day_key]
        daily_averages.append(sum(day_costs) / len(day_costs))

    daily_diffs = []
    for i in range(1, len(daily_averages)):
        if daily_averages[i - 1] > 0:
            diff_pct = (
                abs(daily_averages[i] - daily_averages[i - 1])
                / daily_averages[i - 1]
                * 100
            )
            daily_diffs.append(diff_pct)

    results["daily"] = {
        "avg_difference_pct": sum(daily_diffs) / len(daily_diffs) if daily_diffs else 0,
        "min_difference_pct": min(daily_diffs) if daily_diffs else 0,
        "max_difference_pct": max(daily_diffs) if daily_diffs else 0,
        "periods_meeting_threshold": sum(
            1 for d in daily_diffs if d >= min_difference_pct
        ),
        "total_periods": len(daily_diffs),
    }

    return results


# ENHANCED VARIANCE FUNCTIONS


def is_business_hours(dt: datetime) -> bool:
    """Check if datetime falls within business hours (M-F 9-5)."""
    return dt.weekday() < 5 and 9 <= dt.hour < 17


def is_weekend(dt: datetime) -> bool:
    """Check if datetime falls on weekend (Saturday/Sunday)."""
    return dt.weekday() >= 5


def apply_hourly_variance_with_timing(
    costs: List[float],
    timestamps: List[datetime],
    variance_config: Dict[str, float],
    resource_id: str,
) -> List[float]:
    """
    Apply timing-aware hourly variance based on business hours, weekends, etc.

    ENHANCED: Considers timing patterns from variance_config.
    """
    timing = variance_config.get("timing", "always_on")
    base_variance = variance_config.get("hourly_variance", 0.2)

    if timing == "always_on" or base_variance <= 0:
        # Fall back to original behavior
        return apply_hourly_variance(costs, timestamps, base_variance, resource_id)

    np.random.seed(hash_deterministic_seed(resource_id, "hourly_timing"))
    enhanced = costs.copy()
    base_cost = np.mean(costs) if costs else 1.0

    # Get timing multipliers from config
    business_hours_multiplier = variance_config.get("business_hours_multiplier", 1.0)
    off_hours_multiplier = variance_config.get("off_hours_multiplier", 1.0)
    weekend_multiplier = variance_config.get("weekend_multiplier", 1.0)

    for i, dt in enumerate(timestamps):
        # Determine timing-specific variance multiplier
        if timing == "business_hours":
            if is_business_hours(dt):
                timing_multiplier = business_hours_multiplier
            elif is_weekend(dt):
                timing_multiplier = weekend_multiplier
            else:  # Nights and non-business hours
                timing_multiplier = off_hours_multiplier

        elif timing == "weekend_heavy":
            if is_weekend(dt):
                timing_multiplier = weekend_multiplier
            else:
                timing_multiplier = off_hours_multiplier

        elif timing == "night_shift":
            if 22 <= dt.hour or dt.hour < 6:  # Night hours (10 PM - 6 AM)
                timing_multiplier = business_hours_multiplier
            else:
                timing_multiplier = off_hours_multiplier

        else:
            timing_multiplier = 1.0  # Default

        # Apply timing-adjusted variance
        adjusted_variance = base_variance * timing_multiplier
        max_variance = min(adjusted_variance, 0.8)  # Cap at 80% variance

        # Apply variance around base cost
        min_multiplier = 1.0 - max_variance
        max_multiplier = 1.0 + max_variance

        multiplier = np.random.uniform(min_multiplier, max_multiplier)
        enhanced[i] = base_cost * multiplier

        # Add small chaos for organic feel
        chaos_factor = 1 + np.random.uniform(-0.05, 0.05)
        enhanced[i] *= chaos_factor

        # Safety bounds
        enhanced[i] = max(enhanced[i], base_cost * 0.1)
        enhanced[i] = min(
            enhanced[i], base_cost * 4.0
        )  # Higher cap for timing variance

    return enhanced


def apply_daily_variance_with_timing(
    costs: List[float],
    timestamps: List[datetime],
    variance_config: Dict[str, float],
    resource_id: str,
) -> List[float]:
    """
    Apply timing-aware daily variance.

    ENHANCED: Considers timing patterns for day-level adjustments.
    """
    timing = variance_config.get("timing", "always_on")
    base_variance = variance_config.get("daily_variance", 0.4)

    if timing == "always_on" or base_variance <= 0 or len(costs) < 24:
        # Fall back to original behavior
        return apply_daily_variance(costs, timestamps, base_variance, resource_id)

    np.random.seed(hash_deterministic_seed(resource_id, "daily_timing"))
    enhanced = costs.copy()
    base_cost = np.mean(costs) if costs else 1.0

    # Group by day
    daily_groups = group_by_period(timestamps, costs, "day")

    # Get timing multipliers
    business_hours_multiplier = variance_config.get("business_hours_multiplier", 1.0)
    weekend_multiplier = variance_config.get("weekend_multiplier", 1.0)

    for day_key in sorted(daily_groups.keys()):
        day_indices, day_costs = daily_groups[day_key]

        # Determine if this is a weekend day
        first_dt = timestamps[day_indices[0]]
        is_weekend_day = is_weekend(first_dt)

        # Apply timing-specific variance
        if timing == "business_hours" and not is_weekend_day:
            timing_multiplier = business_hours_multiplier
        elif timing == "weekend_heavy" and is_weekend_day:
            timing_multiplier = weekend_multiplier
        else:
            timing_multiplier = 1.0

        adjusted_variance = base_variance * timing_multiplier
        max_variance = min(adjusted_variance, 0.9)  # Cap at 90% for daily

        # Generate day-level variance
        min_multiplier = 1.0 - max_variance
        max_multiplier = 1.0 + max_variance
        day_multiplier = np.random.uniform(min_multiplier, max_multiplier)

        target_avg = base_cost * day_multiplier
        current_day_avg = sum(day_costs) / len(day_costs)
        adjustment = target_avg / current_day_avg if current_day_avg > 0 else 1.0

        # Apply to all hours in this day
        for idx in day_indices:
            enhanced[idx] *= adjustment
            enhanced[idx] = max(enhanced[idx], base_cost * 0.1)
            enhanced[idx] = min(enhanced[idx], base_cost * 4.0)

    return enhanced


def apply_seasonal_variance(
    costs: List[float],
    timestamps: List[datetime],
    variance_config: Dict[str, float],
    resource_id: str,
) -> List[float]:
    """
    Apply seasonal patterns using sine wave mathematics.

    ENHANCED: Uses actual seasonal mathematics instead of flat variance.
    """
    amplitude = variance_config.get("seasonal_amplitude", 0.0)
    phase = variance_config.get("seasonal_phase", 0.0)
    period = variance_config.get("seasonal_period", "weekly")

    if amplitude <= 0:
        return costs

    np.random.seed(hash_deterministic_seed(resource_id, "seasonal"))
    enhanced = costs.copy()

    for i, dt in enumerate(timestamps):
        # Calculate position in seasonal cycle (0.0-1.0)
        seasonal_position = calculate_seasonal_position(dt, period)

        # Apply sine wave: 1 + amplitude * sin(2π * position + phase)
        seasonal_multiplier = 1 + amplitude * math.sin(
            2 * math.pi * seasonal_position + phase
        )

        # Apply seasonal adjustment to cost
        enhanced[i] *= seasonal_multiplier

    return enhanced


def calculate_seasonal_position(dt: datetime, period: str) -> float:
    """Calculate position in seasonal cycle (0.0-1.0)."""
    if period == "weekly":
        return dt.weekday() / 7.0  # Monday=0.0, Sunday=0.86
    elif period == "monthly":
        return (dt.day - 1) / 30.0  # Approximate monthly position
    elif period == "quarterly":
        quarter_start = datetime(dt.year, ((dt.month - 1) // 3) * 3 + 1, 1)
        days_in_quarter = (dt - quarter_start).days
        return days_in_quarter / 90.0  # Approximate quarterly position
    elif period == "yearly":
        year_start = datetime(dt.year, 1, 1)
        days_in_year = (dt - year_start).days
        return days_in_year / 365.0  # Yearly position
    else:
        return 0.0  # Unknown period


def apply_growth_patterns(
    costs: List[float],
    timestamps: List[datetime],
    variance_config: Dict[str, float],
    resource_id: str,
) -> List[float]:
    """
    Apply growth patterns to costs over time.

    ENHANCED: Supports linear and exponential growth patterns.
    """
    growth_rate = variance_config.get("growth_rate", 0.0)
    growth_type = variance_config.get("growth_type", "none")

    if growth_rate <= 0 or growth_type == "none":
        return costs

    enhanced = costs.copy()

    if not timestamps:
        return enhanced

    # Calculate time progression from first timestamp
    start_time = timestamps[0]

    for i, dt in enumerate(timestamps):
        # Calculate months elapsed from start
        months_elapsed = (
            (dt.year - start_time.year) * 12
            + (dt.month - start_time.month)
            + (dt.day - start_time.day) / 30.0
        )

        if growth_type == "linear":
            # Linear growth: multiplier = 1 + (rate * months)
            growth_multiplier = 1 + (growth_rate * months_elapsed)
        elif growth_type == "exponential":
            # Exponential growth: multiplier = (1 + rate) ^ months
            growth_multiplier = (1 + growth_rate) ** months_elapsed
        else:
            growth_multiplier = 1.0

        # Apply growth with reasonable bounds
        growth_multiplier = max(growth_multiplier, 0.1)  # Min 10% of original
        growth_multiplier = min(growth_multiplier, 10.0)  # Max 10x original

        enhanced[i] *= growth_multiplier

    return enhanced


def create_variance_dataframe(
    base_costs: List[float],
    timestamps: List[str], 
    resource_id: str
) -> pl.DataFrame:
    """
    Create optimized DataFrame for vectorized variance operations.
    
    Uses cached timestamp parsing and pre-computed time features
    for maximum performance.
    """
    # Convert timestamps using cached parsing
    dt_timestamps = [_parse_timestamp_cached(ts) for ts in timestamps]
    
    # Create DataFrame with vectorized time feature extraction
    df = pl.DataFrame({
        "cost": base_costs,
        "timestamp": dt_timestamps
    })
    
    # Add time features using vectorized operations
    df = df.with_columns([
        pl.col("timestamp").dt.hour().alias("hour"),
        pl.col("timestamp").dt.weekday().alias("weekday"),
        pl.col("timestamp").dt.day().alias("day"),
        pl.col("timestamp").dt.week().alias("week"),
        pl.col("timestamp").dt.month().alias("month"),
        pl.col("timestamp").dt.year().alias("year"),
        pl.col("timestamp").dt.strftime("%Y-%m-%d").alias("date_key"),
        pl.col("timestamp").dt.strftime("%Y-W%U").alias("week_key"),
        pl.col("timestamp").dt.strftime("%Y-%m").alias("month_key")
    ])
    
    # Add business hour and weekend flags
    df = df.with_columns([
        ((pl.col("weekday") < 5) & (pl.col("hour") >= 9) & (pl.col("hour") < 17)).alias("is_business_hours"),
        (pl.col("weekday") >= 5).alias("is_weekend")
    ])
    
    return df


@lru_cache(maxsize=10000)
def _parse_timestamp_cached(timestamp_str: str) -> datetime:
    """
    Cached timestamp parsing for improved performance.
    
    Uses LRU cache to avoid re-parsing identical timestamps,
    which is common in time series data.
    """
    if isinstance(timestamp_str, str):
        return datetime.fromisoformat(timestamp_str)
    elif isinstance(timestamp_str, datetime):
        return timestamp_str
    else:
        return datetime.fromisoformat(str(timestamp_str))


def apply_vectorized_variance_transformations(
    df: pl.DataFrame,
    variance_config: Dict[str, float],
    resource_id: str
) -> pl.DataFrame:
    """
    Apply all variance transformations using vectorized operations.
    
    This replaces the multiple function calls with a single vectorized
    pipeline for maximum performance.
    """
    result_df = df.clone()
    base_cost = df["cost"].mean()
    
    # Get configuration parameters
    hourly_variance = variance_config.get("hourly_variance", 0.2)
    daily_variance = variance_config.get("daily_variance", 0.4)
    weekly_variance = variance_config.get("weekly_variance", 0.6)
    monthly_variance = variance_config.get("monthly_variance", 0.8)
    timing = variance_config.get("timing", "always_on")
    
    # Generate deterministic random values using vectorized operations
    np.random.seed(hash_deterministic_seed(resource_id, "vectorized_variance"))
    n_rows = len(df)
    
    # Pre-generate all random values for vectorized application
    hourly_multipliers = np.random.uniform(1 - hourly_variance, 1 + hourly_variance, n_rows)
    daily_multipliers = _generate_daily_multipliers(df, daily_variance, resource_id)
    weekly_multipliers = _generate_weekly_multipliers(df, weekly_variance, resource_id)
    monthly_multipliers = _generate_monthly_multipliers(df, monthly_variance, resource_id)
    
    # Apply timing-aware adjustments if needed
    if timing != "always_on":
        timing_multipliers = _generate_timing_multipliers(df, variance_config)
        hourly_multipliers *= timing_multipliers
    
    # Apply all variance transformations using vectorized operations
    result_df = result_df.with_columns([
        (pl.col("cost") * 
         pl.Series("hourly_mult", hourly_multipliers) *
         pl.Series("daily_mult", daily_multipliers) *
         pl.Series("weekly_mult", weekly_multipliers) *
         pl.Series("monthly_mult", monthly_multipliers)
        ).alias("cost")
    ])
    
    # Apply safety bounds using vectorized operations
    min_cost = base_cost * 0.1
    max_cost = base_cost * 4.0
    
    result_df = result_df.with_columns([
        pl.col("cost").clip(min_cost, max_cost)
    ])
    
    return result_df


def _generate_daily_multipliers(df: pl.DataFrame, variance: float, resource_id: str) -> np.ndarray:
    """Generate daily variance multipliers using vectorized operations."""
    np.random.seed(hash_deterministic_seed(resource_id, "daily_vectorized"))
    
    # Group by date and generate multipliers
    unique_dates = df["date_key"].unique().to_list()
    date_multipliers = {}
    
    for date in unique_dates:
        multiplier = np.random.uniform(1 - variance, 1 + variance)
        date_multipliers[date] = multiplier
    
    # Map back to full dataset
    return np.array([date_multipliers[date] for date in df["date_key"].to_list()])


def _generate_weekly_multipliers(df: pl.DataFrame, variance: float, resource_id: str) -> np.ndarray:
    """Generate weekly variance multipliers using vectorized operations."""
    np.random.seed(hash_deterministic_seed(resource_id, "weekly_vectorized"))
    
    unique_weeks = df["week_key"].unique().to_list()
    week_multipliers = {}
    
    for week in unique_weeks:
        # Bias toward either optimization or scaling events
        if np.random.random() < 0.4:
            multiplier = np.random.uniform(0.3, 0.8)  # Optimization
        else:
            multiplier = np.random.uniform(1.2, 1 + variance)  # Scaling
        week_multipliers[week] = multiplier
    
    return np.array([week_multipliers[week] for week in df["week_key"].to_list()])


def _generate_monthly_multipliers(df: pl.DataFrame, variance: float, resource_id: str) -> np.ndarray:
    """Generate monthly variance multipliers using vectorized operations."""
    np.random.seed(hash_deterministic_seed(resource_id, "monthly_vectorized"))
    
    unique_months = df["month_key"].unique().to_list()
    month_multipliers = {}
    
    for month_key in unique_months:
        month_num = int(month_key.split("-")[1])
        
        if month_num % 3 == 0:  # Quarter end months
            if np.random.random() < 0.7:
                multiplier = np.random.uniform(1.5, 2.5)  # Quarter-end spike
            else:
                multiplier = np.random.uniform(0.3, 0.7)  # Quarter-end dip
        else:
            multiplier = np.random.uniform(0.4, 1 + variance)  # Regular variation
            
        month_multipliers[month_key] = multiplier
    
    return np.array([month_multipliers[month] for month in df["month_key"].to_list()])


def _generate_timing_multipliers(df: pl.DataFrame, variance_config: Dict[str, float]) -> np.ndarray:
    """Generate timing-aware multipliers using vectorized operations."""
    timing = variance_config.get("timing", "always_on")
    business_mult = variance_config.get("business_hours_multiplier", 1.0)
    off_hours_mult = variance_config.get("off_hours_multiplier", 1.0)
    weekend_mult = variance_config.get("weekend_multiplier", 1.0)
    
    if timing == "always_on":
        return np.ones(len(df))
    
    # Create timing multipliers using vectorized conditions
    multipliers = np.ones(len(df))
    
    if timing == "business_hours":
        business_mask = df["is_business_hours"].to_numpy()
        weekend_mask = df["is_weekend"].to_numpy()
        
        multipliers[business_mask] = business_mult
        multipliers[weekend_mask] = weekend_mult
        multipliers[~business_mask & ~weekend_mask] = off_hours_mult
    
    elif timing == "weekend_heavy":
        weekend_mask = df["is_weekend"].to_numpy()
        multipliers[weekend_mask] = weekend_mult
        multipliers[~weekend_mask] = off_hours_mult
    
    return multipliers


# Legacy function maintained for compatibility
def calculate_adjacent_period_variance_legacy(
    base_costs: List[float],
    timestamps: List[str],
    variance_config: Dict[str, float],
    resource_id: str,
) -> List[float]:
    """
    Legacy implementation for backward compatibility.
    
    Use calculate_adjacent_period_variance() for optimized performance.
    """
    if not base_costs or not variance_config:
        return base_costs

    # Set up deterministic random state
    np.random.seed(hash_deterministic_seed(resource_id, "variance"))

    # Parse variance configuration (with enhanced parameters)
    hourly_variance = variance_config.get("hourly_variance", 0.2)
    daily_variance = variance_config.get("daily_variance", 0.4)
    weekly_variance = variance_config.get("weekly_variance", 0.6)
    monthly_variance = variance_config.get("monthly_variance", 0.8)
    phase_jitter = variance_config.get("phase_jitter", 0.5)

    # Convert timestamps to datetime objects (handle both strings and datetime objects)
    dt_timestamps = []
    for ts in timestamps:
        if isinstance(ts, str):
            dt_timestamps.append(datetime.fromisoformat(ts))
        elif isinstance(ts, datetime):
            dt_timestamps.append(ts)
        else:
            # Convert to string first then parse
            dt_timestamps.append(datetime.fromisoformat(str(ts)))

    # Start with base costs
    enhanced_costs = base_costs.copy()

    # ENHANCED: Apply seasonal mathematics first (if enabled)
    if variance_config.get("use_seasonal_math", False):
        enhanced_costs = apply_seasonal_variance(
            enhanced_costs, dt_timestamps, variance_config, resource_id
        )

    # ENHANCED: Apply timing-aware variance at each granularity level
    enhanced_costs = apply_hourly_variance_with_timing(
        enhanced_costs, dt_timestamps, variance_config, resource_id
    )
    enhanced_costs = apply_daily_variance_with_timing(
        enhanced_costs, dt_timestamps, variance_config, resource_id
    )
    enhanced_costs = apply_weekly_variance(
        enhanced_costs, dt_timestamps, weekly_variance, resource_id
    )
    enhanced_costs = apply_monthly_variance(
        enhanced_costs, dt_timestamps, monthly_variance, resource_id
    )

    # Apply phase jitter for organic timing variations
    enhanced_costs = apply_phase_jitter(
        enhanced_costs, dt_timestamps, phase_jitter, resource_id
    )

    # ENHANCED: Apply growth patterns (if specified)
    if variance_config.get("growth_type", "none") != "none":
        enhanced_costs = apply_growth_patterns(
            enhanced_costs, dt_timestamps, variance_config, resource_id
        )

    # Normalize costs to preserve total cost (cost conservation)
    original_total = sum(base_costs)
    enhanced_total = sum(enhanced_costs)

    if enhanced_total > 0 and original_total > 0:
        normalization_factor = original_total / enhanced_total
        enhanced_costs = [cost * normalization_factor for cost in enhanced_costs]

    return enhanced_costs