#!/usr/bin/env python3
"""
Advanced analysis examples for CAVORA.
"""

import numpy as np
import matplotlib.pyplot as plt
from cavora.core import CoupledVLFOscillator, LimitCycleDetector, PhaseSpaceReconstructor
from cavora.cdz import CDZDetector, CDZClassifier, CDZRiskAssessment
from cavora.prediction import FloodForecasting, StabilityEnvelopePredictor
from cavora.visualization import PhasePortraits, TimeSeriesPlots, StabilityMaps


def example_1_phase_space_reconstruction():
    """Example 1: Reconstruct phase space from time series."""
    print("\n" + "="*60)
    print("Advanced Example 1: Phase Space Reconstruction")
    print("="*60)
    
    # Generate sample data
    t = np.linspace(0, 50, 1000)
    V = 2.0 + 0.5 * np.sin(2 * np.pi * 0.05 * t) + 0.1 * np.random.randn(len(t))
    
    # Reconstruct phase space
    reconstructor = PhaseSpaceReconstructor(max_dimension=5)
    result = reconstructor.reconstruct(V, dt=t[1]-t[0])
    
    print(f"Embedding Dimension: {result['embedding_dimension']}")
    print(f"Time Delay: {result['time_delay_days']:.1f} days")
    print(f"Phase Space Points: {result['n_points']}")
    
    # Calculate Lyapunov exponents
    lyapunov = reconstructor.calculate_lyapunov_exponents(result['phase_space'], t[1]-t[0])
    print(f"\nLyapunov Exponents:")
    print(f"  λ_max = {lyapunov['lambda_max']:.4f}")
    print(f"  Interpretation: {lyapunov['interpretation']}")
    
    return result


def example_2_cdz_classification():
    """Example 2: Classify Creative Dissolution Zones."""
    print("\n" + "="*60)
    print("Advanced Example 2: CDZ Classification")
    print("="*60)
    
    # Generate sample data for a phreatic-vadose transition
    t = np.linspace(0, 5, 100)
    V = 2.0 + 0.8 * (1 - np.exp(-t/2))
    L = 3.0 - 0.4 * t
    F = 0.08 + 0.01 * t
    
    # Create classifier
    classifier = CDZClassifier()
    
    # Classify by transition
    transition = classifier.classify_by_transition(V, L, F, t)
    print(f"Transition Classification:")
    print(f"  Type: {transition.get('class_name', 'Unknown')}")
    print(f"  Hazard: {transition.get('color', '')} {transition.get('hazard_level', 'Unknown')}")
    
    # Classify spatially
    spatial = classifier.classify_spatial(V[-1]-V[0], L[-1]-L[0], F[-1]-F[0])
    print(f"\nSpatial Classification:")
    print(f"  Type: {spatial.get('class_name', 'Unknown')}")
    print(f"  V Contribution: {spatial.get('v_contribution', 0):.0%}")
    
    # Complete classification
    metadata = {
        'peak_divergence': 2.3,
        'duration_months': 3.5,
        'co2_flux': 650,
        'depth': 85,
        'water_distance': 3,
        'fracture_density': 2.8
    }
    
    complete = classifier.get_complete_classification(V, L, F, t, metadata)
    print(f"\nComplete Classification:")
    print(f"  Overall Hazard: {complete['overall_hazard']['color']} {complete['overall_hazard']['level']}")
    print(f"\nRecommendations:")
    for rec in complete['recommendations']:
        print(f"  • {rec}")
    
    return complete


def example_3_cdz_risk_assessment():
    """Example 3: Assess CDZ risk."""
    print("\n" + "="*60)
    print("Advanced Example 3: CDZ Risk Assessment")
    print("="*60)
    
    # Create risk assessor
    ra = CDZRiskAssessment()
    
    # Assess risk for a scenario
    assessment = ra.assess_risk(
        cdz_proximity=0.75,
        morphological_rate=0.35,
        co2_level=2800,
        water_level_rise=0.15,
        team_size=3,
        time_in_cave=5.5
    )
    
    print(f"Risk Assessment:")
    print(f"  Total Risk: {assessment['total_risk_score']}/100")
    print(f"  Level: {assessment['color']} {assessment['risk_level']}")
    print(f"  Protocol: {assessment['required_protocol']}")
    print(f"  Time Remaining: {assessment['time_remaining']} hours")
    
    print(f"\nComponent Risks:")
    for comp, data in assessment['components'].items():
        print(f"  {comp}: {data['level']} ({data['score']})")
    
    if assessment['warnings']:
        print(f"\nWarnings:")
        for warning in assessment['warnings']:
            print(f"  ⚠ {warning}")
    
    return assessment


def example_4_flood_scenario_analysis():
    """Example 4: Analyze multiple flood scenarios."""
    print("\n" + "="*60)
    print("Advanced Example 4: Flood Scenario Analysis")
    print("="*60)
    
    ff = FloodForecasting()
    
    # Different precipitation scenarios
    scenarios = {
        'Light Rain': [{'time': i, 'amount': 5} for i in range(0, 24, 6)],
        'Moderate Storm': [{'time': i, 'amount': 25} for i in range(0, 24, 6)],
        'Heavy Storm': [{'time': i, 'amount': 50} for i in range(0, 24, 6)],
        'Extreme Event': [{'time': i, 'amount': 100} for i in range(0, 24, 6)]
    }
    
    print("Flood Scenarios:")
    print("-" * 50)
    print(f"{'Scenario':<15} {'Peak Q':<10} {'Time to Peak':<12} {'Severity':<10}")
    print("-" * 50)
    
    for name, precip in scenarios.items():
        forecast = ff.forecast_from_precipitation(
            precip,
            current_discharge=0.15,
            current_level=0.45
        )
        print(f"{name:<15} {forecast.peak_discharge:<10.1f} {forecast.time_to_peak:<12.1f} {forecast.severity:<10}")
    
    return scenarios


def example_5_sensitivity_analysis():
    """Example 5: Sensitivity analysis of model parameters."""
    print("\n" + "="*60)
    print("Advanced Example 5: Parameter Sensitivity Analysis")
    print("="*60)
    
    # Base parameters
    base_params = {
        'mu_v': 0.15, 'mu_l': 0.10, 'mu_f': 0.05,
        'k_vf': 0.23, 'k_lf': -0.18, 'k_fv': 0.31, 'k_fl': -0.25
    }
    
    # Test variations
    variations = [0.5, 0.8, 1.0, 1.2, 1.5]  # Multipliers
    
    print("Sensitivity of Stability Score to Parameter Variations:")
    print("-" * 60)
    print(f"{'Parameter':<10} {'-50%':<8} {'-20%':<8} {'Base':<8} {'+20%':<8} {'+50%':<8}")
    print("-" * 60)
    
    # Test state
    state = (2.8, 3.2, 0.087)
    
    for param in ['mu_v', 'k_vf']:
        scores = []
        for mult in variations:
            # Modify parameter
            params = base_params.copy()
            params[param] = base_params[param] * mult
            
            # Create oscillator with modified parameters
            osc = CoupledVLFOscillator(**params)
            
            # Get stability
            stability = osc.get_stability_envelope(state)
            scores.append(stability['score'])
        
        print(f"{param:<10} {scores[0]:<8.1f} {scores[1]:<8.1f} {scores[2]:<8.1f} {scores[3]:<8.1f} {scores[4]:<8.1f}")
    
    return variations


def example_6_monte_carlo_simulation():
    """Example 6: Monte Carlo simulation for uncertainty quantification."""
    print("\n" + "="*60)
    print("Advanced Example 6: Monte Carlo Simulation")
    print("="*60)
    
    n_simulations = 1000
    results = []
    
    # Base state with uncertainty
    V_mean, L_mean, F_mean = 2.8, 3.2, 0.087
    V_std, L_std, F_std = 0.1, 0.15, 0.005
    
    print(f"Running {n_simulations} simulations...")
    
    osc = CoupledVLFOscillator()
    
    for i in range(n_simulations):
        # Sample with uncertainty
        V = np.random.normal(V_mean, V_std)
        L = np.random.normal(L_mean, L_std)
        F = np.random.normal(F_mean, F_std)
        
        # Ensure physical constraints
        V = max(0.1, V)
        L = max(0.1, L)
        F = max(0, F)
        
        # Get stability
        stability = osc.get_stability_envelope((V, L, F))
        results.append(stability['score'])
        
        if (i + 1) % 200 == 0:
            print(f"  Completed {i+1} simulations")
    
    results = np.array(results)
    
    print(f"\nResults:")
    print(f"  Mean Stability: {np.mean(results):.1f}/100")
    print(f"  Std Dev: {np.std(results):.1f}")
    print(f"  95% CI: [{np.percentile(results, 2.5):.1f}, {np.percentile(results, 97.5):.1f}]")
    print(f"  P(Stable >80): {np.mean(results > 80):.1%}")
    
    return results


def example_7_time_series_forecasting():
    """Example 7: Time series forecasting with confidence intervals."""
    print("\n" + "="*60)
    print("Advanced Example 7: Time Series Forecasting")
    print("="*60)
    
    # Generate historical data
    t_hist = np.linspace(0, 10, 100)
    V_hist = 2.5 + 0.3 * np.sin(0.5 * t_hist) + 0.05 * np.random.randn(len(t_hist))
    
    # Forecast future
    t_forecast = np.linspace(10, 15, 50)
    
    # Simple extrapolation with uncertainty
    from scipy import stats
    
    # Fit linear model
    slope, intercept, r_value, p_value, std_err = stats.linregress(t_hist, V_hist)
    
    # Forecast
    V_forecast = slope * t_forecast + intercept
    
    # Confidence intervals
    n = len(t_hist)
    t_stat = stats.t.ppf(0.975, n-2)
    
    # Prediction interval
    se = np.sqrt(np.sum((V_hist - (slope*t_hist + intercept))**2) / (n-2))
    se_pred = se * np.sqrt(1 + 1/n + (t_forecast - np.mean(t_hist))**2 / np.sum((t_hist - np.mean(t_hist))**2))
    
    lower = V_forecast - t_stat * se_pred
    upper = V_forecast + t_stat * se_pred
    
    print(f"Forecast Statistics:")
    print(f"  Trend: {slope:.4f} m/year")
    print(f"  R²: {r_value**2:.3f}")
    print(f"  Final Value: {V_forecast[-1]:.2f} ± {t_stat*se_pred[-1]:.2f} m")
    
    return {
        'historical': (t_hist, V_hist),
        'forecast': (t_forecast, V_forecast),
        'confidence': (lower, upper)
    }


def example_8_risk_matrix_analysis():
    """Example 8: Risk matrix for multiple hazards."""
    print("\n" + "="*60)
    print("Advanced Example 8: Risk Matrix Analysis")
    print("="*60)
    
    # Define hazards and their probabilities/impacts
    hazards = {
        'Flood': {'probability': 0.3, 'impact': 0.9, 'description': 'Rapid water level rise'},
        'CO₂ Accumulation': {'probability': 0.4, 'impact': 0.7, 'description': 'Respiratory hazard'},
        'Rockfall': {'probability': 0.2, 'impact': 0.95, 'description': 'Structural failure'},
        'CDZ Activity': {'probability': 0.25, 'impact': 0.8, 'description': 'Rapid morphological change'},
        'Equipment Failure': {'probability': 0.15, 'impact': 0.5, 'description': 'Loss of navigation'},
        'Team Fatigue': {'probability': 0.35, 'impact': 0.4, 'description': 'Reduced decision making'}
    }
    
    # Calculate risk scores
    print("Risk Matrix:")
    print("-" * 70)
    print(f"{'Hazard':<20} {'Probability':<12} {'Impact':<10} {'Risk Score':<12} {'Priority'}")
    print("-" * 70)
    
    risks = []
    for hazard, data in hazards.items():
        risk_score = data['probability'] * data['impact'] * 100
        
        if risk_score > 50:
            priority = "CRITICAL"
        elif risk_score > 30:
            priority = "HIGH"
        elif risk_score > 15:
            priority = "MEDIUM"
        else:
            priority = "LOW"
        
        risks.append({
            'hazard': hazard,
            'probability': data['probability'],
            'impact': data['impact'],
            'score': risk_score,
            'priority': priority,
            'description': data['description']
        })
    
    # Sort by risk score
    risks.sort(key=lambda x: x['score'], reverse=True)
    
    for r in risks:
        print(f"{r['hazard']:<20} {r['probability']:<12.1%} {r['impact']:<10.1f} {r['score']:<12.1f} {r['priority']}")
    
    print("\nTop Priority Risks:")
    for r in risks[:3]:
        print(f"  • {r['hazard']}: {r['description']} (Risk: {r['score']:.1f})")
    
    return risks


if __name__ == "__main__":
    print("="*60)
    print("CAVORA - Advanced Analysis Examples")
    print("="*60)
    
    # Run examples
    example_1_phase_space_reconstruction()
    example_2_cdz_classification()
    example_3_cdz_risk_assessment()
    example_4_flood_scenario_analysis()
    example_5_sensitivity_analysis()
    example_6_monte_carlo_simulation()
    example_7_time_series_forecasting()
    example_8_risk_matrix_analysis()
    
    print("\n" + "="*60)
    print("All advanced examples completed successfully!")
    print("="*60)
