#!/usr/bin/env python3

"""
Cross-platform validation for cx_boost_* macros in ldastools_cmake.
Tests boost detection across different operating systems and environments.
"""

import subprocess
import sys
import os
import platform
import tempfile
import shutil

class BoostMacroTester:
    def __init__(self):
        self.results = []
        self.build_dir = None
        self.modules_dir = os.path.join(os.path.dirname(__file__), "..", "Modules")
        
    def setup(self):
        """Create temporary build directory."""
        self.build_dir = tempfile.mkdtemp(prefix="ldastools_boost_test_")
        print(f"Using build directory: {self.build_dir}")
        return True
        
    def cleanup(self):
        """Clean up temporary files."""
        if self.build_dir and os.path.exists(self.build_dir):
            shutil.rmtree(self.build_dir)
            
    def run_cmake_test(self, test_name, cmake_args=None, env_vars=None):
        """Run a CMake test with the cx_boost macros."""
        print(f"\n{'='*60}")
        print(f"Testing: {test_name}")
        print(f"{'='*60}")
        
        try:
            # Prepare environment
            env = os.environ.copy()
            if env_vars:
                env.update(env_vars)
                
            # Prepare CMake command
            cmake_cmd = [
                "cmake",
                f"-DCMAKE_MODULE_PATH={os.path.abspath(self.modules_dir)}",
            ]
            
            if cmake_args:
                cmake_cmd.extend(cmake_args)
                
            # Add the test script
            test_script = os.path.join(os.path.dirname(__file__), "test_cx_boost_macros.cmake")
            cmake_cmd.extend(["-P", test_script])
            
            print(f"Command: {' '.join(cmake_cmd)}")
            if env_vars:
                print(f"Environment: {env_vars}")
                
            # Run the test
            result = subprocess.run(
                cmake_cmd,
                cwd=self.build_dir,
                env=env,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                timeout=300  # 5 minute timeout
            )
            
            success = result.returncode == 0
            
            # Parse output for specific success indicators
            if "✅ SUCCESS: Boost found" in result.stdout:
                print("✅ PASSED: Boost detection successful")
            elif "❌ FAILED: Boost not found" in result.stdout:
                print("❌ FAILED: Boost detection failed")
                success = False
            else:
                print("⚠️  UNCLEAR: Could not determine boost detection status")
                
            # Show relevant output
            if result.stdout:
                print("\nCMake Output:")
                for line in result.stdout.split('\n'):
                    if any(keyword in line for keyword in ['BOOST', 'SUCCESS', 'FAILED', 'ERROR']):
                        print(f"  {line}")
                        
            if result.stderr and not success:
                print("\nCMake Errors:")
                print(result.stderr)
                
            self.results.append((test_name, success, result.stdout, result.stderr))
            return success
            
        except subprocess.TimeoutExpired:
            print("❌ FAILED: Test timed out")
            self.results.append((test_name, False, "", "Timeout"))
            return False
        except Exception as e:
            print(f"❌ FAILED: Exception: {e}")
            self.results.append((test_name, False, "", str(e)))
            return False
            
    def test_platform_detection(self):
        """Test platform-specific boost detection."""
        system = platform.system().lower()
        
        if system == "linux":
            # Test standard Linux boost
            self.run_cmake_test("Linux Standard Boost")
            
            # Test EL8 boost169 if available
            if os.path.exists("/usr/include/boost169"):
                self.run_cmake_test(
                    "Linux EL8 boost169",
                    env_vars={
                        "BOOST_ROOT": "/usr",
                        "BOOST_INCLUDEDIR": "/usr/include/boost169",
                        "BOOST_LIBRARYDIR": "/usr/lib64/boost169"
                    }
                )
                
        elif system == "darwin":
            # Test macOS boost (likely via Homebrew)
            self.run_cmake_test("macOS Standard Boost")
            
            # Test Homebrew boost if available
            if os.path.exists("/usr/local/include/boost") or os.path.exists("/opt/homebrew/include/boost"):
                homebrew_prefix = "/opt/homebrew" if os.path.exists("/opt/homebrew") else "/usr/local"
                self.run_cmake_test(
                    "macOS Homebrew Boost",
                    env_vars={"BOOST_ROOT": homebrew_prefix}
                )
                
        elif system == "windows":
            # Test Windows boost
            self.run_cmake_test("Windows Standard Boost")
            
        # Test conda environment if available
        if "CONDA_PREFIX" in os.environ:
            self.run_cmake_test(
                "Conda Environment Boost",
                env_vars={"BOOST_ROOT": os.environ["CONDA_PREFIX"]}
            )
            
    def test_version_requirements(self):
        """Test version requirement handling."""
        # Test minimum version
        self.run_cmake_test(
            "Version Requirement 1.40",
            cmake_args=["-DBOOST_MIN_VERSION=1.40"]
        )
        
        # Test higher version requirement
        self.run_cmake_test(
            "Version Requirement 1.69",
            cmake_args=["-DBOOST_MIN_VERSION=1.69"]
        )
        
    def test_component_detection(self):
        """Test individual component detection."""
        components = ["filesystem", "system", "thread", "chrono"]
        
        for component in components:
            self.run_cmake_test(
                f"Component {component}",
                cmake_args=[f"-DTEST_COMPONENT={component}"]
            )
            
    def test_error_conditions(self):
        """Test error handling."""
        # Test with invalid boost root
        self.run_cmake_test(
            "Invalid Boost Root",
            env_vars={"BOOST_ROOT": "/nonexistent/path"}
        )
        
    def print_summary(self):
        """Print test summary."""
        print("\n" + "="*60)
        print("LDASTools CMake - cx_boost_* MACROS VALIDATION SUMMARY")
        print("="*60)
        
        passed = sum(1 for _, success, _, _ in self.results if success)
        total = len(self.results)
        
        print(f"\nPlatform: {platform.system()} {platform.machine()}")
        print(f"Python: {platform.python_version()}")
        print(f"Modules: {self.modules_dir}")
        
        print(f"\nTest Results:")
        for test_name, success, _, _ in self.results:
            status = "✅ PASSED" if success else "❌ FAILED"
            print(f"  {test_name:30} | {status}")
            
        print(f"\nSummary: {passed}/{total} tests passed")
        
        if passed == total:
            print("\n🎉 ALL cx_boost_* MACRO TESTS PASSED!")
            print("Boost detection is working correctly on this platform.")
            return True
        else:
            print(f"\n⚠️  {total - passed} test(s) failed")
            print("Some boost detection scenarios may need attention.")
            return False
            
def main():
    """Main test execution."""
    print("LDASTools CMake - cx_boost_* Macros Cross-Platform Validation")
    print("Testing boost detection across different environments\n")
    
    tester = BoostMacroTester()
    
    try:
        # Setup
        if not tester.setup():
            print("❌ Setup failed")
            return False
            
        # Run tests
        print("Running platform detection tests...")
        tester.test_platform_detection()
        
        print("\nRunning version requirement tests...")
        tester.test_version_requirements()
        
        print("\nRunning component detection tests...")
        tester.test_component_detection()
        
        print("\nRunning error condition tests...")
        tester.test_error_conditions()
        
        # Summary
        success = tester.print_summary()
        return success
        
    finally:
        tester.cleanup()
        
if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)