#!/usr/bin/env python3
"""
Comprehensive test for hierarchical configuration system.
"""

import sys
import os

# Set UTF-8 encoding for Windows
if sys.platform == 'win32':
    import codecs
    sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
    sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')

from pathlib import Path
import tempfile
import shutil
import yaml

# Add app to path
sys.path.insert(0, str(Path(__file__).parent))

from navig.commands.init import init_app
from navig.config import ConfigManager
from navig import console_helper as ch


def test_hierarchical_config():
    """Test complete hierarchical configuration system."""
    
    # Create temp directory for testing
    test_dir = Path(tempfile.mkdtemp(prefix="navig-hierarchy-test-"))
    print(f"\n{'='*80}")
    print(f"Test directory: {test_dir}")
    print(f"{'='*80}\n")
    
    try:
        original_dir = Path.cwd()
        
        # ========================================================================
        # TEST 1: Initialize app
        # ========================================================================
        print("TEST 1: Initialize App")
        print("-" * 80)
        os.chdir(test_dir)
        init_app({'copy_global': False, 'quiet': False, 'yes': True})
        
        navig_dir = test_dir / ".navig"
        if navig_dir.exists():
            ch.success("✓ App initialized successfully")
        else:
            ch.error("✗ App initialization failed", "")
            return
        
        # ========================================================================
        # TEST 2: Create app-specific host config
        # ========================================================================
        print("\nTEST 2: Create app-specific host config")
        print("-" * 80)
        
        app_host_config = {
            'name': 'test-server',
            'host': '10.0.0.1',
            'port': 2222,
            'user': 'app-user',
            'ssh_key': '~/.ssh/app_key',
            'database': {
                'type': 'mysql',
                'remote_port': 3306,
                'local_tunnel_port': 3307,
                'name': 'app_db',
                'user': 'app_dbuser',
                'password': 'app_pass'
            }
        }
        
        app_host_file = navig_dir / "hosts" / "test-server.yaml"
        with open(app_host_file, 'w') as f:
            yaml.dump(app_host_config, f)
        ch.info(f"Created app host config: {app_host_file}")
        
        # ========================================================================
        # TEST 3: Create global host config with different values
        # ========================================================================
        print("\nTEST 3: Create global host config")
        print("-" * 80)
        
        global_config_dir = Path.home() / ".navig"
        global_config_dir.mkdir(exist_ok=True)
        global_hosts_dir = global_config_dir / "hosts"
        global_hosts_dir.mkdir(exist_ok=True)
        
        global_host_config = {
            'name': 'test-server',
            'host': '10.0.0.10',  # Different IP
            'port': 22,  # Different port
            'user': 'global-user',  # Different user
            'ssh_key': '~/.ssh/global_key',
            'database': {
                'type': 'mysql',
                'remote_port': 3306,
                'local_tunnel_port': 3307,
                'name': 'global_db',  # Different database
                'user': 'global_dbuser',
                'password': 'global_pass'
            }
        }
        
        global_host_file = global_hosts_dir / "test-server.yaml"
        with open(global_host_file, 'w') as f:
            yaml.dump(global_host_config, f)
        ch.info(f"Created global host config: {global_host_file}")
        
        # ========================================================================
        # TEST 4: Load config from app directory (should use app config)
        # ========================================================================
        print("\nTEST 4: Load config from app directory")
        print("-" * 80)
        
        os.chdir(test_dir)
        config_mgr = ConfigManager(verbose=True)
        loaded_config = config_mgr.load_host_config('test-server')
        
        if loaded_config:
            if loaded_config['host'] == '10.0.0.1':
                ch.success("✓ App config takes precedence (correct)")
                ch.info(f"  Host: {loaded_config['host']} (app)")
                ch.info(f"  Port: {loaded_config['port']}")
                ch.info(f"  User: {loaded_config['user']}")
            else:
                ch.error(
                    "✗ Wrong config loaded",
                    f"Expected app config (10.0.0.1), got {loaded_config['host']}"
                )
        else:
            ch.error("✗ Failed to load host config", "")
        
        # ========================================================================
        # TEST 5: Load config from subdirectory (should still use app config)
        # ========================================================================
        print("\nTEST 5: Load config from subdirectory")
        print("-" * 80)
        
        subdir = test_dir / "src" / "components"
        subdir.mkdir(parents=True, exist_ok=True)
        os.chdir(subdir)
        
        config_mgr = ConfigManager(verbose=True)
        loaded_config = config_mgr.load_host_config('test-server')
        
        if loaded_config:
            if loaded_config['host'] == '10.0.0.1':
                ch.success("✓ App root detected from subdirectory (correct)")
                ch.info(f"  Current dir: {Path.cwd()}")
                ch.info(f"  App root: {config_mgr.base_dir.parent}")
                ch.info(f"  Host: {loaded_config['host']}")
            else:
                ch.error(
                    "✗ Wrong config loaded from subdirectory",
                    f"Expected app config, got {loaded_config['host']}"
                )
        else:
            ch.error("✗ Failed to load host config from subdirectory", "")
        
        # ========================================================================
        # TEST 6: Load config from outside app (should use global config)
        # ========================================================================
        print("\nTEST 6: Load config from outside app directory")
        print("-" * 80)
        
        temp_outside = Path(tempfile.mkdtemp(prefix="navig-outside-"))
        try:
            os.chdir(temp_outside)
            
            config_mgr = ConfigManager(verbose=True)
            loaded_config = config_mgr.load_host_config('test-server')
            
            if loaded_config:
                if loaded_config['host'] == '10.0.0.10':
                    ch.success("✓ Global config used outside app (correct)")
                    ch.info(f"  Host: {loaded_config['host']} (global)")
                    ch.info(f"  User: {loaded_config['user']}")
                else:
                    ch.error(
                        "✗ Wrong config loaded outside app",
                        f"Expected global config (10.0.0.10), got {loaded_config['host']}"
                    )
            else:
                ch.error("✗ Failed to load global host config", "")
        finally:
            os.chdir(test_dir)  # Change back before cleanup
            if temp_outside.exists():
                shutil.rmtree(temp_outside, ignore_errors=True)
        
        # ========================================================================
        # TEST 7: List hosts (should show merged list)
        # ========================================================================
        print("\nTEST 7: List hosts from app directory")
        print("-" * 80)
        
        os.chdir(test_dir)
        config_mgr = ConfigManager(verbose=True)
        hosts = config_mgr.list_hosts()
        
        if 'test-server' in hosts:
            ch.success(f"✓ Host 'test-server' found in list")
            ch.info(f"  Total hosts: {len(hosts)}")
        else:
            ch.error("✗ Host 'test-server' not found in host list", "")
        
        # ========================================================================
        # TEST 8: Database path separation
        # ========================================================================
        print("\nTEST 8: Database path separation")
        print("-" * 80)
        
        os.chdir(test_dir)
        config_mgr_app = ConfigManager(verbose=False)
        app_db_path = config_mgr_app.db_file
        
        temp_db_test = Path(tempfile.mkdtemp(prefix="navig-db-test-"))
        try:
            os.chdir(temp_db_test)
            config_mgr_global = ConfigManager(verbose=False)
            global_db_path = config_mgr_global.db_file
            
            if app_db_path != global_db_path:
                ch.success("✓ Database paths are separated")
                ch.info(f"  App DB: {app_db_path}")
                ch.info(f"  Global DB:  {global_db_path}")
            else:
                ch.error(
                    "✗ Database paths are not separated",
                    f"Both use: {app_db_path}"
                )
        finally:
            os.chdir(test_dir)
            if temp_db_test.exists():
                shutil.rmtree(temp_db_test, ignore_errors=True)
        
        # ========================================================================
        # Summary
        # ========================================================================
        print("\n" + "="*80)
        ch.success("All hierarchical configuration tests completed!")
        print("="*80 + "\n")
        
    finally:
        # Cleanup
        os.chdir(original_dir)
        if test_dir.exists():
            shutil.rmtree(test_dir)
            ch.dim(f"Cleaned up test directory: {test_dir}")
        
        # Cleanup global test config
        global_test_file = Path.home() / ".navig" / "hosts" / "test-server.yaml"
        if global_test_file.exists():
            global_test_file.unlink()
            ch.dim(f"Cleaned up global test config: {global_test_file}")


if __name__ == "__main__":
    test_hierarchical_config()
