import sys
import os
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))

from src.mcp_client import ts_cpp_get_definition, ts_cpp_get_signature, ts_cpp_get_code_outline, ts_cpp_get_skeleton
from src.aggregate import build_tier3_context

def test_gencpp_full_suite():
    base_dir = Path("tests/assets/gencpp_samples")
    
    # Test all .hpp files in components
    components_dir = base_dir / "components"
    hpp_files = list(components_dir.glob("*.hpp"))
    hpp_files.extend(list((base_dir / "dependencies").glob("*.hpp")))
    hpp_files.extend(list(base_dir.glob("*.hpp")))
    hpp_files.extend(list((base_dir / "auxiliary").glob("*.hpp")))
    
    print(f"Testing {len(hpp_files)} .hpp files from gencpp/base...")
    
    failures = []
    
    for hpp_file in hpp_files:
        filename = hpp_file.name
        print(f"\n=== Testing {filename} ===")
        
        # 1. Skeleton should work without errors
        skeleton = ts_cpp_get_skeleton(str(hpp_file))
        if skeleton.startswith("ERROR:"):
            failures.append(f"{filename}: skeleton failed")
            print(f"  [FAIL] skeleton: {skeleton[:100]}")
        else:
            print(f"  [PASS] skeleton ({len(skeleton)} chars)")
        
        # 2. Outline should work without errors
        outline = ts_cpp_get_code_outline(str(hpp_file))
        if outline.startswith("ERROR:"):
            failures.append(f"{filename}: outline failed")
            print(f"  [FAIL] outline: {outline[:100]}")
        else:
            lines = outline.strip().split('\n')
            print(f"  [PASS] outline ({len(lines)} entries)")
        
        # 3. Get definitions for key symbols from outlines
        for line in outline.strip().split('\n')[:5]:  # Test first 5 symbols
            if '[' in line:
                # Extract symbol name
                parts = line.split('] ')
                if len(parts) > 1:
                    symbol = parts[1].split(' ')[0].split('(')[0]
                    # Handle nested types
                    symbol = symbol.replace('::', '.')
                    
                    # Try different lookup styles
                    for lookup in [symbol, symbol.split('.')[-1] if '.' in symbol else symbol]:
                        defn = ts_cpp_get_definition(str(hpp_file), lookup)
                        if not defn.startswith("ERROR"):
                            print(f"  [PASS] get_definition({lookup}): {defn[:50]}...")
                            break
                    else:
                        print(f"  [INFO] get_definition({symbol}) not found (may be expected)")
    
    # Test aggregation with AST masking on a sample file
    print("\n=== Testing AST Masking with aggregation ===")
    ast_hpp = base_dir / "components" / "ast.hpp"
    if ast_hpp.exists():
        item = {
            "path": ast_hpp,
            "entry": str(ast_hpp),
            "content": ast_hpp.read_text(encoding="utf-8"),
            "ast_mask": {"AST": "def", "Code::append": "sig"},
            "auto_aggregate": True,
            "force_full": False,
            "tier": None
        }
        
        res = build_tier3_context([item], Path("."), [], [], [])
        if "(Masked)" in res and "struct AST" in res:
            print(f"  [PASS] AST masking works")
        else:
            failures.append("AST masking: missing expected content")
            print(f"  [FAIL] AST masking result unexpected")
    
    print(f"\n=== SUMMARY ===")
    if failures:
        print(f"FAILURES ({len(failures)}):")
        for f in failures:
            print(f"  - {f}")
        return False
    else:
        print("ALL TESTS PASSED")
        return True

if __name__ == "__main__":
    success = test_gencpp_full_suite()
    sys.exit(0 if success else 1)