#!/usr/bin/env python3
"""
Field data processing examples for CAVORA.
Shows how to process real survey data.
"""

import numpy as np
import pandas as pd
from datetime import datetime
import json
import os

from cavora.survey import CompassParser, StationAnalysis, PassageModeling, ClosureError
from cavora.monitoring import CPDLInterface, TemperatureMonitor, CO2Monitor, WaterLevelMonitor
from cavora.parameters import VerticalPassage, LateralConduit, FlowstoneDeposition, CouplingDynamics
from cavora.prediction import StabilityEnvelopePredictor, FloodForecasting
from cavora.cdz import CDZDetector, CDZMapper


def example_1_load_survey_data():
    """Example 1: Load and process survey data from Compass format."""
    print("\n" + "="*60)
    print("Field Example 1: Loading Survey Data")
    print("="*60)
    
    # Create sample survey data (simulating a .dat file)
    sample_data = """# VIKOS GORGE CAVE - Survey 2024-12-15
A1 A2 15.5 45.0 5.0 2.0 3.0 4.0 2.0 ; Main passage
A2 A3 22.3 90.0 -2.0 3.0 4.0 5.0 3.0 ; Continuing
A3 A4 18.7 135.0 -8.0 2.5 3.5 4.5 2.5 ; Descending
A4 A1 35.2 225.0 -3.0 4.0 5.0 6.0 4.0 ; Loop closure
A3 B1 12.8 180.0 2.0 1.5 2.0 3.0 1.5 ; Side passage
"""
    
    # Save to temporary file
    with open('/tmp/sample_survey.dat', 'w') as f:
        f.write(sample_data)
    
    # Parse with CompassParser
    parser = CompassParser()
    survey_data = parser.parse_file('/tmp/sample_survey.dat')
    
    print(f"Survey Name: {survey_data.get('survey_name', 'Unnamed')}")
    print(f"Stations: {survey_data['n_stations']}")
    print(f"Shots: {survey_data['n_shots']}")
    print(f"Total Length: {survey_data['total_length']:.1f} m")
    
    # Show stations
    print("\nStations:")
    for station in survey_data['stations'][:3]:  # First 3 stations
        print(f"  {station['name']}: ({station['x']:.1f}, {station['y']:.1f}, {station['z']:.1f})")
    
    # Clean up
    os.remove('/tmp/sample_survey.dat')
    
    return survey_data


def example_2_analyze_station_network():
    """Example 2: Analyze survey station network."""
    print("\n" + "="*60)
    print("Field Example 2: Station Network Analysis")
    print("="*60)
    
    # Create station analyzer
    sa = StationAnalysis()
    
    # Add stations
    sa.add_station("ENT", 0, 0, 0, quality=0.98)
    sa.add_station("A1", 50, 30, -20, quality=0.95)
    sa.add_station("A2", 120, 80, -45, quality=0.92)
    sa.add_station("A3", 200, 150, -80, quality=0.88)
    sa.add_station("B1", 180, 120, -60, quality=0.90)
    sa.add_station("B2", 250, 180, -95, quality=0.85)
    sa.add_station("C1", 300, 220, -120, quality=0.82)
    
    # Add connections
    connections = [
        ("ENT", "A1", 60),
        ("A1", "A2", 85),
        ("A2", "A3", 95),
        ("A3", "B2", 70),
        ("B2", "C1", 65),
        ("A2", "B1", 45),
        ("B1", "B2", 50),
        ("A1", "B1", 110)
    ]
    
    for a, b, dist in connections:
        sa.add_connection(a, b, dist)
    
    # Analyze network
    network = sa.analyze_network()
    print(f"Network Analysis:")
    print(f"  Stations: {network['n_stations']}")
    print(f"  Shots: {network['n_shots']}")
    print(f"  Mean Degree: {network['mean_degree']}")
    print(f"  Most Central: {network['most_central_station']}")
    
    # Quality metrics
    quality = sa.calculate_quality_metrics()
    print(f"\nQuality Metrics:")
    print(f"  Overall Quality: {quality['overall_quality']:.2f}")
    
    # Hub stations
    hubs = sa.identify_hubs(threshold=3)
    print(f"\nHub Stations:")
    for hub in hubs:
        print(f"  {hub['name']}: {hub['connections']} connections")
    
    return sa


def example_3_process_sensor_data():
    """Example 3: Process continuous sensor data."""
    print("\n" + "="*60)
    print("Field Example 3: Sensor Data Processing")
    print("="*60)
    
    # Create CPDL interface
    cpdl = CPDLInterface()
    
    # Register sensors
    cpdl.register_sensor("T001", "temperature", "Main Passage", 0.01)
    cpdl.register_sensor("H001", "humidity", "Main Passage", 0.01)
    cpdl.register_sensor("C001", "co2", "Main Passage", 0.001)
    cpdl.register_sensor("W001", "water_level", "Sump Area", 0.001)
    
    # Generate sample sensor data (24 hours, 10-minute intervals)
    base_time = datetime.now().timestamp()
    n_readings = 144  # 24 hours * 6 per hour
    
    for i in range(n_readings):
        t = base_time + i * 600  # 10-minute intervals
        
        # Temperature with diurnal cycle
        temp = 11.5 + 0.2 * np.sin(2 * np.pi * i / 144) + 0.05 * np.random.randn()
        cpdl.add_reading("T001", t, temp)
        
        # Humidity
        hum = 95 + 2 * np.random.randn()
        cpdl.add_reading("H001", t, min(100, max(0, hum)))
        
        # CO2 (with spikes during survey activity)
        co2 = 850
        if 30 < i < 60:  # Survey period
            co2 += 200 * np.sin(2 * np.pi * (i-30) / 30)
        co2 += 30 * np.random.randn()
        cpdl.add_reading("C001", t, co2)
        
        # Water level (slow rise)
        level = 0.45 + 0.001 * i + 0.02 * np.random.randn()
        cpdl.add_reading("W001", t, level)
    
    # Get statistics
    temp_stats = cpdl.calculate_statistics("T001")
    co2_stats = cpdl.calculate_statistics("C001")
    
    print(f"Sensor Statistics:")
    print(f"  Temperature: {temp_stats['mean']:.1f}°C ±{temp_stats['std']:.1f}")
    print(f"  CO2: {co2_stats['mean']:.0f} ppm ±{co2_stats['std']:.0f}")
    print(f"  Total Readings: {cpdl.summary()['n_readings']}")
    
    # Detect anomalies
    anomalies = cpdl.detect_anomalies("C001", threshold_std=2.5)
    print(f"\nCO2 Anomalies Detected: {len(anomalies)}")
    
    return cpdl


def example_4_calculate_closure_errors():
    """Example 4: Calculate and analyze loop closure errors."""
    print("\n" + "="*60)
    print("Field Example 4: Loop Closure Analysis")
    print("="*60)
    
    # Create closure error analyzer
    ce = ClosureError(max_acceptable_error=0.5)
    
    # Add stations with intentional errors
    ce.add_station("A1", 0, 0, 0)
    ce.add_station("A2", 100, 2, -10)  # 2m error in y
    ce.add_station("A3", 195, 58, -22)  # 5m error in x
    ce.add_station("A4", 48, 63, -18)  # 2m error in y
    
    # Define connections
    connections = [
        ("A1", "A2"),
        ("A2", "A3"),
        ("A3", "A4"),
        ("A4", "A1")
    ]
    
    # Find loops
    loops = ce.find_loops(connections)
    print(f"Found {len(loops)} loops")
    
    # Analyze error distribution
    stats = ce.analyze_error_distribution()
    print(f"\nError Statistics:")
    print(f"  Grade: {stats['color']} {stats['survey_grade']}")
    print(f"  Mean Error: {stats['mean_error_percent']}%")
    print(f"  Max Error: {stats['max_error_percent']}%")
    
    # Worst loops
    worst = ce.identify_worst_loops(2)
    if worst:
        print(f"\nWorst Loops:")
        for w in worst:
            print(f"  • {w['stations']}: {w['error_percent']}% error")
    
    return ce


def example_5_create_passage_model():
    """Example 5: Create 3D passage model from survey data."""
    print("\n" + "="*60)
    print("Field Example 5: 3D Passage Modeling")
    print("="*60)
    
    # Create passage modeler
    pm = PassageModeling()
    
    # Add cross-sections along a passage
    stations = [
        ("A1", 0, 0, 0, 2.0, 3.0, 4.0, 2.0),
        ("A2", 20, 5, -10, 2.5, 3.5, 4.5, 2.5),
        ("A3", 40, 15, -22, 3.0, 4.0, 5.0, 3.0),
        ("A4", 60, 30, -35, 3.2, 4.2, 5.2, 3.2),
        ("A5", 80, 50, -50, 3.5, 4.5, 5.5, 3.5),
        ("A6", 100, 75, -68, 3.0, 4.0, 5.0, 3.0),
        ("A7", 120, 105, -85, 2.5, 3.5, 4.5, 2.5)
    ]
    
    for station, x, y, z, left, right, up, down in stations:
        pm.add_cross_section(station, x, y, z, left, right, up, down)
    
    # Get summary
    summary = pm.summary()
    print(f"Passage Summary:")
    print(f"  Length: {summary['length_m']} m")
    print(f"  Volume: {summary['volume_m3']} m³")
    print(f"  Mean Width: {summary['mean_width']} m")
    print(f"  Mean Height: {summary['mean_height']} m")
    
    # Identify passage type
    ptype = pm.identify_passage_type(pm.sections[0])
    print(f"\nPassage Type:")
    print(f"  {ptype['type']}: {ptype['description']}")
    
    return pm


def example_6_process_time_series():
    """Example 6: Process and analyze time series data."""
    print("\n" + "="*60)
    print("Field Example 6: Time Series Analysis")
    print("="*60)
    
    # Create monitors
    tm = TemperatureMonitor()
    cm = CO2Monitor()
    wm = WaterLevelMonitor()
    
    # Load sample data (simulating 30 days of data)
    base_time = datetime.now().timestamp() - 30 * 86400
    times = np.linspace(0, 30, 720)  # 30 days, hourly
    
    for t in times:
        timestamp = base_time + t * 86400
        
        # Temperature with daily cycle and trend
        temp = 11.5 + 0.5 * np.sin(2 * np.pi * t) + 0.02 * t + 0.1 * np.random.randn()
        tm.add_reading(timestamp, temp, "Main Passage", 50, "T001")
        
        # CO2 with survey events
        co2 = 850
        if 5 < t < 8 or 12 < t < 15 or 19 < t < 22:  # Survey periods
            co2 += 400
        co2 += 50 * np.random.randn()
        cm.add_reading(timestamp, co2, "Main Passage", 50, "C001")
        
        # Water level with flood event at day 15
        level = 0.45
        if 14.5 < t < 15.5:
            level += 2.0 * (1 - abs(t - 15))
        level += 0.05 * np.random.randn()
        wm.add_reading(timestamp, level, "Sump Area", "W001")
    
    # Analyze temperature
    temp_stats = tm.calculate_statistics("Main Passage")
    print(f"Temperature Statistics:")
    print(f"  Mean: {temp_stats['mean']}°C")
    print(f"  Range: {temp_stats['min']} - {temp_stats['max']}°C")
    
    # Detect CO2 events
    events = cm.detect_co2_event("Main Passage", threshold=1200)
    print(f"\nCO2 Events Detected: {len(events)}")
    for event in events[:3]:
        print(f"  • {event['duration_min']:.0f} min peak: {event['peak']} ppm")
    
    # Detect flood events
    floods = wm.detect_flood_events("Sump Area", threshold=1.0)
    print(f"\nFlood Events Detected: {len(floods)}")
    for flood in floods:
        print(f"  • Rise: {flood['rise_m']} m in {flood['duration_min']:.0f} min")
    
    return {'temperature': tm, 'co2': cm, 'water': wm}


def example_7_export_data():
    """Example 7: Export processed data to various formats."""
    print("\n" + "="*60)
    print("Field Example 7: Data Export")
    print("="*60)
    
    # Create sample data
    cpdl = CPDLInterface()
    cpdl.register_sensor("T001", "temperature", "Main Passage", 0.01)
    
    for i in range(100):
        cpdl.add_reading("T001", i * 3600, 11.5 + 0.2 * np.sin(i/10))
    
    # Export to CSV
    cpdl.export_to_csv("/tmp/sensor_data.csv")
    print("Exported to CSV: /tmp/sensor_data.csv")
    
    # Export to JSON
    cpdl.export_to_json("/tmp/sensor_data.json")
    print("Exported to JSON: /tmp/sensor_data.json")
    
    # Load back from CSV
    n_loaded = cpdl.load_from_csv("/tmp/sensor_data.csv")
    print(f"Loaded {n_loaded} readings from CSV")
    
    # Clean up
    os.remove("/tmp/sensor_data.csv")
    os.remove("/tmp/sensor_data.json")
    
    return cpdl


def example_8_complete_field_workflow():
    """Example 8: Complete field data processing workflow."""
    print("\n" + "="*60)
    print("Field Example 8: Complete Field Workflow")
    print("="*60)
    
    # Step 1: Load survey data
    print("\n1. Loading survey data...")
    parser = CompassParser()
    
    # Create sample survey
    sample_data = """# VIKOS GORGE - Survey 2024-12-15
ENT A1 25.5 45.0 -2.0 2.0 3.0 4.0 2.0
A1 A2 32.3 90.0 -5.0 3.0 4.0 5.0 3.0
A2 A3 28.7 135.0 -8.0 2.5 3.5 4.5 2.5
A3 B1 18.5 180.0 -3.0 2.0 2.5 3.5 2.0
B1 B2 22.0 225.0 -6.0 2.5 3.0 4.0 2.5
B2 ENT 45.0 315.0 -4.0 3.5 4.5 5.5 3.5
"""
    
    with open('/tmp/field_survey.dat', 'w') as f:
        f.write(sample_data)
    
    survey = parser.parse_file('/tmp/field_survey.dat')
    print(f"  Loaded {survey['n_stations']} stations, {survey['n_shots']} shots")
    
    # Step 2: Load sensor data
    print("\n2. Loading sensor data...")
    cpdl = CPDLInterface()
    cpdl.register_sensor("T001", "temperature", "Main Passage", 0.01)
    cpdl.register_sensor("C001", "co2", "Main Passage", 0.001)
    cpdl.register_sensor("W001", "water_level", "Sump Area", 0.001)
    
    # Generate sensor data
    base_time = datetime.now().timestamp() - 86400
    for i in range(144):  # 24 hours
        t = base_time + i * 600
        cpdl.add_reading("T001", t, 11.5 + 0.1 * np.sin(i/24))
        cpdl.add_reading("C001", t, 850 + 50 * np.sin(i/12))
        cpdl.add_reading("W001", t, 0.45 + 0.01 * np.sin(i/24))
    
    print(f"  Loaded {cpdl.summary()['n_readings']} sensor readings")
    
    # Step 3: Process VLF parameters
    print("\n3. Processing VLF parameters...")
    vp = VerticalPassage()
    lc = LateralConduit()
    fd = FlowstoneDeposition()
    
    # Add measurements from survey stations
    vp.add_measurement(2.8, 5.0, 2024.5, "A2")
    lc.add_measurement(3.2, 0.15, 0.45, 2024.5, "A2")
    fd.add_measurement(0.087, 0.087, 12, 2024.5, "A2")
    
    print(f"  V: {vp.measurements[-1].value:.2f} m")
    print(f"  L: {lc.measurements[-1].width:.2f} m")
    print(f"  F: {fd.measurements[-1].thickness:.3f} mm")
    
    # Step 4: Analyze stability
    print("\n4. Analyzing stability...")
    from cavora.parameters import PassageState
    from cavora.prediction import StabilityEnvelopePredictor
    
    state = PassageState(
        V=vp.measurements[-1].value,
        L=lc.measurements[-1].width,
        F=fd.measurements[-1].thickness,
        Q=lc.measurements[-1].discharge
    )
    
    predictor = StabilityEnvelopePredictor()
    envelope = predictor.predict_envelope((state.V, state.L, state.F), 1.0)
    
    print(f"  Stability Score: {envelope.probability*100:.1f}/100")
    print(f"  CDZ Proximity: {1-envelope.probability:.2%}")
    
    # Step 5: Check for CDZs
    print("\n5. Checking for CDZs...")
    detector = CDZDetector()
    
    # Generate sample V time series
    t = np.linspace(0, 5, 100)
    V = 2.5 + 0.3 * np.sin(t) + 0.05 * np.random.randn(100)
    
    cdzs = detector.detect_from_trajectory(t, V, location="Main Passage")
    print(f"  CDZs detected: {len(cdzs)}")
    
    # Step 6: Flood risk assessment
    print("\n6. Flood risk assessment...")
    ff = FloodForecasting()
    
    # Check current conditions
    risk = ff.detect_flood_risk(state.Q)
    print(f"  Current risk: {risk['color']} {risk['current_risk']}")
    print(f"  Evacuation needed: {risk['evacuation_needed']}")
    
    # Step 7: Generate report
    print("\n7. Generating report...")
    report = {
        'survey_name': survey['survey_name'],
        'date': datetime.now().isoformat(),
        'stations': survey['n_stations'],
        'total_length': survey['total_length'],
        'vlf_state': {
            'V': state.V,
            'L': state.L,
            'F': state.F,
            'Q': state.Q
        },
        'stability': {
            'score': envelope.probability * 100,
            'cdz_proximity': 1 - envelope.probability,
            'flood_risk': risk['current_risk']
        },
        'recommendations': []
    }
    
    if envelope.probability > 0.8:
        report['recommendations'].append("Standard survey protocol")
    elif envelope.probability > 0.6:
        report['recommendations'].append("Enhanced monitoring required")
    else:
        report['recommendations'].append("CDZ active - extreme caution")
    
    if risk['evacuation_needed']:
        report['recommendations'].append("IMMEDIATE EVACUATION")
    
    # Save report
    with open('/tmp/field_report.json', 'w') as f:
        json.dump(report, f, indent=2)
    
    print("  Report saved to: /tmp/field_report.json")
    print(f"\nFinal Recommendations:")
    for rec in report['recommendations']:
        print(f"  • {rec}")
    
    # Clean up
    os.remove('/tmp/field_survey.dat')
    
    return report


if __name__ == "__main__":
    print("="*60)
    print("CAVORA - Field Data Processing Examples")
    print("="*60)
    
    # Run examples
    example_1_load_survey_data()
    example_2_analyze_station_network()
    example_3_process_sensor_data()
    example_4_calculate_closure_errors()
    example_5_create_passage_model()
    example_6_process_time_series()
    example_7_export_data()
    example_8_complete_field_workflow()
    
    print("\n" + "="*60)
    print("All field examples completed successfully!")
    print("="*60)
