#!/usr/bin/env python3
"""
PrecipGen Convenience API Tutorial

This tutorial demonstrates the complete workflow from location input to publication-ready
precipitation analysis using the PrecipGen Convenience API. The convenience API automates
the entire process that previously required 350+ lines of custom code.

Author: PrecipGen Development Team
Version: 0.1.3
"""

import os
from pathlib import Path
from precipgen.convenience import ConvenienceAPI, BatchProcessor
from precipgen.convenience.config import TemplateConfig, OutputConfig, AnalysisConfig
from precipgen.convenience.templates.template_examples import get_template_config

def tutorial_1_basic_usage():
    """
    Tutorial 1: Basic Usage - Single Function Call
    
    The simplest way to use the convenience API is with a single function call
    that handles everything from location to publication-ready results.
    """
    print("=" * 60)
    print("Tutorial 1: Basic Usage")
    print("=" * 60)
    
    # Initialize the convenience API
    api = ConvenienceAPI()
    
    # Analyze precipitation for a location with a single function call
    print("Analyzing precipitation for Seattle, WA...")
    
    try:
        result = api.analyze_precipitation("Seattle, WA")
        
        print(f"✅ Analysis completed successfully!")
        print(f"   Station: {result.station_info.name} ({result.station_info.id})")
        print(f"   Data years: {result.station_info.data_years}")
        print(f"   Validation score: {result.validation_report.validation_score:.1%}")
        print(f"   Report saved to: {result.html_report}")
        
        if result.has_trends:
            print(f"   🔍 Trends detected: {len(result.trend_analysis.significant_parameters)} parameters")
        else:
            print(f"   📊 No significant trends detected")
            
    except Exception as e:
        print(f"❌ Analysis failed: {e}")
        print("   This might be due to network connectivity or data availability")

def tutorial_2_interactive_station_selection():
    """
    Tutorial 2: Interactive Station Selection
    
    Sometimes you want to review and select from multiple candidate stations
    before running the full analysis.
    """
    print("\n" + "=" * 60)
    print("Tutorial 2: Interactive Station Selection")
    print("=" * 60)
    
    api = ConvenienceAPI()
    
    # Step 1: Discover candidate stations
    print("Discovering stations near Portland, OR...")
    
    try:
        candidates = api.discover_stations("Portland, OR")
        
        print(f"Found {len(candidates)} candidate stations:")
        for i, candidate in enumerate(candidates[:5]):  # Show top 5
            print(f"  {i+1}. {candidate.name} ({candidate.id})")
            print(f"     Distance: {candidate.distance_km:.1f} km")
            print(f"     Data: {candidate.first_year}-{candidate.last_year} ({candidate.data_years} years)")
            print(f"     Quality: {candidate.quality_score:.1%}")
            print(f"     Completeness: {candidate.data_completeness:.1%}")
            print()
        
        # Step 2: Preview the top station
        if candidates:
            top_station = candidates[0]
            print(f"Previewing data for top station: {top_station.name}")
            
            preview = api.preview_station_data(top_station.id)
            print(f"   Recommendation: {preview.recommendation}")
            print(f"   Notes: {', '.join(preview.notes[:2])}")
            
            # Step 3: Run analysis with selected station
            print(f"\nRunning full analysis with {top_station.name}...")
            result = api.analyze_precipitation(
                location="Portland, OR",
                station_id=top_station.id
            )
            
            print(f"✅ Analysis completed!")
            print(f"   Report: {result.html_report}")
            
    except Exception as e:
        print(f"❌ Station discovery failed: {e}")

def tutorial_3_custom_configuration():
    """
    Tutorial 3: Custom Analysis Configuration
    
    Demonstrates how to customize the analysis parameters, output settings,
    and template configuration for specific use cases.
    """
    print("\n" + "=" * 60)
    print("Tutorial 3: Custom Configuration")
    print("=" * 60)
    
    # Custom analysis configuration
    analysis_config = AnalysisConfig(
        min_years_data=20,              # Require at least 20 years
        search_radius_km=75,            # Expand search radius
        wet_day_threshold=0.5,          # Higher threshold for wet days
        trend_window_years=25,          # Shorter trend analysis window
        validation_realizations=200,    # More validation runs
        parallel_execution=True         # Enable parallel processing
    )
    
    # Custom output configuration
    output_config = OutputConfig(
        base_output_dir="./custom_analysis",
        organize_by_location=True,
        create_timestamped_dirs=False,
        use_location_in_filename=True,
        use_timestamp_in_filename=False
    )
    
    # Custom template configuration for engineering report
    template_config = get_template_config("engineering")
    template_config.custom_variables.update({
        "project_number": "DEMO-2024-001",
        "client": "Tutorial User",
        "engineer": "PrecipGen Tutorial System"
    })
    
    # Initialize API with custom configurations
    api = ConvenienceAPI()
    
    print("Running analysis with custom configuration...")
    print(f"  - Minimum data years: {analysis_config.min_years_data}")
    print(f"  - Search radius: {analysis_config.search_radius_km} km")
    print(f"  - Validation runs: {analysis_config.validation_realizations}")
    print(f"  - Output directory: {output_config.base_output_dir}")
    
    try:
        result = api.analyze_precipitation(
            location="San Francisco, CA",
            analysis_config=analysis_config,
            output_config=output_config,
            template_config=template_config
        )
        
        print(f"✅ Custom analysis completed!")
        print(f"   Station: {result.station_info.name}")
        print(f"   Template used: {template_config.template_name}")
        print(f"   Report: {result.html_report}")
        
    except Exception as e:
        print(f"❌ Custom analysis failed: {e}")

def tutorial_4_batch_processing():
    """
    Tutorial 4: Batch Processing Multiple Locations
    
    Demonstrates how to analyze multiple locations in a single operation
    with comprehensive error handling and summary generation.
    """
    print("\n" + "=" * 60)
    print("Tutorial 4: Batch Processing")
    print("=" * 60)
    
    # Define multiple locations for analysis
    locations = [
        "Seattle, WA",
        "Portland, OR", 
        "San Francisco, CA",
        "Los Angeles, CA",
        (47.6062, -122.3321),  # Seattle coordinates
        "Vancouver, BC"         # This might fail (international)
    ]
    
    # Configure batch processing
    from precipgen.convenience.config import BatchConfig
    
    batch_config = BatchConfig(
        parallel_execution=True,
        max_workers=3,                    # Limit concurrent analyses
        continue_on_error=True,           # Don't stop on individual failures
        save_intermediate_results=True,   # Save results as they complete
        generate_summary_report=True      # Create cross-location summary
    )
    
    # Configure template for batch reports
    template_config = get_template_config("batch")
    template_config.custom_variables["analysis_purpose"] = "Regional Climate Assessment"
    
    # Initialize batch processor
    processor = BatchProcessor()
    
    print(f"Processing {len(locations)} locations...")
    print("Locations:")
    for i, loc in enumerate(locations, 1):
        print(f"  {i}. {loc}")
    
    try:
        # Run batch analysis
        batch_results = processor.analyze_multiple_locations(
            locations=locations,
            batch_config=batch_config,
            template_config=template_config
        )
        
        print(f"\n✅ Batch processing completed!")
        print(f"   Successful analyses: {batch_results.batch_summary.successful_analyses}")
        print(f"   Failed analyses: {batch_results.batch_summary.failed_analyses}")
        print(f"   Success rate: {batch_results.success_rate:.1%}")
        print(f"   Processing time: {batch_results.batch_summary.processing_time:.1f} seconds")
        
        if batch_results.batch_summary.successful_analyses > 0:
            print(f"   Summary report: {batch_results.summary_report_path}")
            print(f"   Index report: {batch_results.index_report_path}")
        
        # Show failed locations if any
        if batch_results.failed_locations:
            print("\n❌ Failed locations:")
            for location, error in batch_results.failed_locations:
                print(f"   - {location}: {error.__class__.__name__}")
        
        # Show regional insights if available
        if batch_results.batch_summary.recommendations:
            print("\n🔍 Key insights:")
            for insight in batch_results.batch_summary.recommendations[:3]:
                print(f"   - {insight}")
                
    except Exception as e:
        print(f"❌ Batch processing failed: {e}")

def tutorial_5_template_customization():
    """
    Tutorial 5: Template Customization
    
    Demonstrates how to create custom report templates and modify
    existing templates for specific branding or content requirements.
    """
    print("\n" + "=" * 60)
    print("Tutorial 5: Template Customization")
    print("=" * 60)
    
    # Example 1: Scientific publication template
    scientific_config = get_template_config("scientific")
    scientific_config.custom_variables.update({
        "author": "Dr. Climate Researcher",
        "institution": "University of Weather Sciences",
        "journal": "Journal of Applied Climatology",
        "manuscript_id": "JAC-2024-0123"
    })
    
    # Example 2: Minimal dashboard template
    minimal_config = get_template_config("minimal")
    
    # Example 3: Custom branded template
    branded_config = TemplateConfig(
        template_name="default_report",
        include_executive_summary=True,
        include_trend_analysis=True,
        include_validation_details=True,
        include_plots=True,
        embed_plots=True,
        custom_variables={
            "organization": "Climate Solutions Inc.",
            "report_type": "Climate Assessment",
            "confidentiality": "Internal Use Only"
        },
        custom_css="""
            .header {
                background: linear-gradient(135deg, #2E8B57 0%, #228B22 100%);
                color: white;
            }
            .section h2 {
                color: #2E8B57;
                border-bottom: 2px solid #228B22;
            }
            .trend-summary {
                background: #F0FFF0;
                border-left: 4px solid #228B22;
            }
        """,
        custom_header="""
            <div style="background: #F0FFF0; padding: 15px; text-align: center; border: 2px solid #228B22;">
                <h3 style="margin: 0; color: #2E8B57;">🌿 Climate Solutions Inc.</h3>
                <p style="margin: 5px 0 0 0; color: #666;">Sustainable Climate Analysis</p>
            </div>
        """,
        custom_footer="""
            <div style="background: #2E8B57; color: white; padding: 15px; text-align: center;">
                <p><strong>Climate Solutions Inc.</strong> | Confidential Report</p>
                <p>📧 contact@climatesolutions.com | 🌐 www.climatesolutions.com</p>
            </div>
        """
    )
    
    api = ConvenienceAPI()
    
    print("Demonstrating different template styles...")
    
    # Test location
    test_location = "Denver, CO"
    
    templates_to_test = [
        ("Scientific", scientific_config),
        ("Minimal", minimal_config),
        ("Branded", branded_config)
    ]
    
    for template_name, config in templates_to_test:
        print(f"\nGenerating {template_name} report...")
        
        try:
            result = api.analyze_precipitation(
                location=test_location,
                template_config=config
            )
            
            print(f"   ✅ {template_name} report generated: {Path(result.html_report).name}")
            
        except Exception as e:
            print(f"   ❌ {template_name} report failed: {e}")

def tutorial_6_workflow_patterns():
    """
    Tutorial 6: Advanced Workflow Patterns
    
    Demonstrates advanced usage patterns including error handling,
    fallback strategies, and integration with existing workflows.
    """
    print("\n" + "=" * 60)
    print("Tutorial 6: Advanced Workflow Patterns")
    print("=" * 60)
    
    api = ConvenienceAPI()
    
    # Pattern 1: Robust analysis with fallbacks
    print("Pattern 1: Robust Analysis with Fallbacks")
    
    def robust_analysis(location, max_retries=3):
        """Analyze with automatic fallbacks and retries."""
        
        for attempt in range(max_retries):
            try:
                print(f"  Attempt {attempt + 1}: Analyzing {location}")
                
                # Try with progressively relaxed requirements
                analysis_config = AnalysisConfig(
                    min_years_data=max(10, 25 - attempt * 5),  # Relax data requirements
                    search_radius_km=50 + attempt * 25,        # Expand search radius
                    validation_realizations=max(50, 100 - attempt * 25)  # Reduce validation load
                )
                
                result = api.analyze_precipitation(
                    location=location,
                    analysis_config=analysis_config
                )
                
                print(f"  ✅ Success on attempt {attempt + 1}")
                return result
                
            except Exception as e:
                print(f"  ❌ Attempt {attempt + 1} failed: {e}")
                if attempt == max_retries - 1:
                    print(f"  🚫 All attempts failed for {location}")
                    return None
        
        return None
    
    # Test robust analysis
    test_locations = ["Phoenix, AZ", "Miami, FL"]
    
    for location in test_locations:
        result = robust_analysis(location)
        if result:
            print(f"     Final result: {result.station_info.name} ({result.station_info.data_years} years)")
    
    # Pattern 2: Quality-based station selection
    print(f"\nPattern 2: Quality-Based Station Selection")
    
    def select_best_quality_station(location, min_quality=0.8):
        """Select station based on data quality criteria."""
        
        try:
            candidates = api.discover_stations(location)
            
            # Filter by quality
            quality_stations = [
                s for s in candidates 
                if s.quality_score >= min_quality and s.data_years >= 20
            ]
            
            if quality_stations:
                best_station = quality_stations[0]  # Already sorted by ranking
                print(f"  Selected: {best_station.name} (Quality: {best_station.quality_score:.1%})")
                return best_station.id
            else:
                print(f"  No stations meet quality criteria (>= {min_quality:.1%})")
                return None
                
        except Exception as e:
            print(f"  Station selection failed: {e}")
            return None
    
    # Test quality-based selection
    station_id = select_best_quality_station("Austin, TX", min_quality=0.85)
    if station_id:
        print(f"     Would use station: {station_id}")
    
    # Pattern 3: Conditional analysis based on data availability
    print(f"\nPattern 3: Conditional Analysis")
    
    def conditional_analysis(location):
        """Run different analysis types based on data availability."""
        
        try:
            # First, check data availability
            candidates = api.discover_stations(location)
            
            if not candidates:
                print(f"  No stations found for {location}")
                return None
            
            best_candidate = candidates[0]
            
            # Choose analysis type based on data characteristics
            if best_candidate.data_years >= 30:
                print(f"  Long record available: Full trend analysis")
                analysis_config = AnalysisConfig(trend_window_years=30)
            elif best_candidate.data_years >= 20:
                print(f"  Moderate record: Limited trend analysis")
                analysis_config = AnalysisConfig(trend_window_years=20)
            else:
                print(f"  Short record: Stationary analysis only")
                analysis_config = AnalysisConfig(trend_window_years=None)
            
            # Run analysis with appropriate configuration
            result = api.analyze_precipitation(
                location=location,
                station_id=best_candidate.id,
                analysis_config=analysis_config
            )
            
            print(f"  ✅ Analysis completed: {result.station_info.data_years} years of data")
            return result
            
        except Exception as e:
            print(f"  Conditional analysis failed: {e}")
            return None
    
    # Test conditional analysis
    test_location = "Salt Lake City, UT"
    result = conditional_analysis(test_location)

def main():
    """
    Run all tutorials in sequence.
    
    This function demonstrates the complete range of PrecipGen Convenience API
    capabilities from basic usage to advanced workflow patterns.
    """
    print("PrecipGen Convenience API Tutorial")
    print("Version 0.1.3")
    print("=" * 60)
    print()
    print("This tutorial demonstrates the complete workflow from location input")
    print("to publication-ready precipitation analysis using the Convenience API.")
    print()
    print("Note: Some examples may fail due to network connectivity or data")
    print("availability. This is normal and demonstrates error handling.")
    print()
    
    # Create output directory
    output_dir = Path("./tutorial_output")
    output_dir.mkdir(exist_ok=True)
    print(f"Tutorial outputs will be saved to: {output_dir.absolute()}")
    print()
    
    # Run tutorials
    try:
        tutorial_1_basic_usage()
        tutorial_2_interactive_station_selection()
        tutorial_3_custom_configuration()
        tutorial_4_batch_processing()
        tutorial_5_template_customization()
        tutorial_6_workflow_patterns()
        
        print("\n" + "=" * 60)
        print("Tutorial completed!")
        print("=" * 60)
        print()
        print("Next steps:")
        print("1. Check the generated reports in the output directories")
        print("2. Explore the template customization examples")
        print("3. Try the convenience API with your own locations")
        print("4. Review the full documentation for advanced features")
        print()
        print("For more information:")
        print("- API Documentation: docs/api_reference.md")
        print("- Template Guide: precipgen/convenience/templates/template_examples.py")
        print("- Mathematical Foundation: docs/mathematical_foundation.md")
        
    except KeyboardInterrupt:
        print("\n\nTutorial interrupted by user.")
    except Exception as e:
        print(f"\n\nTutorial failed with unexpected error: {e}")
        print("This might be due to network connectivity or missing dependencies.")

if __name__ == "__main__":
    main()