"""
Simulation Workflow Testing for PrecipGen.

This module tests the simulation workflow components including:
- Simulation engine initialization with ParameterManifest
- Random seed handling and state consistency
- Trend mode initialization and parameter application
- Daily precipitation generation with step() and generate() methods
- Extended simulation runs for stability
- Synthetic data statistical properties validation
- Output statistics calculation (monthly, annual, seasonal)
- Simulation metadata generation and storage

Tests validate Requirements 4.1-4.3 for the simulation workflow.
"""

import pytest
import tempfile
import shutil
from pathlib import Path
from typing import List, Dict, Optional, Tuple, Union, Any
from unittest.mock import Mock, patch, MagicMock
import pandas as pd
import numpy as np
from datetime import datetime, timedelta, timedelta
from hypothesis import given, strategies as st, assume, settings, HealthCheck

from tests.workflow_testing.infrastructure.directory_manager import DirectoryManager
from tests.workflow_testing.infrastructure.test_logger import WorkflowTestLogger
from precipgen.engines.simulation import SimulationEngine, SimulationState
from precipgen.engines.analytical import ParameterManifest, MonthlyParams, TrendAnalysis
from precipgen.utils.exceptions import SimulationEngineError, StateError, BoundsError


# Hypothesis strategies for generating test data
@st.composite
def valid_monthly_params(draw):
    """Generate valid monthly parameters for testing."""
    p_ww = draw(st.floats(min_value=0.0, max_value=1.0))
    p_wd = draw(st.floats(min_value=0.0, max_value=1.0))
    alpha = draw(st.floats(min_value=0.1, max_value=10.0))
    beta = draw(st.floats(min_value=0.1, max_value=100.0))
    
    return MonthlyParams(p_ww=p_ww, p_wd=p_wd, alpha=alpha, beta=beta)


@st.composite
def valid_parameter_manifest(draw):
    """Generate valid parameter manifest for testing."""
    # Generate parameters for all 12 months
    overall_parameters = {}
    for month in range(1, 13):
        overall_parameters[month] = draw(valid_monthly_params())
    
    metadata = {
        'analysis_date': datetime.now().isoformat(),
        'data_period': ['2000-01-01', '2020-12-31'],
        'wet_day_threshold': 0.1,
        'data_completeness': draw(st.floats(min_value=0.8, max_value=1.0)),
        'total_data_points': draw(st.integers(min_value=1000, max_value=10000))
    }
    
    return ParameterManifest(
        metadata=metadata,
        overall_parameters=overall_parameters,
        trend_analysis=None,
        sliding_window_stats=None
    )


@st.composite
def random_seeds(draw):
    """Generate random seeds for testing."""
    return draw(st.integers(min_value=0, max_value=2**31 - 1))


@st.composite
def simulation_days(draw):
    """Generate number of simulation days for testing."""
    return draw(st.integers(min_value=1, max_value=1000))


@st.composite
def extended_simulation_days(draw):
    """Generate extended simulation days for stability testing."""
    return draw(st.integers(min_value=10000, max_value=50000))


class SimulationInitializationTester:
    """
    Tester for simulation engine initialization and WGEN engine setup.
    
    Tests SimulationEngine initialization with ParameterManifest, validates
    random seed handling and state consistency, and tests trend mode 
    initialization and parameter application.
    """
    
    def __init__(self, cache_dir: Optional[str] = None):
        """
        Initialize simulation initialization tester.
        
        Args:
            cache_dir: Directory for caching test data
        """
        self.logger = WorkflowTestLogger("simulation_initialization_tester")
        self.cache_dir = cache_dir or tempfile.mkdtemp(prefix="precipgen_sim_test_")
        self.directory_manager = DirectoryManager(base_dir=self.cache_dir)
        
    def test_basic_initialization(self, parameter_manifest: ParameterManifest,
                                random_seed: Optional[int] = None) -> bool:
        """
        Test basic SimulationEngine initialization with ParameterManifest.
        
        Args:
            parameter_manifest: Parameter manifest for initialization
            random_seed: Optional random seed for reproducibility
            
        Returns:
            True if initialization successful, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize simulation engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate initialization
            success = (
                engine.parameters is not None and
                engine.parameters == parameter_manifest and
                engine.trend_mode == False and
                engine.random_state is not None
            )
            
            # Test state retrieval
            state = engine.get_state()
            state_valid = (
                isinstance(state, dict) and
                'trend_mode' in state and
                'random_state' in state
            )
            
            success = success and state_valid
            
            self.logger.log_test_result(
                f"basic_initialization_seed_{random_seed}",
                success,
                execution_time,
                details={
                    "random_seed": random_seed,
                    "trend_mode": False,
                    "parameters_count": len(parameter_manifest.overall_parameters),
                    "state_valid": state_valid
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "basic_initialization")
            return False
    
    def test_trend_mode_initialization(self, parameter_manifest: ParameterManifest,
                                     random_seed: Optional[int] = None) -> bool:
        """
        Test SimulationEngine initialization with trend mode enabled.
        
        Args:
            parameter_manifest: Parameter manifest for initialization
            random_seed: Optional random seed for reproducibility
            
        Returns:
            True if trend mode initialization successful, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize simulation engine with trend mode
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=True,
                random_seed=random_seed
            )
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate trend mode initialization
            success = (
                engine.parameters is not None and
                engine.trend_mode == True and
                engine.random_state is not None
            )
            
            # Test trend projection info
            trend_info = engine.get_trend_projection_info()
            trend_info_valid = (
                isinstance(trend_info, dict) and
                'trend_mode_enabled' in trend_info and
                trend_info['trend_mode_enabled'] == True
            )
            
            success = success and trend_info_valid
            
            self.logger.log_test_result(
                f"trend_mode_initialization_seed_{random_seed}",
                success,
                execution_time,
                details={
                    "random_seed": random_seed,
                    "trend_mode": True,
                    "trend_info_valid": trend_info_valid,
                    "trend_analysis_available": trend_info.get('trend_analysis_available', False)
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "trend_mode_initialization")
            return False
    
    def test_random_seed_consistency(self, parameter_manifest: ParameterManifest,
                                   random_seed: int, num_tests: int = 5) -> bool:
        """
        Test that random seed produces consistent initialization and behavior.
        
        Args:
            parameter_manifest: Parameter manifest for initialization
            random_seed: Random seed for consistency testing
            num_tests: Number of consistency tests to run
            
        Returns:
            True if random seed behavior is consistent, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize multiple engines with same seed
            engines = []
            initial_states = []
            
            for i in range(num_tests):
                engine = SimulationEngine(
                    parameters=parameter_manifest,
                    trend_mode=False,
                    random_seed=random_seed
                )
                engines.append(engine)
                initial_states.append(engine.get_state())
            
            # Check that all engines have identical initial random states
            first_random_state = initial_states[0]['random_state']
            states_consistent = all(
                np.array_equal(state['random_state'][1], first_random_state[1])  # Compare the actual state array
                for state in initial_states
            )
            
            # Initialize engines and generate a few steps
            start_date = datetime(2025, 1, 1)
            generated_values = []
            
            for engine in engines:
                engine.initialize(start_date, initial_wet_state=False)
                values = []
                for _ in range(10):  # Generate 10 days
                    values.append(engine.step())
                generated_values.append(values)
            
            # Check that all engines generated identical sequences
            first_sequence = generated_values[0]
            sequences_consistent = all(
                sequence == first_sequence 
                for sequence in generated_values
            )
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            success = states_consistent and sequences_consistent
            
            self.logger.log_test_result(
                f"random_seed_consistency_{random_seed}",
                success,
                execution_time,
                details={
                    "random_seed": random_seed,
                    "num_tests": num_tests,
                    "states_consistent": states_consistent,
                    "sequences_consistent": sequences_consistent,
                    "first_10_values": first_sequence
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "random_seed_consistency")
            return False
    
    def test_state_consistency(self, parameter_manifest: ParameterManifest,
                             random_seed: int = 42) -> bool:
        """
        Test that simulation engine maintains consistent state across operations.
        
        Args:
            parameter_manifest: Parameter manifest for initialization
            random_seed: Random seed for reproducibility
            
        Returns:
            True if state consistency is maintained, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            # Test initial state
            initial_state = engine.get_state()
            
            # Initialize simulation
            start_date = datetime(2025, 1, 1)
            engine.initialize(start_date, initial_wet_state=False)
            
            # Get state after initialization
            initialized_state = engine.get_state()
            
            # Verify state changes appropriately
            state_changed_correctly = (
                initialized_state['current_date'] is not None and
                initialized_state['elapsed_days'] == 0 and
                initialized_state != initial_state
            )
            
            # Generate some steps and check state evolution
            for i in range(5):
                engine.step()
                current_state = engine.get_state()
                
                # Verify elapsed days increment
                if current_state['elapsed_days'] != i + 1:
                    state_changed_correctly = False
                    break
            
            # Test reset functionality
            engine.reset()
            reset_state = engine.get_state()
            
            # Verify reset worked correctly
            reset_successful = (
                reset_state['elapsed_days'] == 0 and
                reset_state['current_date'] == start_date.isoformat()
            )
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            success = state_changed_correctly and reset_successful
            
            self.logger.log_test_result(
                f"state_consistency_{random_seed}",
                success,
                execution_time,
                details={
                    "random_seed": random_seed,
                    "state_changed_correctly": state_changed_correctly,
                    "reset_successful": reset_successful,
                    "final_elapsed_days": reset_state['elapsed_days']
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "state_consistency")
            return False
    
    def test_parameter_validation(self, parameter_manifest: ParameterManifest) -> bool:
        """
        Test parameter validation during initialization.
        
        Args:
            parameter_manifest: Parameter manifest to validate
            
        Returns:
            True if parameter validation works correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Test with valid parameters
            try:
                engine = SimulationEngine(
                    parameters=parameter_manifest,
                    trend_mode=False,
                    random_seed=42
                )
                valid_params_accepted = True
            except Exception:
                valid_params_accepted = False
            
            # Test with invalid parameters (None)
            try:
                engine_none = SimulationEngine(
                    parameters=None,
                    trend_mode=False,
                    random_seed=42
                )
                none_params_rejected = False  # Should have raised exception
            except Exception:
                none_params_rejected = True  # Expected behavior
            
            # Test with invalid parameter values
            invalid_manifest = ParameterManifest(
                metadata={'test': True},
                overall_parameters={
                    1: MonthlyParams(p_ww=-0.5, p_wd=1.5, alpha=-1.0, beta=0.0)  # Invalid values
                },
                trend_analysis=None,
                sliding_window_stats=None
            )
            
            try:
                engine_invalid = SimulationEngine(
                    parameters=invalid_manifest,
                    trend_mode=False,
                    random_seed=42
                )
                invalid_params_rejected = False  # Should have raised exception
            except Exception:
                invalid_params_rejected = True  # Expected behavior
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            success = valid_params_accepted and none_params_rejected and invalid_params_rejected
            
            self.logger.log_test_result(
                "parameter_validation",
                success,
                execution_time,
                details={
                    "valid_params_accepted": valid_params_accepted,
                    "none_params_rejected": none_params_rejected,
                    "invalid_params_rejected": invalid_params_rejected
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "parameter_validation")
            return False
    
    def test_initialization_error_handling(self) -> bool:
        """
        Test error handling during initialization with various invalid inputs.
        
        Returns:
            True if error handling works correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            error_cases_handled = 0
            total_error_cases = 0
            
            # Test case 1: None parameters
            total_error_cases += 1
            try:
                engine = SimulationEngine(parameters=None, trend_mode=False)
                # Should not reach here
            except Exception as e:
                if "parameter" in str(e).lower():
                    error_cases_handled += 1
            
            # Test case 2: Empty parameter manifest
            total_error_cases += 1
            try:
                empty_manifest = ParameterManifest(
                    metadata={},
                    overall_parameters={},  # Empty parameters
                    trend_analysis=None,
                    sliding_window_stats=None
                )
                engine = SimulationEngine(parameters=empty_manifest, trend_mode=False)
                # Should not reach here
            except Exception as e:
                if any(keyword in str(e).lower() for keyword in ["parameter", "missing", "empty"]):
                    error_cases_handled += 1
            
            # Test case 3: Invalid initialization date
            total_error_cases += 1
            try:
                # Create valid engine first with complete 12-month parameters
                valid_manifest = ParameterManifest(
                    metadata={'test': True},
                    overall_parameters={
                        month: MonthlyParams(p_ww=0.5, p_wd=0.3, alpha=1.0, beta=5.0)
                        for month in range(1, 13)
                    },
                    trend_analysis=None,
                    sliding_window_stats=None
                )
                engine = SimulationEngine(parameters=valid_manifest, trend_mode=False)
                
                # Try to initialize with invalid date
                engine.initialize("invalid_date", initial_wet_state=False)
                # Should not reach here
            except Exception as e:
                if any(keyword in str(e).lower() for keyword in ["date", "invalid", "type"]):
                    error_cases_handled += 1
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            success = error_cases_handled == total_error_cases
            
            self.logger.log_test_result(
                "initialization_error_handling",
                success,
                execution_time,
                details={
                    "error_cases_handled": error_cases_handled,
                    "total_error_cases": total_error_cases,
                    "success_rate": error_cases_handled / total_error_cases if total_error_cases > 0 else 0
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "initialization_error_handling")
            return False
    
    def run_comprehensive_tests(self) -> Dict[str, bool]:
        """
        Run comprehensive simulation initialization tests.
        
        Returns:
            Dictionary of test results
        """
        results = {}
        
        self.logger.start_test_execution("Comprehensive Simulation Initialization Tests")
        
        try:
            # Create test parameter manifest
            test_manifest = ParameterManifest(
                metadata={
                    'analysis_date': datetime.now().isoformat(),
                    'data_period': ['2000-01-01', '2020-12-31'],
                    'wet_day_threshold': 0.1,
                    'data_completeness': 0.95,
                    'total_data_points': 7665
                },
                overall_parameters={
                    month: MonthlyParams(
                        p_ww=0.6 + 0.1 * np.sin(month * np.pi / 6),
                        p_wd=0.3 + 0.1 * np.cos(month * np.pi / 6),
                        alpha=1.0 + 0.5 * np.sin(month * np.pi / 6),
                        beta=5.0 + 2.0 * np.cos(month * np.pi / 6)
                    ) for month in range(1, 13)
                },
                trend_analysis=None,
                sliding_window_stats=None
            )
            
            # Test basic initialization
            results["basic_initialization"] = self.test_basic_initialization(test_manifest, 42)
            
            # Test trend mode initialization
            results["trend_mode_initialization"] = self.test_trend_mode_initialization(test_manifest, 42)
            
            # Test random seed consistency
            results["random_seed_consistency"] = self.test_random_seed_consistency(test_manifest, 12345)
            
            # Test state consistency
            results["state_consistency"] = self.test_state_consistency(test_manifest, 42)
            
            # Test parameter validation
            results["parameter_validation"] = self.test_parameter_validation(test_manifest)
            
            # Test error handling
            results["error_handling"] = self.test_initialization_error_handling()
            
            overall_success = all(results.values())
            
            self.logger.end_test_execution(overall_success, 
                                         f"Completed {len(results)} tests, {sum(results.values())} passed")
            
            return results
            
        except Exception as e:
            self.logger.log_error_with_context(e, "comprehensive_tests")
            self.logger.end_test_execution(False, f"Comprehensive tests failed: {e}")
            return results


class TestSimulationInitialization:
    """Test suite for simulation initialization workflow components."""
    
    def setup_method(self):
        """Set up test environment."""
        self.temp_dir = tempfile.mkdtemp(prefix="precipgen_simulation_init_test_")
        self.tester = SimulationInitializationTester(cache_dir=self.temp_dir)
        
    def teardown_method(self):
        """Clean up test environment."""
        if hasattr(self, 'temp_dir') and Path(self.temp_dir).exists():
            shutil.rmtree(self.temp_dir)
    
    def test_simulation_initialization_tester_setup(self):
        """Test that SimulationInitializationTester initializes correctly."""
        assert self.tester is not None
        assert self.tester.cache_dir == self.temp_dir
        assert self.tester.directory_manager is not None
        assert self.tester.logger is not None
    
    def test_basic_initialization_functionality(self):
        """Test basic simulation engine initialization functionality."""
        # Create test parameter manifest with all 12 months
        test_manifest = ParameterManifest(
            metadata={'test': True},
            overall_parameters={
                month: MonthlyParams(p_ww=0.6, p_wd=0.3, alpha=1.2, beta=4.5)
                for month in range(1, 13)
            },
            trend_analysis=None,
            sliding_window_stats=None
        )
        
        # Test basic initialization
        result = self.tester.test_basic_initialization(test_manifest, 42)
        assert result == True, "Basic initialization should succeed with valid parameters"
    
    def test_random_seed_consistency_functionality(self):
        """Test random seed consistency functionality."""
        # Create test parameter manifest
        test_manifest = ParameterManifest(
            metadata={'test': True},
            overall_parameters={
                month: MonthlyParams(p_ww=0.6, p_wd=0.3, alpha=1.0, beta=5.0)
                for month in range(1, 13)
            },
            trend_analysis=None,
            sliding_window_stats=None
        )
        
        # Test random seed consistency
        result = self.tester.test_random_seed_consistency(test_manifest, 12345, 3)
        assert result == True, "Random seed should produce consistent behavior"
    
    def test_parameter_validation_functionality(self):
        """Test parameter validation functionality."""
        # Create valid test parameter manifest
        test_manifest = ParameterManifest(
            metadata={'test': True},
            overall_parameters={
                month: MonthlyParams(p_ww=0.6, p_wd=0.3, alpha=1.0, beta=5.0)
                for month in range(1, 13)
            },
            trend_analysis=None,
            sliding_window_stats=None
        )
        
        # Test parameter validation
        result = self.tester.test_parameter_validation(test_manifest)
        assert result == True, "Parameter validation should work correctly"
    
    def test_comprehensive_workflow(self):
        """Test the complete simulation initialization workflow."""
        results = self.tester.run_comprehensive_tests()
        
        # Should have multiple test results
        assert len(results) > 0, "Should have test results"
        
        # Most tests should pass
        success_rate = sum(results.values()) / len(results)
        assert success_rate >= 0.8, f"Success rate too low: {success_rate:.2f}"
        
        # Specific critical tests should pass
        critical_tests = ["basic_initialization", "parameter_validation"]
        for test_name in critical_tests:
            if test_name in results:
                assert results[test_name] == True, f"Critical test {test_name} should pass"


class SyntheticGenerationTester:
    """
    Tester for synthetic precipitation generation functionality.
    
    Tests daily precipitation generation with step() and generate() methods,
    extended simulation runs for stability, and validates synthetic data
    statistical properties.
    """
    
    def __init__(self, cache_dir: Optional[str] = None):
        """
        Initialize synthetic generation tester.
        
        Args:
            cache_dir: Directory for caching test data
        """
        self.logger = WorkflowTestLogger("synthetic_generation_tester")
        self.cache_dir = cache_dir or tempfile.mkdtemp(prefix="precipgen_synth_test_")
        self.directory_manager = DirectoryManager(base_dir=self.cache_dir)
        
    def test_step_method_generation(self, parameter_manifest: ParameterManifest,
                                  num_steps: int = 100, random_seed: int = 42) -> bool:
        """
        Test daily precipitation generation using step() method.
        
        Args:
            parameter_manifest: Parameter manifest for simulation
            num_steps: Number of simulation steps to test
            random_seed: Random seed for reproducibility
            
        Returns:
            True if step method works correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize simulation engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            # Initialize simulation
            start_date = datetime(2025, 1, 1)
            engine.initialize(start_date, initial_wet_state=False)
            
            # Generate precipitation using step method
            generated_values = []
            dates = []
            
            for i in range(num_steps):
                precip_value = engine.step()
                generated_values.append(precip_value)
                
                # Get current state to track date
                state = engine.get_state()
                dates.append(state['current_date'])
                
                # Validate precipitation value
                if precip_value < 0:
                    self.logger.log_error_with_context(
                        ValueError(f"Negative precipitation at step {i}: {precip_value}"),
                        "step_method_generation"
                    )
                    return False
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate results
            success = (
                len(generated_values) == num_steps and
                all(isinstance(val, (int, float)) for val in generated_values) and
                all(val >= 0 for val in generated_values) and
                len(dates) == num_steps
            )
            
            # Calculate basic statistics
            wet_days = sum(1 for val in generated_values if val > 0.1)
            wet_day_frequency = wet_days / num_steps
            mean_precip = np.mean([val for val in generated_values if val > 0.1]) if wet_days > 0 else 0
            
            self.logger.log_test_result(
                f"step_method_generation_{num_steps}_steps",
                success,
                execution_time,
                details={
                    "num_steps": num_steps,
                    "random_seed": random_seed,
                    "wet_days": wet_days,
                    "wet_day_frequency": wet_day_frequency,
                    "mean_precip": mean_precip,
                    "total_precip": sum(generated_values),
                    "max_precip": max(generated_values),
                    "min_precip": min(generated_values)
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "step_method_generation")
            return False
    
    def test_generate_method_bulk(self, parameter_manifest: ParameterManifest,
                                 num_days: int = 365, random_seed: int = 42) -> bool:
        """
        Test bulk precipitation generation using generate() method.
        
        Args:
            parameter_manifest: Parameter manifest for simulation
            num_days: Number of days to generate
            random_seed: Random seed for reproducibility
            
        Returns:
            True if generate method works correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize simulation engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            # Initialize simulation
            start_date = datetime(2025, 1, 1)
            engine.initialize(start_date, initial_wet_state=False)
            
            # Generate precipitation using generate method
            precipitation_series = engine.generate(num_days)
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate results
            success = (
                isinstance(precipitation_series, pd.Series) and
                len(precipitation_series) == num_days and
                all(val >= 0 for val in precipitation_series) and
                precipitation_series.index.dtype.kind == 'M'  # DateTime index
            )
            
            # Calculate statistics
            wet_days = sum(1 for val in precipitation_series if val > 0.1)
            wet_day_frequency = wet_days / num_days
            mean_precip = precipitation_series[precipitation_series > 0.1].mean() if wet_days > 0 else 0
            
            self.logger.log_test_result(
                f"generate_method_bulk_{num_days}_days",
                success,
                execution_time,
                details={
                    "num_days": num_days,
                    "random_seed": random_seed,
                    "wet_days": wet_days,
                    "wet_day_frequency": wet_day_frequency,
                    "mean_precip": mean_precip,
                    "total_precip": precipitation_series.sum(),
                    "max_precip": precipitation_series.max(),
                    "min_precip": precipitation_series.min(),
                    "series_type": type(precipitation_series).__name__
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "generate_method_bulk")
            return False
    
    def test_extended_simulation_stability(self, parameter_manifest: ParameterManifest,
                                         num_days: int = 10000, random_seed: int = 42) -> bool:
        """
        Test extended simulation runs for stability (>10,000 days).
        
        Args:
            parameter_manifest: Parameter manifest for simulation
            num_days: Number of days for extended simulation
            random_seed: Random seed for reproducibility
            
        Returns:
            True if extended simulation is stable, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize simulation engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            # Initialize simulation
            start_date = datetime(2025, 1, 1)
            engine.initialize(start_date, initial_wet_state=False)
            
            # Generate extended precipitation series
            precipitation_series = engine.generate(num_days)
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate basic properties
            basic_success = (
                isinstance(precipitation_series, pd.Series) and
                len(precipitation_series) == num_days and
                all(val >= 0 for val in precipitation_series)
            )
            
            if not basic_success:
                return False
            
            # Test statistical stability by comparing different segments
            segment_size = num_days // 4
            segments = [
                precipitation_series[i*segment_size:(i+1)*segment_size] 
                for i in range(4)
            ]
            
            # Calculate statistics for each segment
            segment_stats = []
            for i, segment in enumerate(segments):
                wet_days = sum(1 for val in segment if val > 0.1)
                wet_freq = wet_days / len(segment)
                mean_precip = segment[segment > 0.1].mean() if wet_days > 0 else 0
                
                segment_stats.append({
                    'wet_frequency': wet_freq,
                    'mean_precip': mean_precip,
                    'total_precip': segment.sum()
                })
            
            # Check stability (coefficients of variation should be reasonable)
            wet_freqs = [s['wet_frequency'] for s in segment_stats]
            mean_precips = [s['mean_precip'] for s in segment_stats if s['mean_precip'] > 0]
            
            wet_freq_cv = np.std(wet_freqs) / np.mean(wet_freqs) if np.mean(wet_freqs) > 0 else 0
            mean_precip_cv = np.std(mean_precips) / np.mean(mean_precips) if len(mean_precips) > 0 and np.mean(mean_precips) > 0 else 0
            
            # Stability criteria (CV should be < 0.5 for reasonable stability)
            stability_success = wet_freq_cv < 0.5 and mean_precip_cv < 0.5
            
            success = basic_success and stability_success
            
            self.logger.log_test_result(
                f"extended_simulation_stability_{num_days}_days",
                success,
                execution_time,
                details={
                    "num_days": num_days,
                    "random_seed": random_seed,
                    "execution_time_seconds": execution_time,
                    "wet_freq_cv": wet_freq_cv,
                    "mean_precip_cv": mean_precip_cv,
                    "stability_success": stability_success,
                    "segment_stats": segment_stats,
                    "total_precip": precipitation_series.sum(),
                    "overall_wet_frequency": sum(1 for val in precipitation_series if val > 0.1) / num_days
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "extended_simulation_stability")
            return False
    
    def test_synthetic_data_statistical_properties(self, parameter_manifest: ParameterManifest,
                                                 num_days: int = 3650, random_seed: int = 42) -> bool:
        """
        Test that synthetic data maintains expected statistical properties.
        
        Args:
            parameter_manifest: Parameter manifest for simulation
            num_days: Number of days to generate for statistical testing
            random_seed: Random seed for reproducibility
            
        Returns:
            True if statistical properties are reasonable, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Initialize simulation engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            # Initialize simulation
            start_date = datetime(2025, 1, 1)
            engine.initialize(start_date, initial_wet_state=False)
            
            # Generate precipitation series
            precipitation_series = engine.generate(num_days)
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Calculate monthly statistics
            monthly_stats = {}
            for month in range(1, 13):
                # Get data for this month across all years
                month_mask = precipitation_series.index.month == month
                month_data = precipitation_series[month_mask]
                
                if len(month_data) > 0:
                    wet_days = sum(1 for val in month_data if val > 0.1)
                    wet_frequency = wet_days / len(month_data)
                    wet_data = month_data[month_data > 0.1]
                    mean_wet_precip = wet_data.mean() if len(wet_data) > 0 else 0
                    
                    monthly_stats[month] = {
                        'wet_frequency': wet_frequency,
                        'mean_wet_precip': mean_wet_precip,
                        'total_days': len(month_data),
                        'wet_days': wet_days
                    }
            
            # Validate statistical properties
            statistical_checks = []
            
            # Check 1: Wet day frequencies should be reasonable (0.1 to 0.9)
            wet_freqs = [stats['wet_frequency'] for stats in monthly_stats.values()]
            wet_freq_reasonable = all(0.05 <= freq <= 0.95 for freq in wet_freqs)
            statistical_checks.append(wet_freq_reasonable)
            
            # Check 2: Mean precipitation on wet days should be positive and reasonable
            mean_precips = [stats['mean_wet_precip'] for stats in monthly_stats.values() if stats['mean_wet_precip'] > 0]
            mean_precip_reasonable = all(0.1 <= precip <= 100.0 for precip in mean_precips)
            statistical_checks.append(mean_precip_reasonable)
            
            # Check 3: Should have data for all 12 months
            all_months_present = len(monthly_stats) == 12
            statistical_checks.append(all_months_present)
            
            # Check 4: Transition probabilities should be consistent with parameters
            # Calculate observed transition probabilities
            wet_to_wet_transitions = 0
            wet_to_dry_transitions = 0
            dry_to_wet_transitions = 0
            dry_to_dry_transitions = 0
            
            for i in range(len(precipitation_series) - 1):
                current_wet = precipitation_series.iloc[i] > 0.1
                next_wet = precipitation_series.iloc[i + 1] > 0.1
                
                if current_wet and next_wet:
                    wet_to_wet_transitions += 1
                elif current_wet and not next_wet:
                    wet_to_dry_transitions += 1
                elif not current_wet and next_wet:
                    dry_to_wet_transitions += 1
                else:
                    dry_to_dry_transitions += 1
            
            # Calculate observed probabilities
            total_wet_days = wet_to_wet_transitions + wet_to_dry_transitions
            total_dry_days = dry_to_wet_transitions + dry_to_dry_transitions
            
            observed_p_ww = wet_to_wet_transitions / total_wet_days if total_wet_days > 0 else 0
            observed_p_wd = dry_to_wet_transitions / total_dry_days if total_dry_days > 0 else 0
            
            # Transition probabilities should be reasonable
            transition_reasonable = 0.0 <= observed_p_ww <= 1.0 and 0.0 <= observed_p_wd <= 1.0
            statistical_checks.append(transition_reasonable)
            
            success = all(statistical_checks)
            
            self.logger.log_test_result(
                f"synthetic_statistical_properties_{num_days}_days",
                success,
                execution_time,
                details={
                    "num_days": num_days,
                    "random_seed": random_seed,
                    "monthly_stats": monthly_stats,
                    "wet_freq_reasonable": wet_freq_reasonable,
                    "mean_precip_reasonable": mean_precip_reasonable,
                    "all_months_present": all_months_present,
                    "transition_reasonable": transition_reasonable,
                    "observed_p_ww": observed_p_ww,
                    "observed_p_wd": observed_p_wd,
                    "total_wet_days": total_wet_days,
                    "total_dry_days": total_dry_days,
                    "statistical_checks_passed": sum(statistical_checks),
                    "total_statistical_checks": len(statistical_checks)
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "synthetic_statistical_properties")
            return False
    
    def test_step_vs_generate_consistency(self, parameter_manifest: ParameterManifest,
                                        num_days: int = 100, random_seed: int = 42) -> bool:
        """
        Test that step() and generate() methods produce consistent results.
        
        Args:
            parameter_manifest: Parameter manifest for simulation
            num_days: Number of days to test consistency
            random_seed: Random seed for reproducibility
            
        Returns:
            True if methods are consistent, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Test with step() method
            engine1 = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            start_date = datetime(2025, 1, 1)
            engine1.initialize(start_date, initial_wet_state=False)
            
            step_values = []
            for _ in range(num_days):
                step_values.append(engine1.step())
            
            # Test with generate() method
            engine2 = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=random_seed
            )
            
            engine2.initialize(start_date, initial_wet_state=False)
            generate_series = engine2.generate(num_days)
            generate_values = generate_series.values.tolist()
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Compare results
            values_match = step_values == generate_values
            
            # Calculate statistics for both methods
            step_wet_days = sum(1 for val in step_values if val > 0.1)
            generate_wet_days = sum(1 for val in generate_values if val > 0.1)
            
            step_total = sum(step_values)
            generate_total = sum(generate_values)
            
            statistics_match = (
                step_wet_days == generate_wet_days and
                abs(step_total - generate_total) < 1e-10
            )
            
            success = values_match and statistics_match
            
            self.logger.log_test_result(
                f"step_vs_generate_consistency_{num_days}_days",
                success,
                execution_time,
                details={
                    "num_days": num_days,
                    "random_seed": random_seed,
                    "values_match": values_match,
                    "statistics_match": statistics_match,
                    "step_wet_days": step_wet_days,
                    "generate_wet_days": generate_wet_days,
                    "step_total": step_total,
                    "generate_total": generate_total,
                    "first_10_step": step_values[:10],
                    "first_10_generate": generate_values[:10]
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "step_vs_generate_consistency")
            return False
    
    def run_comprehensive_tests(self) -> Dict[str, bool]:
        """
        Run comprehensive synthetic generation tests.
        
        Returns:
            Dictionary of test results
        """
        results = {}
        
        self.logger.start_test_execution("Comprehensive Synthetic Generation Tests")
        
        try:
            # Create test parameter manifest
            test_manifest = ParameterManifest(
                metadata={
                    'analysis_date': datetime.now().isoformat(),
                    'data_period': ['2000-01-01', '2020-12-31'],
                    'wet_day_threshold': 0.1,
                    'data_completeness': 0.95,
                    'total_data_points': 7665
                },
                overall_parameters={
                    month: MonthlyParams(
                        p_ww=0.6 + 0.1 * np.sin(month * np.pi / 6),
                        p_wd=0.3 + 0.1 * np.cos(month * np.pi / 6),
                        alpha=1.0 + 0.5 * np.sin(month * np.pi / 6),
                        beta=5.0 + 2.0 * np.cos(month * np.pi / 6)
                    ) for month in range(1, 13)
                },
                trend_analysis=None,
                sliding_window_stats=None
            )
            
            # Test step method generation
            results["step_method_generation"] = self.test_step_method_generation(test_manifest, 100, 42)
            
            # Test generate method bulk
            results["generate_method_bulk"] = self.test_generate_method_bulk(test_manifest, 365, 42)
            
            # Test extended simulation stability
            results["extended_simulation_stability"] = self.test_extended_simulation_stability(test_manifest, 10000, 42)
            
            # Test synthetic data statistical properties
            results["synthetic_statistical_properties"] = self.test_synthetic_data_statistical_properties(test_manifest, 3650, 42)
            
            # Test step vs generate consistency
            results["step_vs_generate_consistency"] = self.test_step_vs_generate_consistency(test_manifest, 100, 42)
            
            overall_success = all(results.values())
            
            self.logger.end_test_execution(overall_success, 
                                         f"Completed {len(results)} tests, {sum(results.values())} passed")
            
            return results
            
        except Exception as e:
            self.logger.log_error_with_context(e, "comprehensive_tests")
            self.logger.end_test_execution(False, f"Comprehensive tests failed: {e}")
            return results


class TestSyntheticGeneration:
    """Test suite for synthetic generation workflow components."""
    
    def setup_method(self):
        """Set up test environment."""
        self.temp_dir = tempfile.mkdtemp(prefix="precipgen_synthetic_gen_test_")
        self.tester = SyntheticGenerationTester(cache_dir=self.temp_dir)
        
    def teardown_method(self):
        """Clean up test environment."""
        if hasattr(self, 'temp_dir') and Path(self.temp_dir).exists():
            shutil.rmtree(self.temp_dir)
    
    def test_synthetic_generation_tester_setup(self):
        """Test that SyntheticGenerationTester initializes correctly."""
        assert self.tester is not None
        assert self.tester.cache_dir == self.temp_dir
        assert self.tester.directory_manager is not None
        assert self.tester.logger is not None
    
    def test_step_method_functionality(self):
        """Test step method generation functionality."""
        # Create test parameter manifest
        test_manifest = ParameterManifest(
            metadata={'test': True},
            overall_parameters={
                month: MonthlyParams(p_ww=0.6, p_wd=0.3, alpha=1.0, beta=5.0)
                for month in range(1, 13)
            },
            trend_analysis=None,
            sliding_window_stats=None
        )
        
        # Test step method generation
        result = self.tester.test_step_method_generation(test_manifest, 50, 42)
        assert result == True, "Step method generation should succeed"
    
    def test_generate_method_functionality(self):
        """Test generate method bulk functionality."""
        # Create test parameter manifest
        test_manifest = ParameterManifest(
            metadata={'test': True},
            overall_parameters={
                month: MonthlyParams(p_ww=0.6, p_wd=0.3, alpha=1.0, beta=5.0)
                for month in range(1, 13)
            },
            trend_analysis=None,
            sliding_window_stats=None
        )
        
        # Test generate method bulk
        result = self.tester.test_generate_method_bulk(test_manifest, 100, 42)
        assert result == True, "Generate method should succeed"
    
    def test_step_vs_generate_consistency_functionality(self):
        """Test step vs generate consistency functionality."""
        # Create test parameter manifest
        test_manifest = ParameterManifest(
            metadata={'test': True},
            overall_parameters={
                month: MonthlyParams(p_ww=0.6, p_wd=0.3, alpha=1.0, beta=5.0)
                for month in range(1, 13)
            },
            trend_analysis=None,
            sliding_window_stats=None
        )
        
        # Test consistency
        result = self.tester.test_step_vs_generate_consistency(test_manifest, 50, 42)
        assert result == True, "Step and generate methods should be consistent"
    
    def test_comprehensive_workflow(self):
        """Test the complete synthetic generation workflow."""
        results = self.tester.run_comprehensive_tests()
        
        # Should have multiple test results
        assert len(results) > 0, "Should have test results"
        
        # Most tests should pass
        success_rate = sum(results.values()) / len(results)
        assert success_rate >= 0.6, f"Success rate too low: {success_rate:.2f}"
        
        # Specific critical tests should pass
        critical_tests = ["step_method_generation", "generate_method_bulk"]
        for test_name in critical_tests:
            if test_name in results:
                assert results[test_name] == True, f"Critical test {test_name} should pass"


class StatisticsGenerationTester:
    """
    Tester for simulation output statistics generation.
    
    Tests monthly statistics calculation (mean, std, wet-day frequency),
    annual statistics calculation (totals, wet days, dry spells),
    seasonal statistics breakdown by season, and simulation metadata
    generation and storage.
    """
    
    def __init__(self, cache_dir: Optional[str] = None):
        """
        Initialize statistics generation tester.
        
        Args:
            cache_dir: Directory for caching test data
        """
        self.logger = WorkflowTestLogger("statistics_generation_tester")
        self.cache_dir = cache_dir or tempfile.mkdtemp(prefix="precipgen_stats_test_")
        self.directory_manager = DirectoryManager(base_dir=self.cache_dir)
        
    def test_monthly_statistics_calculation(self, precipitation_series: pd.Series) -> bool:
        """
        Test monthly statistics calculation (mean, std, wet-day frequency).
        
        Args:
            precipitation_series: Precipitation time series data
            
        Returns:
            True if monthly statistics are calculated correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Calculate monthly statistics
            monthly_stats = {}
            
            for month in range(1, 13):
                # Get data for this month across all years
                month_mask = precipitation_series.index.month == month
                month_data = precipitation_series[month_mask]
                
                if len(month_data) > 0:
                    # Calculate statistics
                    total_days = len(month_data)
                    wet_days = sum(1 for val in month_data if val > 0.1)
                    wet_frequency = wet_days / total_days
                    
                    # Mean and std for all days
                    mean_precip = month_data.mean()
                    std_precip = month_data.std()
                    
                    # Mean and std for wet days only
                    wet_data = month_data[month_data > 0.1]
                    mean_wet_precip = wet_data.mean() if len(wet_data) > 0 else 0
                    std_wet_precip = wet_data.std() if len(wet_data) > 0 else 0
                    
                    monthly_stats[month] = {
                        'total_days': total_days,
                        'wet_days': wet_days,
                        'wet_frequency': wet_frequency,
                        'mean_precip': mean_precip,
                        'std_precip': std_precip,
                        'mean_wet_precip': mean_wet_precip,
                        'std_wet_precip': std_wet_precip,
                        'total_precip': month_data.sum(),
                        'max_precip': month_data.max(),
                        'min_precip': month_data.min()
                    }
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate results
            success = (
                len(monthly_stats) == 12 and  # Should have all 12 months
                all(isinstance(stats, dict) for stats in monthly_stats.values()) and
                all('wet_frequency' in stats for stats in monthly_stats.values()) and
                all('mean_precip' in stats for stats in monthly_stats.values()) and
                all('std_precip' in stats for stats in monthly_stats.values()) and
                all(0 <= stats['wet_frequency'] <= 1 for stats in monthly_stats.values()) and
                all(stats['mean_precip'] >= 0 for stats in monthly_stats.values()) and
                all(stats['std_precip'] >= 0 for stats in monthly_stats.values())
            )
            
            self.logger.log_test_result(
                f"monthly_statistics_calculation_{len(precipitation_series)}_days",
                success,
                execution_time,
                details={
                    "total_days": len(precipitation_series),
                    "months_calculated": len(monthly_stats),
                    "avg_wet_frequency": np.mean([stats['wet_frequency'] for stats in monthly_stats.values()]),
                    "avg_monthly_precip": np.mean([stats['mean_precip'] for stats in monthly_stats.values()]),
                    "monthly_stats_sample": {k: v for k, v in list(monthly_stats.items())[:3]}
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "monthly_statistics_calculation")
            return False
    
    def test_annual_statistics_calculation(self, precipitation_series: pd.Series) -> bool:
        """
        Test annual statistics calculation (totals, wet days, dry spells).
        
        Args:
            precipitation_series: Precipitation time series data
            
        Returns:
            True if annual statistics are calculated correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Calculate annual statistics
            annual_stats = {}
            
            # Group by year
            years = precipitation_series.index.year.unique()
            
            for year in years:
                year_mask = precipitation_series.index.year == year
                year_data = precipitation_series[year_mask]
                
                if len(year_data) > 0:
                    # Calculate basic statistics
                    total_precip = year_data.sum()
                    wet_days = sum(1 for val in year_data if val > 0.1)
                    dry_days = len(year_data) - wet_days
                    max_daily_precip = year_data.max()
                    
                    # Calculate dry spell statistics
                    dry_spells = []
                    current_dry_spell = 0
                    
                    for precip in year_data:
                        if precip <= 0.1:  # Dry day
                            current_dry_spell += 1
                        else:  # Wet day
                            if current_dry_spell > 0:
                                dry_spells.append(current_dry_spell)
                                current_dry_spell = 0
                    
                    # Add final dry spell if year ends with dry days
                    if current_dry_spell > 0:
                        dry_spells.append(current_dry_spell)
                    
                    # Calculate wet spell statistics
                    wet_spells = []
                    current_wet_spell = 0
                    
                    for precip in year_data:
                        if precip > 0.1:  # Wet day
                            current_wet_spell += 1
                        else:  # Dry day
                            if current_wet_spell > 0:
                                wet_spells.append(current_wet_spell)
                                current_wet_spell = 0
                    
                    # Add final wet spell if year ends with wet days
                    if current_wet_spell > 0:
                        wet_spells.append(current_wet_spell)
                    
                    annual_stats[year] = {
                        'total_days': len(year_data),
                        'total_precip': total_precip,
                        'wet_days': wet_days,
                        'dry_days': dry_days,
                        'wet_frequency': wet_days / len(year_data),
                        'max_daily_precip': max_daily_precip,
                        'mean_daily_precip': year_data.mean(),
                        'std_daily_precip': year_data.std(),
                        'dry_spells': dry_spells,
                        'wet_spells': wet_spells,
                        'max_dry_spell': max(dry_spells) if dry_spells else 0,
                        'max_wet_spell': max(wet_spells) if wet_spells else 0,
                        'avg_dry_spell': np.mean(dry_spells) if dry_spells else 0,
                        'avg_wet_spell': np.mean(wet_spells) if wet_spells else 0
                    }
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate results
            success = (
                len(annual_stats) > 0 and  # Should have at least one year
                all(isinstance(stats, dict) for stats in annual_stats.values()) and
                all('total_precip' in stats for stats in annual_stats.values()) and
                all('wet_days' in stats for stats in annual_stats.values()) and
                all('dry_days' in stats for stats in annual_stats.values()) and
                all(stats['total_precip'] >= 0 for stats in annual_stats.values()) and
                all(stats['wet_days'] >= 0 for stats in annual_stats.values()) and
                all(stats['dry_days'] >= 0 for stats in annual_stats.values()) and
                all(0 <= stats['wet_frequency'] <= 1 for stats in annual_stats.values())
            )
            
            self.logger.log_test_result(
                f"annual_statistics_calculation_{len(precipitation_series)}_days",
                success,
                execution_time,
                details={
                    "total_days": len(precipitation_series),
                    "years_calculated": len(annual_stats),
                    "avg_annual_precip": np.mean([stats['total_precip'] for stats in annual_stats.values()]),
                    "avg_wet_days_per_year": np.mean([stats['wet_days'] for stats in annual_stats.values()]),
                    "avg_max_dry_spell": np.mean([stats['max_dry_spell'] for stats in annual_stats.values()]),
                    "annual_stats_sample": {k: v for k, v in list(annual_stats.items())[:2]}
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "annual_statistics_calculation")
            return False
    
    def test_seasonal_statistics_breakdown(self, precipitation_series: pd.Series) -> bool:
        """
        Test seasonal statistics breakdown by season.
        
        Args:
            precipitation_series: Precipitation time series data
            
        Returns:
            True if seasonal statistics are calculated correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Define seasons (Northern Hemisphere)
            season_months = {
                'winter': [12, 1, 2],
                'spring': [3, 4, 5],
                'summer': [6, 7, 8],
                'fall': [9, 10, 11]
            }
            
            # Calculate seasonal statistics
            seasonal_stats = {}
            
            for season, months in season_months.items():
                # Get data for this season across all years
                season_mask = precipitation_series.index.month.isin(months)
                season_data = precipitation_series[season_mask]
                
                if len(season_data) > 0:
                    # Calculate statistics
                    total_days = len(season_data)
                    wet_days = sum(1 for val in season_data if val > 0.1)
                    wet_frequency = wet_days / total_days
                    
                    # Mean and std for all days
                    mean_precip = season_data.mean()
                    std_precip = season_data.std()
                    
                    # Mean and std for wet days only
                    wet_data = season_data[season_data > 0.1]
                    mean_wet_precip = wet_data.mean() if len(wet_data) > 0 else 0
                    std_wet_precip = wet_data.std() if len(wet_data) > 0 else 0
                    
                    seasonal_stats[season] = {
                        'total_days': total_days,
                        'wet_days': wet_days,
                        'wet_frequency': wet_frequency,
                        'mean_precip': mean_precip,
                        'std_precip': std_precip,
                        'mean_wet_precip': mean_wet_precip,
                        'std_wet_precip': std_wet_precip,
                        'total_precip': season_data.sum(),
                        'max_precip': season_data.max(),
                        'min_precip': season_data.min(),
                        'months': months
                    }
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate results
            success = (
                len(seasonal_stats) == 4 and  # Should have all 4 seasons
                all(season in seasonal_stats for season in ['winter', 'spring', 'summer', 'fall']) and
                all(isinstance(stats, dict) for stats in seasonal_stats.values()) and
                all('wet_frequency' in stats for stats in seasonal_stats.values()) and
                all('mean_precip' in stats for stats in seasonal_stats.values()) and
                all(0 <= stats['wet_frequency'] <= 1 for stats in seasonal_stats.values()) and
                all(stats['mean_precip'] >= 0 for stats in seasonal_stats.values())
            )
            
            self.logger.log_test_result(
                f"seasonal_statistics_breakdown_{len(precipitation_series)}_days",
                success,
                execution_time,
                details={
                    "total_days": len(precipitation_series),
                    "seasons_calculated": len(seasonal_stats),
                    "seasonal_wet_frequencies": {season: stats['wet_frequency'] for season, stats in seasonal_stats.items()},
                    "seasonal_mean_precip": {season: stats['mean_precip'] for season, stats in seasonal_stats.items()},
                    "seasonal_total_precip": {season: stats['total_precip'] for season, stats in seasonal_stats.items()}
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "seasonal_statistics_breakdown")
            return False
    
    def test_simulation_metadata_generation(self, parameter_manifest: ParameterManifest,
                                          simulation_config: Dict[str, Any]) -> bool:
        """
        Test simulation metadata generation and storage.
        
        Args:
            parameter_manifest: Parameter manifest used for simulation
            simulation_config: Configuration used for simulation
            
        Returns:
            True if metadata is generated correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Generate simulation metadata
            metadata = {
                'simulation_id': f"sim_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
                'creation_date': datetime.now().isoformat(),
                'parameter_manifest': {
                    'metadata': parameter_manifest.metadata,
                    'parameter_count': len(parameter_manifest.overall_parameters),
                    'trend_analysis_available': parameter_manifest.trend_analysis is not None,
                    'sliding_window_stats_available': parameter_manifest.sliding_window_stats is not None
                },
                'simulation_config': simulation_config,
                'engine_info': {
                    'algorithm': 'WGEN (Richardson & Wright, 1984)',
                    'version': 'v0.1.3',
                    'trend_mode': simulation_config.get('trend_mode', False),
                    'random_seed': simulation_config.get('random_seed', None)
                },
                'data_period': {
                    'start_date': simulation_config.get('start_date', datetime(2025, 1, 1)).isoformat(),
                    'num_days': simulation_config.get('num_days', 365),
                    'end_date': (simulation_config.get('start_date', datetime(2025, 1, 1)) + 
                               timedelta(days=simulation_config.get('num_days', 365) - 1)).isoformat()
                },
                'quality_metrics': {
                    'parameter_completeness': len(parameter_manifest.overall_parameters) / 12,
                    'data_completeness': parameter_manifest.metadata.get('data_completeness', 1.0),
                    'wet_day_threshold': parameter_manifest.metadata.get('wet_day_threshold', 0.1)
                }
            }
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate metadata structure
            success = (
                isinstance(metadata, dict) and
                'simulation_id' in metadata and
                'creation_date' in metadata and
                'parameter_manifest' in metadata and
                'simulation_config' in metadata and
                'engine_info' in metadata and
                'data_period' in metadata and
                'quality_metrics' in metadata and
                isinstance(metadata['parameter_manifest'], dict) and
                isinstance(metadata['simulation_config'], dict) and
                isinstance(metadata['engine_info'], dict) and
                isinstance(metadata['data_period'], dict) and
                isinstance(metadata['quality_metrics'], dict)
            )
            
            # Test JSON serialization
            try:
                import json
                json_str = json.dumps(metadata, indent=2)
                json_success = len(json_str) > 0
            except Exception:
                json_success = False
            
            success = success and json_success
            
            self.logger.log_test_result(
                "simulation_metadata_generation",
                success,
                execution_time,
                details={
                    "metadata_keys": list(metadata.keys()),
                    "parameter_count": metadata['parameter_manifest']['parameter_count'],
                    "trend_mode": metadata['engine_info']['trend_mode'],
                    "num_days": metadata['data_period']['num_days'],
                    "json_serializable": json_success,
                    "metadata_size_bytes": len(json_str) if json_success else 0
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "simulation_metadata_generation")
            return False
    
    def test_statistics_file_storage(self, statistics_data: Dict[str, Any],
                                   station_id: str = "TEST_STATION") -> bool:
        """
        Test statistics file storage in organized directory structure.
        
        Args:
            statistics_data: Statistics data to store
            station_id: Station ID for directory organization
            
        Returns:
            True if statistics are stored correctly, False otherwise
        """
        try:
            start_time = pd.Timestamp.now()
            
            # Create station directory
            station_dir = self.directory_manager.create_station_directory(station_id)
            simulation_dir = station_dir / "simulation" / datetime.now().strftime("%Y%m%d_%H%M%S")
            simulation_dir.mkdir(parents=True, exist_ok=True)
            
            # Store different types of statistics
            files_created = []
            
            # Monthly statistics
            if 'monthly_stats' in statistics_data:
                monthly_file = simulation_dir / "monthly_stats.json"
                with open(monthly_file, 'w') as f:
                    import json
                    json.dump(statistics_data['monthly_stats'], f, indent=2)
                files_created.append(monthly_file)
            
            # Annual statistics
            if 'annual_stats' in statistics_data:
                annual_file = simulation_dir / "annual_stats.json"
                with open(annual_file, 'w') as f:
                    import json
                    json.dump(statistics_data['annual_stats'], f, indent=2)
                files_created.append(annual_file)
            
            # Seasonal statistics
            if 'seasonal_stats' in statistics_data:
                seasonal_file = simulation_dir / "seasonal_stats.json"
                with open(seasonal_file, 'w') as f:
                    import json
                    json.dump(statistics_data['seasonal_stats'], f, indent=2)
                files_created.append(seasonal_file)
            
            # Simulation metadata
            if 'metadata' in statistics_data:
                metadata_file = simulation_dir / "simulation_metadata.json"
                with open(metadata_file, 'w') as f:
                    import json
                    json.dump(statistics_data['metadata'], f, indent=2)
                files_created.append(metadata_file)
            
            execution_time = (pd.Timestamp.now() - start_time).total_seconds()
            
            # Validate file creation
            success = (
                len(files_created) > 0 and
                all(file_path.exists() for file_path in files_created) and
                all(file_path.stat().st_size > 0 for file_path in files_created)
            )
            
            # Test file reading
            read_success = True
            for file_path in files_created:
                try:
                    with open(file_path, 'r') as f:
                        import json
                        data = json.load(f)
                        if not isinstance(data, dict):
                            read_success = False
                except Exception:
                    read_success = False
            
            success = success and read_success
            
            self.logger.log_test_result(
                f"statistics_file_storage_{station_id}",
                success,
                execution_time,
                details={
                    "station_id": station_id,
                    "files_created": len(files_created),
                    "file_paths": [str(f) for f in files_created],
                    "total_size_bytes": sum(f.stat().st_size for f in files_created),
                    "read_success": read_success,
                    "simulation_dir": str(simulation_dir)
                }
            )
            
            return success
            
        except Exception as e:
            self.logger.log_error_with_context(e, "statistics_file_storage")
            return False
    
    def run_comprehensive_tests(self) -> Dict[str, bool]:
        """
        Run comprehensive statistics generation tests.
        
        Returns:
            Dictionary of test results
        """
        results = {}
        
        self.logger.start_test_execution("Comprehensive Statistics Generation Tests")
        
        try:
            # Create test parameter manifest
            test_manifest = ParameterManifest(
                metadata={
                    'analysis_date': datetime.now().isoformat(),
                    'data_period': ['2000-01-01', '2020-12-31'],
                    'wet_day_threshold': 0.1,
                    'data_completeness': 0.95,
                    'total_data_points': 7665
                },
                overall_parameters={
                    month: MonthlyParams(
                        p_ww=0.6 + 0.1 * np.sin(month * np.pi / 6),
                        p_wd=0.3 + 0.1 * np.cos(month * np.pi / 6),
                        alpha=1.0 + 0.5 * np.sin(month * np.pi / 6),
                        beta=5.0 + 2.0 * np.cos(month * np.pi / 6)
                    ) for month in range(1, 13)
                },
                trend_analysis=None,
                sliding_window_stats=None
            )
            
            # Generate test precipitation data
            np.random.seed(42)
            dates = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D')
            precip_values = np.random.exponential(scale=2.0, size=len(dates))
            # Make some days dry
            dry_mask = np.random.random(len(dates)) < 0.7
            precip_values[dry_mask] = 0.0
            
            test_precipitation = pd.Series(precip_values, index=dates)
            
            # Test monthly statistics calculation
            results["monthly_statistics"] = self.test_monthly_statistics_calculation(test_precipitation)
            
            # Test annual statistics calculation
            results["annual_statistics"] = self.test_annual_statistics_calculation(test_precipitation)
            
            # Test seasonal statistics breakdown
            results["seasonal_statistics"] = self.test_seasonal_statistics_breakdown(test_precipitation)
            
            # Test simulation metadata generation
            simulation_config = {
                'trend_mode': False,
                'random_seed': 42,
                'start_date': datetime(2025, 1, 1),
                'num_days': 1095
            }
            results["metadata_generation"] = self.test_simulation_metadata_generation(test_manifest, simulation_config)
            
            # Test statistics file storage
            test_stats_data = {
                'monthly_stats': {'1': {'wet_frequency': 0.3, 'mean_precip': 1.5}},
                'annual_stats': {'2020': {'total_precip': 500, 'wet_days': 120}},
                'seasonal_stats': {'winter': {'wet_frequency': 0.4, 'mean_precip': 2.0}},
                'metadata': {'simulation_id': 'test_sim', 'creation_date': datetime.now().isoformat()}
            }
            results["file_storage"] = self.test_statistics_file_storage(test_stats_data, "TEST_STATION")
            
            overall_success = all(results.values())
            
            self.logger.end_test_execution(overall_success, 
                                         f"Completed {len(results)} tests, {sum(results.values())} passed")
            
            return results
            
        except Exception as e:
            self.logger.log_error_with_context(e, "comprehensive_tests")
            self.logger.end_test_execution(False, f"Comprehensive tests failed: {e}")
            return results


class TestStatisticsGeneration:
    """Test suite for statistics generation workflow components."""
    
    def setup_method(self):
        """Set up test environment."""
        self.temp_dir = tempfile.mkdtemp(prefix="precipgen_stats_gen_test_")
        self.tester = StatisticsGenerationTester(cache_dir=self.temp_dir)
        
    def teardown_method(self):
        """Clean up test environment."""
        if hasattr(self, 'temp_dir') and Path(self.temp_dir).exists():
            shutil.rmtree(self.temp_dir)
    
    def test_statistics_generation_tester_setup(self):
        """Test that StatisticsGenerationTester initializes correctly."""
        assert self.tester is not None
        assert self.tester.cache_dir == self.temp_dir
        assert self.tester.directory_manager is not None
        assert self.tester.logger is not None
    
    def test_monthly_statistics_functionality(self):
        """Test monthly statistics calculation functionality."""
        # Create test precipitation data
        dates = pd.date_range(start='2020-01-01', end='2020-12-31', freq='D')
        np.random.seed(42)
        precip_values = np.random.exponential(scale=2.0, size=len(dates))
        # Make some days dry
        dry_mask = np.random.random(len(dates)) < 0.7
        precip_values[dry_mask] = 0.0
        
        test_precipitation = pd.Series(precip_values, index=dates)
        
        # Test monthly statistics calculation
        result = self.tester.test_monthly_statistics_calculation(test_precipitation)
        assert result == True, "Monthly statistics calculation should succeed"
    
    def test_annual_statistics_functionality(self):
        """Test annual statistics calculation functionality."""
        # Create test precipitation data
        dates = pd.date_range(start='2020-01-01', end='2021-12-31', freq='D')
        np.random.seed(42)
        precip_values = np.random.exponential(scale=2.0, size=len(dates))
        # Make some days dry
        dry_mask = np.random.random(len(dates)) < 0.7
        precip_values[dry_mask] = 0.0
        
        test_precipitation = pd.Series(precip_values, index=dates)
        
        # Test annual statistics calculation
        result = self.tester.test_annual_statistics_calculation(test_precipitation)
        assert result == True, "Annual statistics calculation should succeed"
    
    def test_seasonal_statistics_functionality(self):
        """Test seasonal statistics breakdown functionality."""
        # Create test precipitation data
        dates = pd.date_range(start='2020-01-01', end='2020-12-31', freq='D')
        np.random.seed(42)
        precip_values = np.random.exponential(scale=2.0, size=len(dates))
        # Make some days dry
        dry_mask = np.random.random(len(dates)) < 0.7
        precip_values[dry_mask] = 0.0
        
        test_precipitation = pd.Series(precip_values, index=dates)
        
        # Test seasonal statistics breakdown
        result = self.tester.test_seasonal_statistics_breakdown(test_precipitation)
        assert result == True, "Seasonal statistics breakdown should succeed"
    
    def test_comprehensive_workflow(self):
        """Test the complete statistics generation workflow."""
        results = self.tester.run_comprehensive_tests()
        
        # Should have multiple test results
        assert len(results) > 0, "Should have test results"
        
        # Most tests should pass
        success_rate = sum(results.values()) / len(results)
        assert success_rate >= 0.8, f"Success rate too low: {success_rate:.2f}"
        
        # Specific critical tests should pass
        critical_tests = ["monthly_statistics", "annual_statistics", "seasonal_statistics"]
        for test_name in critical_tests:
            if test_name in results:
                assert results[test_name] == True, f"Critical test {test_name} should pass"


# Property-based tests for simulation workflow
class TestSimulationWorkflowProperties:
    """Property-based tests for simulation workflow components."""
    
    def setup_method(self):
        """Set up test environment."""
        self.temp_dir = tempfile.mkdtemp(prefix="precipgen_simulation_props_test_")
        
    def teardown_method(self):
        """Clean up test environment."""
        if hasattr(self, 'temp_dir') and Path(self.temp_dir).exists():
            shutil.rmtree(self.temp_dir)
    
    @given(valid_parameter_manifest(), random_seeds())
    @settings(max_examples=10, deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_simulation_engine_initialization_consistency(self, parameter_manifest, random_seed):
        """
        Property 8: Simulation Engine Initialization Consistency
        
        For any valid ParameterManifest object, the SimulationEngine should 
        initialize successfully with WGEN algorithm parameters and maintain 
        consistent state across multiple initializations with the same parameters.
        
        **Validates: Requirements 4.1**
        """
        # Test multiple initializations with same parameters
        engines = []
        initial_states = []
        
        try:
            for _ in range(3):
                engine = SimulationEngine(
                    parameters=parameter_manifest,
                    trend_mode=False,
                    random_seed=random_seed
                )
                engines.append(engine)
                initial_states.append(engine.get_state())
            
            # All engines should initialize successfully
            assert len(engines) == 3, "All engines should initialize"
            assert len(initial_states) == 3, "All states should be captured"
            
            # All engines should have the same parameters
            for engine in engines:
                assert engine.parameters == parameter_manifest, "Parameters should match manifest"
                assert engine.trend_mode == False, "Trend mode should be False"
                assert engine.random_state is not None, "Random state should be initialized"
            
            # Random states should be identical for same seed
            first_random_state = initial_states[0]['random_state']
            for state in initial_states:
                # Handle different types of random state properly
                current_random_state = state['random_state']
                if isinstance(first_random_state, tuple) and isinstance(current_random_state, tuple):
                    # Compare tuples element by element
                    assert len(first_random_state) == len(current_random_state), "Random state tuples should have same length"
                    for i, (first_elem, current_elem) in enumerate(zip(first_random_state, current_random_state)):
                        if hasattr(first_elem, 'shape') and hasattr(current_elem, 'shape'):
                            # Compare numpy arrays element-wise
                            assert np.array_equal(first_elem, current_elem), f"Random state element {i} should be identical"
                        else:
                            # Compare regular values
                            assert current_elem == first_elem, f"Random state element {i} should be identical"
                elif hasattr(first_random_state, 'shape') and hasattr(current_random_state, 'shape'):
                    # Compare numpy arrays element-wise
                    assert np.array_equal(first_random_state, current_random_state), "Random states should be identical"
                else:
                    # Compare regular values
                    assert current_random_state == first_random_state, "Random states should be identical"
            
            # Test that engines produce identical sequences
            start_date = datetime(2025, 1, 1)
            sequences = []
            
            for engine in engines:
                engine.initialize(start_date, initial_wet_state=False)
                sequence = []
                for _ in range(10):
                    sequence.append(engine.step())
                sequences.append(sequence)
            
            # All sequences should be identical
            first_sequence = sequences[0]
            for sequence in sequences:
                assert sequence == first_sequence, "Sequences should be identical for same seed"
                
        except Exception as e:
            # If initialization fails, it should be due to invalid parameters
            assert "parameter" in str(e).lower() or "invalid" in str(e).lower(), f"Unexpected error: {e}"


    @given(valid_parameter_manifest(), simulation_days())
    @settings(max_examples=5, deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_simulation_output_completeness(self, parameter_manifest, num_days):
        """
        Property 9: Simulation Output Completeness
        
        For any simulation execution, the system should generate all required outputs: 
        daily time series, monthly statistics, annual statistics, seasonal statistics, 
        and simulation metadata in the organized directory structure.
        
        **Validates: Requirements 4.2**
        """
        try:
            # Initialize simulation engine
            engine = SimulationEngine(
                parameters=parameter_manifest,
                trend_mode=False,
                random_seed=42
            )
            
            # Initialize and generate precipitation using step() method
            start_date = datetime(2025, 1, 1)
            engine.initialize(start_date, initial_wet_state=False)
            
            # Generate precipitation data using step() method
            precipitation_values = []
            dates = []
            
            for i in range(min(num_days, 100)):  # Limit to 100 days for property test performance
                precip_value = engine.step()
                precipitation_values.append(precip_value)
                
                # Get current date from engine state
                state = engine.get_state()
                current_date = pd.to_datetime(state['current_date'])
                dates.append(current_date)
            
            # Create pandas series
            precipitation_series = pd.Series(precipitation_values, index=dates)
            actual_days = len(precipitation_series)
            
            # Test 1: Daily time series completeness
            assert isinstance(precipitation_series, pd.Series), "Should return pandas Series"
            assert len(precipitation_series) == actual_days, f"Should have {actual_days} days of data"
            assert precipitation_series.index.dtype.kind == 'M', "Should have datetime index"
            assert all(val >= 0 for val in precipitation_series), "All precipitation values should be non-negative"
            
            # Test 2: Monthly statistics can be calculated
            monthly_stats = {}
            for month in range(1, 13):
                month_mask = precipitation_series.index.month == month
                month_data = precipitation_series[month_mask]
                
                if len(month_data) > 0:
                    wet_days = sum(1 for val in month_data if val > 0.1)
                    monthly_stats[month] = {
                        'total_days': len(month_data),
                        'wet_days': wet_days,
                        'wet_frequency': wet_days / len(month_data),
                        'mean_precip': month_data.mean(),
                        'total_precip': month_data.sum()
                    }
            
            # Should have monthly stats for months with data
            months_with_data = precipitation_series.index.month.unique()
            assert len(monthly_stats) == len(months_with_data), "Should have stats for all months with data"
            
            # Test 3: Annual statistics can be calculated
            annual_stats = {}
            years = precipitation_series.index.year.unique()
            
            for year in years:
                year_mask = precipitation_series.index.year == year
                year_data = precipitation_series[year_mask]
                
                if len(year_data) > 0:
                    wet_days = sum(1 for val in year_data if val > 0.1)
                    annual_stats[year] = {
                        'total_days': len(year_data),
                        'wet_days': wet_days,
                        'total_precip': year_data.sum(),
                        'max_precip': year_data.max()
                    }
            
            # Should have annual stats for all years with data
            assert len(annual_stats) == len(years), "Should have stats for all years with data"
            
            # Test 4: Seasonal statistics can be calculated
            season_months = {
                'winter': [12, 1, 2],
                'spring': [3, 4, 5], 
                'summer': [6, 7, 8],
                'fall': [9, 10, 11]
            }
            
            seasonal_stats = {}
            for season, months in season_months.items():
                season_mask = precipitation_series.index.month.isin(months)
                season_data = precipitation_series[season_mask]
                
                if len(season_data) > 0:
                    wet_days = sum(1 for val in season_data if val > 0.1)
                    seasonal_stats[season] = {
                        'total_days': len(season_data),
                        'wet_days': wet_days,
                        'total_precip': season_data.sum()
                    }
            
            # Should have seasonal stats for seasons with data
            seasons_with_data = set()
            for month in precipitation_series.index.month.unique():
                for season, months in season_months.items():
                    if month in months:
                        seasons_with_data.add(season)
            
            assert len(seasonal_stats) == len(seasons_with_data), "Should have stats for all seasons with data"
            
            # Test 5: Simulation metadata can be generated
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            metadata = {
                'simulation_id': f'test_sim_{timestamp}',
                'creation_date': datetime.now().isoformat(),
                'num_days': actual_days,
                'start_date': start_date.isoformat(),
                'end_date': (start_date + timedelta(days=actual_days-1)).isoformat(),
                'parameter_count': len(parameter_manifest.overall_parameters),
                'trend_mode': False,
                'random_seed': 42,
                'total_precipitation': float(precipitation_series.sum()),
                'wet_days': int(sum(1 for val in precipitation_series if val > 0.1)),
                'wet_frequency': float(sum(1 for val in precipitation_series if val > 0.1) / len(precipitation_series))
            }
            
            # Validate metadata structure
            assert isinstance(metadata, dict), "Metadata should be a dictionary"
            assert 'simulation_id' in metadata, "Should have simulation ID"
            assert 'creation_date' in metadata, "Should have creation date"
            assert 'num_days' in metadata, "Should have number of days"
            assert 'total_precipitation' in metadata, "Should have total precipitation"
            assert 'wet_days' in metadata, "Should have wet days count"
            assert 'wet_frequency' in metadata, "Should have wet frequency"
            
            # Test JSON serialization of metadata
            import json
            json_str = json.dumps(metadata)
            assert len(json_str) > 0, "Metadata should be JSON serializable"
            
        except Exception as e:
            # For property tests, we expect some failures with edge cases
            # Only fail if it's a fundamental issue, not edge case behavior
            if num_days < 1:
                # Expected failure for invalid input
                return
            else:
                raise AssertionError(f"Simulation output completeness failed: {e}")


if __name__ == "__main__":
    # Run comprehensive tests
    print("Running Simulation Initialization Tests...")
    init_tester = SimulationInitializationTester()
    init_results = init_tester.run_comprehensive_tests()
    
    print(f"\nInitialization Test Results:")
    for test_name, result in init_results.items():
        status = "PASS" if result else "FAIL"
        print(f"  {test_name}: {status}")
    
    print("\nRunning Synthetic Generation Tests...")
    gen_tester = SyntheticGenerationTester()
    gen_results = gen_tester.run_comprehensive_tests()
    
    print(f"\nGeneration Test Results:")
    for test_name, result in gen_results.items():
        status = "PASS" if result else "FAIL"
        print(f"  {test_name}: {status}")
    
    # Overall summary
    all_results = {**init_results, **gen_results}
    total_tests = len(all_results)
    passed_tests = sum(all_results.values())
    
    print(f"\nOverall Results: {passed_tests}/{total_tests} tests passed ({passed_tests/total_tests*100:.1f}%)")
    
    if passed_tests == total_tests:
        print("All simulation workflow tests PASSED!")
    else:
        print("Some simulation workflow tests FAILED. Check logs for details.")
