"""
Anomaly Profiles for Realistic Cloud Cost Incidents and Events

This module contains predefined anomaly profiles that create compelling,
realistic cloud cost anomalies for demonstrations and testing. Each profile
focuses on mathematical/temporal behavior patterns rather than specific business cases,
making them reusable across different scenarios.

Profile categories:
- Spike Patterns: Various sudden increase behaviors
- Drop & Recovery Patterns: Outage and recovery behaviors
- Duration-Based Patterns: Time-focused anomaly behaviors
- Timing & Cyclical Patterns: Scheduled and cyclical anomaly behaviors
- Propagation Patterns: How anomalies spread across services/regions
- Recovery Behavior Patterns: Different recovery characteristics
"""

ANOMALY_PROFILES = {
    # Spike Patterns
    "sudden_extreme_spike": {
        "description": "Instant 10-50x spike lasting 2-8 hours with immediate return to baseline",
        "category": "spike_patterns",
        "pattern_type": "instant_spike",
        "magnitude_range": [10.0, 50.0],
        "duration_range": [2, 8],  # hours
        "recovery_pattern": "immediate_drop",
        "trigger_probability": 0.005,  # 0.5% daily probability
        "timing_preferences": ["business_hours", "peak_usage"],
        "cascade_probability": 0.15,
        "realistic_for": ["ddos_response", "viral_events", "system_overload"],
    },
    "gradual_massive_buildup": {
        "description": "Slow ramp to 20x peak over 6-12 hours, then exponential decay",
        "category": "spike_patterns",
        "pattern_type": "gradual_buildup",
        "magnitude_range": [15.0, 25.0],
        "buildup_duration": [6, 12],  # hours to reach peak
        "decay_duration": [4, 8],  # hours to return to baseline
        "recovery_pattern": "exponential_decay",
        "trigger_probability": 0.003,  # 0.3% daily probability
        "timing_preferences": ["off_hours", "weekend"],
        "cascade_probability": 0.25,
        "realistic_for": ["batch_processing", "data_migration", "load_testing"],
    },
    "random_mega_burst": {
        "description": "Unpredictable 100x+ spikes with exponential decay over 1-3 days",
        "category": "spike_patterns",
        "pattern_type": "mega_burst",
        "magnitude_range": [100.0, 500.0],
        "duration_range": [24, 72],  # hours
        "recovery_pattern": "exponential_decay",
        "decay_half_life": 8,  # hours
        "trigger_probability": 0.001,  # 0.1% daily probability
        "timing_preferences": ["random"],
        "cascade_probability": 0.40,
        "realistic_for": ["viral_content", "news_events", "catastrophic_scaling"],
    },
    "double_spike_pattern": {
        "description": "Two major spikes (15x, 10x) separated by 40% recovery valley",
        "category": "spike_patterns",
        "pattern_type": "double_spike",
        "first_spike_magnitude": [12.0, 18.0],
        "valley_reduction": 0.40,  # 40% reduction between spikes
        "second_spike_magnitude": [8.0, 12.0],
        "spike_separation": [3, 8],  # hours between spikes
        "total_duration": [12, 24],  # hours
        "recovery_pattern": "gradual_decline",
        "trigger_probability": 0.002,
        "timing_preferences": ["business_hours"],
        "cascade_probability": 0.20,
        "realistic_for": ["deployment_issues", "failover_events", "cascading_failures"],
    },
    "cascading_spike_chain": {
        "description": "Multiple sequential spikes of increasing magnitude (3x → 8x → 15x)",
        "category": "spike_patterns",
        "pattern_type": "cascading_chain",
        "spike_magnitudes": [3.0, 8.0, 15.0, 25.0],
        "spike_intervals": [2, 4, 6],  # hours between each spike
        "spike_durations": [1, 2, 3, 4],  # hours for each spike
        "recovery_pattern": "stepped_decline",
        "trigger_probability": 0.001,
        "timing_preferences": ["business_hours", "peak_usage"],
        "cascade_probability": 0.60,  # High cascade probability
        "realistic_for": [
            "system_cascades",
            "regional_failures",
            "auto_scaling_storms",
        ],
    },
    # Drop & Recovery Patterns
    "immediate_cliff_drop": {
        "description": "Instant 90% cost reduction followed by gradual 6-hour recovery",
        "category": "drop_recovery_patterns",
        "pattern_type": "cliff_drop",
        "drop_magnitude": 0.10,  # Drop to 10% of normal
        "recovery_duration": [6, 12],  # hours
        "recovery_pattern": "linear_recovery",
        "trigger_probability": 0.003,
        "timing_preferences": ["random"],
        "cascade_probability": 0.10,
        "realistic_for": ["system_outages", "service_failures", "emergency_shutdowns"],
    },
    "stepped_recovery_ladder": {
        "description": "Outage + recovery in discrete 25% → 50% → 80% → 100% steps",
        "category": "drop_recovery_patterns",
        "pattern_type": "stepped_recovery",
        "outage_duration": [1, 4],  # hours
        "recovery_steps": [0.25, 0.50, 0.80, 1.0],
        "step_durations": [2, 3, 4, 2],  # hours for each recovery step
        "trigger_probability": 0.004,
        "timing_preferences": ["off_hours", "maintenance_windows"],
        "cascade_probability": 0.05,
        "realistic_for": [
            "planned_maintenance",
            "service_restoration",
            "gradual_rollback",
        ],
    },
    "oscillating_recovery": {
        "description": "Up/down oscillations during recovery (±30% swings) over 8 hours",
        "category": "drop_recovery_patterns",
        "pattern_type": "oscillating_recovery",
        "initial_drop": 0.30,  # Drop to 30% of normal
        "oscillation_amplitude": 0.30,  # ±30% swings
        "oscillation_frequency": 2,  # hours per oscillation
        "recovery_duration": [8, 16],  # hours
        "damping_factor": 0.8,  # Oscillations reduce over time
        "trigger_probability": 0.003,
        "timing_preferences": ["random"],
        "cascade_probability": 0.20,
        "realistic_for": [
            "auto_scaling_hunting",
            "system_instability",
            "feedback_loops",
        ],
    },
    "overcompensation_bounce": {
        "description": "Drop + recovery overshoot to 150% before stabilizing",
        "category": "drop_recovery_patterns",
        "pattern_type": "overshoot_recovery",
        "initial_drop": 0.20,  # Drop to 20% of normal
        "overshoot_magnitude": 1.50,  # 150% of normal
        "overshoot_duration": [2, 6],  # hours
        "stabilization_duration": [4, 8],  # hours to return to normal
        "trigger_probability": 0.003,
        "timing_preferences": ["business_hours"],
        "cascade_probability": 0.15,
        "realistic_for": [
            "over_provisioning",
            "emergency_scaling",
            "reactive_responses",
        ],
    },
    "partial_recovery_plateau": {
        "description": "Incomplete recovery to new 70% baseline after incident",
        "category": "drop_recovery_patterns",
        "pattern_type": "plateau_recovery",
        "initial_drop": 0.15,  # Drop to 15% of normal
        "plateau_level": 0.70,  # Recover to only 70% of original
        "recovery_duration": [6, 12],  # hours
        "plateau_duration": "permanent",  # New baseline
        "trigger_probability": 0.002,
        "timing_preferences": ["random"],
        "cascade_probability": 0.25,
        "realistic_for": ["permanent_changes", "service_degradation", "capacity_loss"],
    },
    # Duration-Based Patterns
    "brief_extreme_event": {
        "description": "Very high magnitude (30-80x) for very short duration (15min-2hrs)",
        "category": "duration_patterns",
        "pattern_type": "brief_extreme",
        "magnitude_range": [30.0, 80.0],
        "duration_range": [0.25, 2.0],  # hours (15 min to 2 hours)
        "recovery_pattern": "immediate_drop",
        "trigger_probability": 0.008,  # Higher probability due to brief nature
        "timing_preferences": ["random"],
        "cascade_probability": 0.30,
        "realistic_for": ["flash_traffic", "micro_incidents", "burst_processing"],
    },
    "sustained_elevated_period": {
        "description": "Moderate elevation (2-4x) over days or weeks",
        "category": "duration_patterns",
        "pattern_type": "sustained_elevation",
        "magnitude_range": [2.0, 4.0],
        "duration_range": [48, 336],  # hours (2 days to 2 weeks)
        "recovery_pattern": "gradual_decline",
        "trigger_probability": 0.005,
        "timing_preferences": ["random"],
        "cascade_probability": 0.10,
        "realistic_for": ["project_phases", "seasonal_increases", "ongoing_issues"],
    },
    "intermittent_burst_series": {
        "description": "Multiple short bursts (5-12x) over extended period",
        "category": "duration_patterns",
        "pattern_type": "burst_series",
        "burst_magnitude": [5.0, 12.0],
        "burst_duration": [0.5, 3.0],  # hours per burst
        "burst_count": [5, 15],
        "series_duration": [24, 72],  # hours for entire series
        "burst_interval": [2, 8],  # hours between bursts
        "trigger_probability": 0.004,
        "timing_preferences": ["business_hours"],
        "cascade_probability": 0.25,
        "realistic_for": ["recurring_jobs", "periodic_failures", "testing_cycles"],
    },
    "marathon_incident": {
        "description": "Extended duration (1-3 days) with moderate-high magnitude (6-15x)",
        "category": "duration_patterns",
        "pattern_type": "marathon_event",
        "magnitude_range": [6.0, 15.0],
        "duration_range": [24, 72],  # hours
        "intensity_variation": 0.30,  # ±30% variation during event
        "recovery_pattern": "gradual_decline",
        "trigger_probability": 0.001,
        "timing_preferences": ["random"],
        "cascade_probability": 0.40,
        "realistic_for": ["major_incidents", "disaster_recovery", "large_migrations"],
    },
    # Timing & Cyclical Patterns
    "scheduled_load_event": {
        "description": "Predictable timing with high magnitude (8-20x) spikes",
        "category": "timing_cyclical_patterns",
        "pattern_type": "scheduled_event",
        "magnitude_range": [8.0, 20.0],
        "duration_range": [2, 8],  # hours
        "schedule_type": "weekly",  # or "monthly", "daily"
        "schedule_timing": "end_of_period",
        "timing_variance": 0.10,  # ±10% timing variation
        "trigger_probability": 0.95,  # High probability on scheduled days
        "cascade_probability": 0.05,
        "realistic_for": ["batch_jobs", "reporting_cycles", "scheduled_processing"],
    },
    "end_period_rush": {
        "description": "Month/quarter-end concentrated activity (5-12x) for 2-3 days",
        "category": "timing_cyclical_patterns",
        "pattern_type": "period_end_rush",
        "magnitude_range": [5.0, 12.0],
        "duration_range": [48, 72],  # hours
        "period_type": "monthly",  # or "quarterly"
        "days_before_end": [3, 1],  # Start 1-3 days before period end
        "trigger_probability": 0.80,  # High probability at period end
        "timing_preferences": ["business_hours"],
        "cascade_probability": 0.15,
        "realistic_for": [
            "financial_reporting",
            "compliance_deadlines",
            "period_end_processing",
        ],
    },
    "business_hours_incident": {
        "description": "Only occurs during business hours (9-5) with 4-15x magnitude",
        "category": "timing_cyclical_patterns",
        "pattern_type": "business_hours_only",
        "magnitude_range": [4.0, 15.0],
        "duration_range": [1, 6],  # hours
        "time_window": {"start": 9, "end": 17},  # 9 AM to 5 PM
        "timezone": "business_timezone",
        "trigger_probability": 0.006,  # Only during business hours
        "timing_preferences": ["business_hours"],
        "cascade_probability": 0.20,
        "realistic_for": [
            "user_driven_issues",
            "interactive_processing",
            "business_operations",
        ],
    },
    "weekend_maintenance_surge": {
        "description": "Scheduled weekend activity spikes (3-8x) for maintenance windows",
        "category": "timing_cyclical_patterns",
        "pattern_type": "weekend_maintenance",
        "magnitude_range": [3.0, 8.0],
        "duration_range": [4, 12],  # hours
        "weekend_days": ["saturday", "sunday"],
        "preferred_hours": [2, 8],  # 2 AM to 8 AM
        "trigger_probability": 0.30,  # 30% chance on weekends
        "timing_preferences": ["off_hours", "weekend"],
        "cascade_probability": 0.05,
        "realistic_for": ["maintenance_windows", "backup_operations", "system_updates"],
    },
    # Propagation Patterns
    "single_service_isolation": {
        "description": "Affects only one service/resource type with 8-25x magnitude",
        "category": "propagation_patterns",
        "pattern_type": "isolated_impact",
        "magnitude_range": [8.0, 25.0],
        "duration_range": [2, 12],  # hours
        "service_scope": "single",
        "isolation_factor": 1.0,  # No spread to other services
        "trigger_probability": 0.010,  # Higher probability due to isolation
        "cascade_probability": 0.05,  # Low cascade to other services
        "realistic_for": [
            "service_specific_issues",
            "isolated_failures",
            "single_component_problems",
        ],
    },
    "multi_service_cascade": {
        "description": "Spreads across multiple services with decreasing magnitude",
        "category": "propagation_patterns",
        "pattern_type": "cascade_spread",
        "initial_magnitude": [15.0, 30.0],
        "cascade_reduction": 0.60,  # Each service 60% of previous
        "affected_services": [3, 8],  # Number of services affected
        "spread_delay": [1, 3],  # hours between service impacts
        "duration_range": [6, 18],  # hours
        "trigger_probability": 0.003,
        "cascade_probability": 0.80,  # High internal cascade
        "realistic_for": [
            "dependency_failures",
            "resource_exhaustion",
            "cascading_systems",
        ],
    },
    "regional_propagation": {
        "description": "Starts in one region, spreads to others with 2-hour delays",
        "category": "propagation_patterns",
        "pattern_type": "regional_spread",
        "initial_magnitude": [12.0, 25.0],
        "propagation_delay": [1, 3],  # hours between regions
        "magnitude_decay": 0.70,  # Each region 70% of previous
        "affected_regions": [2, 5],
        "duration_range": [8, 24],  # hours
        "trigger_probability": 0.002,
        "cascade_probability": 0.90,  # High regional cascade
        "realistic_for": ["regional_failures", "network_issues", "dns_problems"],
    },
    "cross_account_overflow": {
        "description": "Affects multiple accounts/environments with varying magnitudes",
        "category": "propagation_patterns",
        "pattern_type": "account_overflow",
        "magnitude_range": [5.0, 20.0],
        "account_variation": 0.50,  # ±50% variation between accounts
        "affected_accounts": [2, 6],
        "duration_range": [4, 16],  # hours
        "trigger_probability": 0.003,
        "cascade_probability": 0.60,
        "realistic_for": [
            "shared_resources",
            "multi_tenant_issues",
            "cross_account_dependencies",
        ],
    },
    # Recovery Behavior Patterns
    "exponential_decay_recovery": {
        "description": "Smooth exponential return to baseline with 4-hour half-life",
        "category": "recovery_patterns",
        "pattern_type": "exponential_recovery",
        "initial_magnitude": [10.0, 30.0],
        "decay_half_life": [2, 6],  # hours
        "recovery_completeness": 0.95,  # 95% recovery to baseline
        "duration_range": [8, 24],  # hours
        "trigger_probability": 0.008,
        "cascade_probability": 0.10,
        "realistic_for": [
            "natural_recovery",
            "automatic_healing",
            "gradual_normalization",
        ],
    },
    "linear_recovery_ramp": {
        "description": "Steady linear recovery over 6-12 hours",
        "category": "recovery_patterns",
        "pattern_type": "linear_recovery",
        "initial_magnitude": [8.0, 25.0],
        "recovery_duration": [6, 12],  # hours
        "recovery_slope": "constant",
        "duration_range": [6, 12],  # hours
        "trigger_probability": 0.008,
        "cascade_probability": 0.10,
        "realistic_for": [
            "manual_recovery",
            "controlled_restoration",
            "progressive_fixes",
        ],
    },
    "stepped_recovery_phases": {
        "description": "Recovery in distinct phases: 30% → 60% → 85% → 100%",
        "category": "recovery_patterns",
        "pattern_type": "phased_recovery",
        "initial_magnitude": [12.0, 35.0],
        "recovery_phases": [0.30, 0.60, 0.85, 1.0],
        "phase_durations": [3, 4, 3, 2],  # hours for each phase
        "duration_range": [12, 15],  # total hours
        "trigger_probability": 0.006,
        "cascade_probability": 0.15,
        "realistic_for": [
            "staged_recovery",
            "service_restoration",
            "capacity_restoration",
        ],
    },
    "hunt_oscillation_recovery": {
        "description": "Overcorrection oscillations (±25%) during recovery process",
        "category": "recovery_patterns",
        "pattern_type": "oscillating_recovery",
        "initial_magnitude": [8.0, 20.0],
        "oscillation_amplitude": 0.25,  # ±25% oscillations
        "oscillation_frequency": 1.5,  # hours per oscillation
        "damping_rate": 0.15,  # Oscillations reduce by 15% each cycle
        "duration_range": [8, 18],  # hours
        "trigger_probability": 0.005,
        "cascade_probability": 0.25,
        "realistic_for": [
            "auto_scaling_recovery",
            "system_hunting",
            "feedback_corrections",
        ],
    },
}


def get_anomaly_profile(profile_name: str) -> dict:
    """Get a specific anomaly profile by name.

    Args:
        profile_name: Name of the anomaly profile

    Returns:
        Dictionary containing the profile data

    Raises:
        KeyError: If profile_name doesn't exist
    """
    if profile_name not in ANOMALY_PROFILES:
        available = list(ANOMALY_PROFILES.keys())
        raise KeyError(
            f"Anomaly profile '{profile_name}' not found. Available profiles: {available}"
        )

    return ANOMALY_PROFILES[profile_name]


def list_anomaly_profiles() -> list:
    """Get list of all available anomaly profile names.

    Returns:
        List of anomaly profile names
    """
    return list(ANOMALY_PROFILES.keys())


def get_anomaly_profiles_by_category(category: str = None) -> dict:
    """Get anomaly profiles filtered by category.

    Args:
        category: Optional category filter

    Returns:
        Dictionary of profiles (filtered if category specified)
    """
    if category is None:
        return ANOMALY_PROFILES

    return {
        name: profile
        for name, profile in ANOMALY_PROFILES.items()
        if profile.get("category") == category
    }


def get_anomaly_profile_categories() -> list:
    """Get list of all anomaly profile categories.

    Returns:
        List of unique category names
    """
    categories = set()
    for profile in ANOMALY_PROFILES.values():
        if "category" in profile:
            categories.add(profile["category"])
    return sorted(list(categories))


def get_anomaly_profile_info(profile_name: str) -> dict:
    """Get detailed information about an anomaly profile.

    Args:
        profile_name: Name of the anomaly profile

    Returns:
        Dictionary with profile statistics and details
    """
    profile = get_anomaly_profile(profile_name)

    return {
        "name": profile_name,
        "description": profile.get("description", "No description available"),
        "category": profile.get("category", "uncategorized"),
        "pattern_type": profile.get("pattern_type", "unknown"),
        "parameters": {
            k: v
            for k, v in profile.items()
            if k not in ["description", "category", "pattern_type", "realistic_for"]
        },
        "realistic_for": profile.get("realistic_for", []),
    }
