#!/usr/bin/env python3
"""
Genesis Agent Tier Validation Test Suite

Tests the L1-L4 tier system to ensure:
1. Tier definitions load correctly
2. Capability resolution works
3. Tool access restrictions are enforced
4. Agent frontmatter parsing works
"""

import sys
from pathlib import Path

# Add project root to path
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT))

from core.tiering.tier_gate import TierGate
from core.tiering.tier_config import load_tier_config, resolve_capabilities, parse_agent_frontmatter


def test_tier_config_loads():
    """Test that tier_definitions.json loads successfully."""
    print("\n=== Test 1: Tier Config Loading ===")
    config = load_tier_config()

    assert "tiers" in config, "Config missing 'tiers' key"
    assert "BASIC" in config["tiers"], "Missing BASIC tier"
    assert "STANDARD" in config["tiers"], "Missing STANDARD tier"
    assert "PRO" in config["tiers"], "Missing PRO tier"
    assert "ENTERPRISE" in config["tiers"], "Missing ENTERPRISE tier"

    print("✅ All 4 tiers present in config")
    return True


def test_capability_resolution():
    """Test that capability inheritance works correctly."""
    print("\n=== Test 2: Capability Resolution ===")
    config = load_tier_config()

    # BASIC has 5 base capabilities
    basic_caps = resolve_capabilities("BASIC", config)
    print(f"BASIC capabilities: {len(basic_caps)}")
    assert "text_chat" in basic_caps
    assert "web_search" in basic_caps

    # STANDARD inherits BASIC + adds 10 more
    standard_caps = resolve_capabilities("STANDARD", config)
    print(f"STANDARD capabilities: {len(standard_caps)}")
    assert "text_chat" in standard_caps  # inherited
    assert "native_voice" in standard_caps  # new
    assert len(standard_caps) > len(basic_caps)

    # PRO inherits STANDARD + adds 4 more
    pro_caps = resolve_capabilities("PRO", config)
    print(f"PRO capabilities: {len(pro_caps)}")
    assert "native_voice" in pro_caps  # inherited
    assert "domain_expertise" in pro_caps  # new
    assert len(pro_caps) > len(standard_caps)

    # ENTERPRISE inherits PRO + adds 13 more
    enterprise_caps = resolve_capabilities("ENTERPRISE", config)
    print(f"ENTERPRISE capabilities: {len(enterprise_caps)}")
    assert "domain_expertise" in enterprise_caps  # inherited
    assert "constitutional_guard" in enterprise_caps  # new
    assert len(enterprise_caps) > len(pro_caps)

    print("✅ Capability inheritance working correctly")
    return True


def test_l1_basic_gate():
    """Test L1 Basic tier restrictions."""
    print("\n=== Test 3: L1 Basic Tier Gate ===")
    gate = TierGate("BASIC")

    # Check capabilities
    assert gate.has("text_chat"), "BASIC should have text_chat"
    assert gate.has("web_search"), "BASIC should have web_search"
    assert not gate.has("native_voice"), "BASIC should NOT have native_voice"
    assert not gate.has("multi_agent"), "BASIC should NOT have multi_agent"

    # Check tool access
    tools = gate.get_tool_access()
    assert "Read" in tools, "BASIC should have Read tool"
    assert "WebSearch" in tools, "BASIC should have WebSearch tool"
    assert "Edit" not in tools, "BASIC should NOT have Edit tool"
    assert "Bash" not in tools, "BASIC should NOT have Bash tool"

    # Check limits
    limits = gate.get_budget_limits()
    assert limits["daily_budget_usd"] == 1.00
    assert limits["max_turns"] == 50

    # Check autonomy
    assert gate.get_autonomy_level() == 3  # Advisory only

    # Check tier comparison
    assert not gate.at_least("STANDARD"), "BASIC is not >= STANDARD"
    assert gate.at_least("BASIC"), "BASIC is >= BASIC"

    print(f"✅ L1 Basic gate working: {len(gate.get_all_capabilities())} capabilities")
    return True


def test_l2_standard_gate():
    """Test L2 Digital Employee tier."""
    print("\n=== Test 4: L2 Digital Employee Tier Gate ===")
    gate = TierGate("STANDARD")

    # Check capabilities (inherits BASIC + adds new)
    assert gate.has("text_chat"), "STANDARD should have text_chat (inherited)"
    assert gate.has("native_voice"), "STANDARD should have native_voice"
    assert gate.has("persistent_memory"), "STANDARD should have persistent_memory"
    assert gate.has("browser"), "STANDARD should have browser"
    assert not gate.has("multi_agent"), "STANDARD should NOT have multi_agent"

    # Check tool access
    tools = gate.get_tool_access()
    assert "Read" in tools
    assert "Bash" in tools, "STANDARD should have Bash tool"
    assert "WebFetch" in tools, "STANDARD should have WebFetch tool"
    assert "Edit" not in tools, "STANDARD should NOT have Edit tool"

    # Check MCP tools
    mcp_tools = gate.get_mcp_tools()
    assert "kg_*" in mcp_tools or any("kg" in t for t in mcp_tools), "STANDARD should have KG tools"
    assert "memory_*" in mcp_tools or any("memory" in t for t in mcp_tools), "STANDARD should have memory tools"

    # Check limits
    limits = gate.get_budget_limits()
    assert limits["daily_budget_usd"] == 5.00
    assert limits["max_turns"] == 100

    # Check autonomy
    assert gate.get_autonomy_level() == 2  # Pre-confirmation

    # Check tier comparison
    assert gate.at_least("BASIC"), "STANDARD is >= BASIC"
    assert gate.at_least("STANDARD"), "STANDARD is >= STANDARD"
    assert not gate.at_least("PRO"), "STANDARD is not >= PRO"

    print(f"✅ L2 Standard gate working: {len(gate.get_all_capabilities())} capabilities")
    return True


def test_l3_pro_gate():
    """Test L3 Domain Expert tier."""
    print("\n=== Test 5: L3 Domain Expert Tier Gate ===")
    gate = TierGate("PRO")

    # Check capabilities (inherits STANDARD + adds domain expertise)
    assert gate.has("native_voice"), "PRO should have native_voice (inherited)"
    assert gate.has("domain_expertise"), "PRO should have domain_expertise"
    assert gate.has("platform_workflows"), "PRO should have platform_workflows"
    assert not gate.has("multi_agent"), "PRO should NOT have multi_agent"

    # Check domain overlays
    overlays = gate.get_domain_overlays()
    assert overlays == 1, "PRO should allow 1 domain overlay"

    # Check limits
    limits = gate.get_budget_limits()
    assert limits["daily_budget_usd"] == 10.00
    assert limits["max_turns"] == 150

    # Check tier comparison
    assert gate.at_least("BASIC")
    assert gate.at_least("STANDARD")
    assert gate.at_least("PRO")
    assert not gate.at_least("ENTERPRISE")

    print(f"✅ L3 Pro gate working: {len(gate.get_all_capabilities())} capabilities")
    return True


def test_l4_executive_gate():
    """Test L4 Digital Executive tier."""
    print("\n=== Test 6: L4 Digital Executive Tier Gate ===")
    gate = TierGate("ENTERPRISE")

    # Check capabilities (inherits PRO + adds everything)
    assert gate.has("domain_expertise"), "ENTERPRISE should have domain_expertise (inherited)"
    assert gate.has("multi_agent"), "ENTERPRISE should have multi_agent"
    assert gate.has("constitutional_guard"), "ENTERPRISE should have constitutional_guard"
    assert gate.has("ide_access"), "ENTERPRISE should have ide_access"
    assert gate.has("sovereign_memory"), "ENTERPRISE should have sovereign_memory"

    # Check tool access
    tools = gate.get_tool_access()
    assert "Read" in tools
    assert "Edit" in tools, "ENTERPRISE should have Edit tool"
    assert "Write" in tools, "ENTERPRISE should have Write tool"
    assert "TaskCreate" in tools, "ENTERPRISE should have TaskCreate tool"
    assert "TeamCreate" in tools, "ENTERPRISE should have TeamCreate tool"

    # Check domain overlays
    overlays = gate.get_domain_overlays()
    assert overlays == -1, "ENTERPRISE should allow unlimited domain overlays"

    # Check limits
    limits = gate.get_budget_limits()
    assert limits["daily_budget_usd"] == 50.00
    assert limits["max_turns"] == 200

    # Check autonomy
    assert gate.get_autonomy_level() == 1  # Post-notification

    # Check tier comparison
    assert gate.at_least("BASIC")
    assert gate.at_least("STANDARD")
    assert gate.at_least("PRO")
    assert gate.at_least("ENTERPRISE")

    print(f"✅ L4 Executive gate working: {len(gate.get_all_capabilities())} capabilities")
    return True


def test_agent_frontmatter_parsing():
    """Test parsing agent definition files."""
    print("\n=== Test 7: Agent Frontmatter Parsing ===")

    agents_dir = PROJECT_ROOT / ".claude" / "agents"

    # Test L1 Basic
    l1_path = agents_dir / "l1-basic.md"
    if l1_path.exists():
        parsed = parse_agent_frontmatter(str(l1_path))
        assert "frontmatter" in parsed
        assert "body" in parsed
        assert parsed["frontmatter"]["name"] == "l1-basic"
        assert parsed["frontmatter"]["tier"] == "BASIC"
        print(f"✅ Parsed l1-basic.md: tier={parsed['frontmatter']['tier']}")

    # Test L2 Digital Employee
    l2_path = agents_dir / "l2-digital-employee.md"
    if l2_path.exists():
        parsed = parse_agent_frontmatter(str(l2_path))
        assert parsed["frontmatter"]["name"] == "l2-digital-employee"
        assert parsed["frontmatter"]["tier"] == "STANDARD"
        print(f"✅ Parsed l2-digital-employee.md: tier={parsed['frontmatter']['tier']}")

    # Test L3 Domain Expert
    l3_path = agents_dir / "l3-domain-expert.md"
    if l3_path.exists():
        parsed = parse_agent_frontmatter(str(l3_path))
        assert parsed["frontmatter"]["name"] == "l3-domain-expert"
        assert parsed["frontmatter"]["tier"] == "PRO"
        print(f"✅ Parsed l3-domain-expert.md: tier={parsed['frontmatter']['tier']}")

    # Test L4 Executive
    l4_path = agents_dir / "l4-executive.md"
    if l4_path.exists():
        parsed = parse_agent_frontmatter(str(l4_path))
        assert parsed["frontmatter"]["name"] == "l4-executive"
        assert parsed["frontmatter"]["tier"] == "ENTERPRISE"
        print(f"✅ Parsed l4-executive.md: tier={parsed['frontmatter']['tier']}")

    return True


def test_from_agent_definition():
    """Test creating TierGate from agent definition file."""
    print("\n=== Test 8: TierGate.from_agent_definition() ===")

    agents_dir = PROJECT_ROOT / ".claude" / "agents"

    # Test L1
    l1_path = agents_dir / "l1-basic.md"
    if l1_path.exists():
        gate = TierGate.from_agent_definition(str(l1_path))
        assert gate.tier_name == "BASIC"
        assert not gate.has("native_voice")
        print(f"✅ L1 gate from file: {gate}")

    # Test L4
    l4_path = agents_dir / "l4-executive.md"
    if l4_path.exists():
        gate = TierGate.from_agent_definition(str(l4_path))
        assert gate.tier_name == "ENTERPRISE"
        assert gate.has("multi_agent")
        print(f"✅ L4 gate from file: {gate}")

    return True


def run_all_tests():
    """Run all tier validation tests."""
    print("\n" + "="*60)
    print("Genesis Agent Tier Validation Test Suite")
    print("="*60)

    tests = [
        ("Tier Config Loading", test_tier_config_loads),
        ("Capability Resolution", test_capability_resolution),
        ("L1 Basic Gate", test_l1_basic_gate),
        ("L2 Standard Gate", test_l2_standard_gate),
        ("L3 Pro Gate", test_l3_pro_gate),
        ("L4 Executive Gate", test_l4_executive_gate),
        ("Agent Frontmatter Parsing", test_agent_frontmatter_parsing),
        ("TierGate.from_agent_definition()", test_from_agent_definition),
    ]

    passed = 0
    failed = 0

    for test_name, test_func in tests:
        try:
            result = test_func()
            if result:
                passed += 1
        except Exception as e:
            print(f"\n❌ {test_name} FAILED: {e}")
            failed += 1

    print("\n" + "="*60)
    print(f"Test Results: {passed} passed, {failed} failed")
    print("="*60)

    if failed == 0:
        print("\n🎉 ALL TESTS PASSED! Genesis tier system is fully operational.")
        return 0
    else:
        print(f"\n⚠️  {failed} test(s) failed. Review errors above.")
        return 1


if __name__ == "__main__":
    exit_code = run_all_tests()
    sys.exit(exit_code)
