#!/usr/bin/env python3
"""
Integration tests for CLI interfaces to prevent conflicts and ensure compatibility.

This module tests the different CLI entry points to ensure they work correctly
and that the compatibility layer functions as expected.
"""

import subprocess
import pytest
import warnings
import sys
import os
from pathlib import Path

# Add src to path
current_dir = Path(__file__).parent
src_dir = current_dir.parent.parent / "src"
sys.path.insert(0, str(src_dir))

from mcp_memory_service.cli.main import memory_server_main, main as cli_main


class TestCLIInterfaces:
    """Test CLI interface compatibility and functionality."""
    
    def test_memory_command_backward_compatibility(self):
        """Test that 'uv run memory' (without server) starts the MCP server for backward compatibility."""
        result = subprocess.run(
            ["uv", "run", "memory", "--help"],
            capture_output=True,
            text=True,
            timeout=10,
            cwd=current_dir.parent.parent
        )
        # Should show help text (not start server) when --help is provided
        assert result.returncode == 0
        assert "MCP Memory Service" in result.stdout
    
    def test_memory_command_exists(self):
        """Test that the memory command is available."""
        result = subprocess.run(
            ["uv", "run", "memory", "--help"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        assert result.returncode == 0
        assert "MCP Memory Service" in result.stdout
        assert "server" in result.stdout
        assert "status" in result.stdout
    
    def test_memory_server_command_exists(self):
        """Test that the memory-server command is available."""
        result = subprocess.run(
            ["uv", "run", "memory-server", "--help"],
            capture_output=True, 
            text=True,
            cwd=current_dir.parent.parent
        )
        assert result.returncode == 0
        assert "MCP Memory Service" in result.stdout
        # Should show deprecation warning in stderr
        assert "deprecated" in result.stderr.lower()
    
    def test_mcp_memory_server_command_exists(self):
        """Test that the mcp-memory-server command is available."""
        result = subprocess.run(
            ["uv", "run", "mcp-memory-server", "--help"],
            capture_output=True,
            text=True, 
            cwd=current_dir.parent.parent
        )
        # This might have different behavior or missing dependencies
        # 0 for success, 1 for import error (missing fastmcp), 2 for argument error
        assert result.returncode in [0, 1, 2]
        
        # If it failed due to missing fastmcp dependency, that's expected
        if result.returncode == 1 and "fastmcp" in result.stderr:
            pytest.skip("mcp-memory-server requires FastMCP which is not installed")
    
    def test_memory_server_version_flag(self):
        """Test that memory-server --version works and shows deprecation warning."""
        result = subprocess.run(
            ["uv", "run", "memory-server", "--version"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        assert result.returncode == 0
        assert "8.24.0" in result.stdout
        assert "deprecated" in result.stderr.lower()
    
    def test_memory_server_vs_memory_server_subcommand(self):
        """Test that both memory-server and memory server provide similar functionality."""
        # Test memory-server --help
        result1 = subprocess.run(
            ["uv", "run", "memory-server", "--help"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        
        # Test memory server --help  
        result2 = subprocess.run(
            ["uv", "run", "memory", "server", "--help"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        
        assert result1.returncode == 0
        assert result2.returncode == 0

        # Both should mention debug option
        assert "--debug" in result1.stdout
        assert "--debug" in result2.stdout
        # Note: --chroma-path removed in v8.0.0
    
    def test_compatibility_wrapper_deprecation_warning(self):
        """Test that the compatibility wrapper issues deprecation warnings."""
        # Capture warnings when calling memory_server_main
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")  # Ensure all warnings are caught
            
            # Mock sys.argv to test argument parsing
            original_argv = sys.argv
            try:
                sys.argv = ["memory-server", "--version"]
                # This will raise SystemExit due to --version, which is expected
                with pytest.raises(SystemExit) as exc_info:
                    memory_server_main()
                assert exc_info.value.code == 0  # Should exit successfully
            finally:
                sys.argv = original_argv
            
            # Check that deprecation warning was issued
            deprecation_warnings = [warning for warning in w if issubclass(warning.category, DeprecationWarning)]
            assert len(deprecation_warnings) > 0
            assert "deprecated" in str(deprecation_warnings[0].message).lower()
            assert "memory server" in str(deprecation_warnings[0].message)
    
    def test_argument_compatibility(self):
        """Test that arguments are properly passed through compatibility wrapper."""
        # Test with --debug flag
        result = subprocess.run(
            ["uv", "run", "memory-server", "--help"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        
        assert result.returncode == 0
        assert "--debug" in result.stdout
        assert "--version" in result.stdout
        # Note: --chroma-path removed in v8.0.0
    
    def test_no_cli_conflicts_during_import(self):
        """Test that importing CLI modules doesn't cause conflicts."""
        try:
            # These imports should work without conflicts
            from mcp_memory_service.cli.main import main, memory_server_main
            from mcp_memory_service import server
            
            # Check that functions exist and are callable
            assert callable(main)
            assert callable(memory_server_main)
            assert callable(server.main)
            
            # Should not raise any import errors or conflicts
        except ImportError as e:
            pytest.fail(f"CLI import conflict detected: {str(e)}")


class TestCLIFunctionality:
    """Test actual CLI functionality to ensure commands work end-to-end."""
    
    def test_memory_status_command(self):
        """Test that memory status command works."""
        result = subprocess.run(
            ["uv", "run", "memory", "status"],
            capture_output=True,
            text=True,
            timeout=30,
            cwd=current_dir.parent.parent
        )
        # Status command might fail if no storage is available, but should not crash
        # Return code 0 = success, 1 = expected error (e.g., no storage)
        assert result.returncode in [0, 1]
        
        if result.returncode == 0:
            assert "MCP Memory Service Status" in result.stdout
            assert "Version: 8.24.0" in result.stdout
        else:
            # If it fails, should have a meaningful error message
            assert len(result.stderr) > 0 or len(result.stdout) > 0


class TestCLIRobustness:
    """Test CLI robustness and edge cases."""
    
    def test_environment_variable_passing(self):
        """Test that CLI arguments correctly set environment variables."""
        import os
        import subprocess

        # Test that --debug flag affects application behavior
        env = os.environ.copy()
        env.pop('MCP_DEBUG', None)  # Ensure not already set

        result = subprocess.run(
            ["uv", "run", "python", "-c", """
import os
import sys
from mcp_memory_service.cli.main import cli
from click.testing import CliRunner

# Test that --debug flag is recognized and sets debug mode
runner = CliRunner()
result = runner.invoke(cli, ['server', '--debug', '--help'])
print(f'EXIT_CODE:{result.exit_code}')
print(f'DEBUG_IN_OUTPUT:{\"--debug\" in result.output}')
"""],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent,
            env=env,
            timeout=10
        )

        # Should succeed and recognize --debug flag
        assert result.returncode == 0
        assert 'EXIT_CODE:0' in result.stdout
        assert 'DEBUG_IN_OUTPUT:True' in result.stdout
    
    def test_cli_error_handling(self):
        """Test that CLI handles errors gracefully."""
        # Test invalid storage backend
        result = subprocess.run(
            ["uv", "run", "memory", "server", "--storage-backend", "invalid"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent,
            timeout=10
        )
        
        # Should fail with clear error message
        assert result.returncode != 0
        assert len(result.stderr) > 0 or "invalid" in result.stdout.lower()
    
    def test_memory_server_argument_parity(self):
        """Test that memory-server and memory server support the same core arguments."""
        import subprocess
        
        # Test memory server arguments
        result1 = subprocess.run(
            ["uv", "run", "memory", "server", "--help"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        
        # Test memory-server arguments
        result2 = subprocess.run(
            ["uv", "run", "memory-server", "--help"],
            capture_output=True,
            text=True,
            cwd=current_dir.parent.parent
        )
        
        assert result1.returncode == 0
        assert result2.returncode == 0
        
        # Both should support debug argument
        assert "--debug" in result1.stdout
        assert "--debug" in result2.stdout
        # Note: --chroma-path removed in v8.0.0
    
    def test_entry_point_isolation(self):
        """Test that different entry points don't interfere with each other."""
        # Test that we can import all entry points without conflicts
        try:
            # Import main CLI
            from mcp_memory_service.cli.main import main, memory_server_main
            
            # Import server main
            from mcp_memory_service.server import main as server_main
            
            # Verify they're different functions
            assert main != memory_server_main
            assert main != server_main
            assert memory_server_main != server_main
            
            # Verify they're all callable
            assert callable(main)
            assert callable(memory_server_main)  
            assert callable(server_main)
            
        except ImportError as e:
            pytest.fail(f"Entry point isolation failed: {e}")
    
    def test_backward_compatibility_deprecation_warning(self):
        """Test that using 'memory' without subcommand shows deprecation warning."""
        import warnings
        import sys
        from mcp_memory_service.cli.main import cli
        
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            
            # Mock sys.argv to test backward compatibility
            original_argv = sys.argv
            try:
                # This simulates 'uv run memory' without subcommand
                sys.argv = ["memory"]
                with pytest.raises(SystemExit):  # Server will try to start and exit
                    cli(standalone_mode=False)
            except Exception:
                # Expected - server can't actually start in test environment
                pass
            finally:
                sys.argv = original_argv
            
            # Verify backward compatibility deprecation warning
            deprecation_warnings = [warning for warning in w if issubclass(warning.category, DeprecationWarning)]
            assert len(deprecation_warnings) > 0
            
            warning_msg = str(deprecation_warnings[0].message)
            assert "without a subcommand is deprecated" in warning_msg
            assert "memory server" in warning_msg
            assert "backward compatibility will be removed" in warning_msg
    
    def test_deprecation_warning_format(self):
        """Test that deprecation warning has proper format and information."""
        import warnings
        import sys
        from mcp_memory_service.cli.main import memory_server_main
        
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            
            # Mock sys.argv for the compatibility wrapper
            original_argv = sys.argv
            try:
                sys.argv = ["memory-server", "--version"]
                with pytest.raises(SystemExit):  # --version causes system exit
                    memory_server_main()
            finally:
                sys.argv = original_argv
            
            # Verify deprecation warning content
            deprecation_warnings = [warning for warning in w if issubclass(warning.category, DeprecationWarning)]
            assert len(deprecation_warnings) > 0
            
            warning_msg = str(deprecation_warnings[0].message)
            assert "memory-server" in warning_msg.lower()
            assert "deprecated" in warning_msg.lower() 
            assert "memory server" in warning_msg.lower()
            assert "removed" in warning_msg.lower()


class TestCLIPerformance:
    """Test CLI performance characteristics."""
    
    def test_cli_startup_time(self):
        """Test that CLI commands start reasonably quickly."""
        import time
        import subprocess
        
        start_time = time.time()
        result = subprocess.run(
            ["uv", "run", "memory", "--help"],
            capture_output=True,
            text=True,
            timeout=30,
            cwd=current_dir.parent.parent
        )
        elapsed = time.time() - start_time
        
        assert result.returncode == 0
        # CLI help should respond within 30 seconds (generous timeout for CI)
        assert elapsed < 30
        # Log performance for monitoring
        print(f"CLI startup took {elapsed:.2f} seconds")
    
    def test_memory_version_performance(self):
        """Test that version commands are fast."""
        import time
        import subprocess
        
        # Test both version commands
        commands = [
            ["uv", "run", "memory", "--version"],
            ["uv", "run", "memory-server", "--version"]
        ]
        
        for cmd in commands:
            start_time = time.time()
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=15,
                cwd=current_dir.parent.parent
            )
            elapsed = time.time() - start_time
            
            assert result.returncode == 0
            assert "8.24.0" in result.stdout
            # Version should be very fast
            assert elapsed < 15
            print(f"Version command {' '.join(cmd[2:])} took {elapsed:.2f} seconds")


if __name__ == "__main__":
    pytest.main([__file__, "-v"])