#!/usr/bin/env python3
"""ARIS End-to-End Integration Test — Tests the full organism."""
import asyncio
import json
import os
import sys


async def test_integration():
    results = {"pass": 0, "fail": 0, "tests": []}
    sep = "=" * 50

    def check(name, condition, detail=""):
        if condition:
            results["pass"] += 1
            results["tests"].append(f"  PASS: {name}")
        else:
            results["fail"] += 1
            results["tests"].append(f"  FAIL: {name} - {detail}")

    # 1. Import all modules
    try:
        from aris_mcp.server import (
            mcp, _sessions, registry,
            aris_activate, aris_list_skills, aris_get_skill, aris_route_task,
            aris_guardian, aris_memory_save, aris_memory_recall, aris_memory_search,
            aris_budget_set, aris_budget_report, aris_budget_add_subscription,
            aris_forge, aris_scout_report, aris_analytics, aris_dev_license,
        )
        from aris_mcp.guardian import guardian_scan, check_node
        from aris_mcp.memory_store import MemoryStore
        from aris_mcp.budget import BudgetTracker
        from aris_mcp.analytics_store import AnalyticsStore
        check("All module imports", True)
    except ImportError as e:
        check("All module imports", False, str(e))
        print(f"FATAL: {e}")
        return results

    # 2. License flow: generate -> activate
    license_resp = await aris_dev_license(tier="pro", days=30)
    ld = json.loads(license_resp)
    check("Dev license generation", ld.get("status") == "ok", ld.get("message", ""))

    key = ld.get("license_key", "")
    act_resp = await aris_activate(key)
    ad = json.loads(act_resp)
    check("License activation", ad.get("status") == "activated", ad.get("status", ""))
    check("Tier = PRO", ad.get("tier") == "pro", ad.get("tier", ""))

    # 3. Skills registry
    skills_resp = await aris_list_skills("all")
    sd = json.loads(skills_resp)
    total = sd.get("total", 0)
    accessible = sd.get("accessible", 0)
    check(f"Skills loaded: {total} total, {accessible} accessible", total >= 60)

    # 4. Get a free skill
    skill_resp = await aris_get_skill("code-reviewer")
    skd = json.loads(skill_resp)
    check("Get free skill (code-reviewer)", skd.get("status") == "ok", skd.get("status", ""))
    check("Skill has content", len(skd.get("content", "")) > 100)

    # 5. Smart Router
    route_resp = await aris_route_task(
        "review this Python code for security vulnerabilities and write tests",
        "claude,ollama,gemini"
    )
    rd = json.loads(route_resp)
    check("Router works", rd.get("status") == "ok", rd.get("status", ""))
    steps = rd.get("routing", {}).get("steps", [])
    check(f"Router produced {len(steps)} steps", len(steps) > 0)
    models = rd.get("models_used", [])
    check(f"Router selected models: {models}", len(models) > 0)

    # Check routing intelligence
    privacy_resp = await aris_route_task("analyze patient medical records with HIPAA compliance", "claude,ollama,gemini")
    pd = json.loads(privacy_resp)
    p_steps = pd.get("routing", {}).get("steps", [])
    has_ollama = any(s.get("model") == "ollama" for s in p_steps)
    has_privacy = pd.get("routing", {}).get("privacy_flag", False)
    check("Privacy routing: sensitive -> Ollama", has_ollama, f"models: {[s.get('model') for s in p_steps]}")
    check("Privacy flag raised", has_privacy)

    # 6. Memory: save -> recall -> search
    save_resp = await aris_memory_save("int-test-key", "integration test value 123", "fact", "test,integration")
    svd = json.loads(save_resp)
    check("Memory save", svd.get("status") == "saved", svd.get("status", ""))
    check("Memory layer = hot", svd.get("layer") == "hot")

    recall_resp = await aris_memory_recall("int-test-key")
    rcd = json.loads(recall_resp)
    check("Memory recall correct value", rcd.get("value") == "integration test value 123")
    check("Memory has tags", "test" in rcd.get("tags", []))

    search_resp = await aris_memory_search("integration", "fact")
    srd = json.loads(search_resp)
    check("Memory search finds result", srd.get("total", 0) > 0)
    check("Memory stats present", "total" in srd.get("stats", {}))

    # 7. Budget: set limits -> add subscription -> report
    budget_resp = await aris_budget_set(monthly_limit=100, daily_limit=10, block_on_exceed=True)
    bd = json.loads(budget_resp)
    check("Budget limits set", bd.get("status") == "ok")

    sub_resp = await aris_budget_add_subscription("Claude Pro", 200, "unlimited,code,reasoning")
    sbd = json.loads(sub_resp)
    check("Subscription added", sbd.get("status") == "ok")

    report_resp = await aris_budget_report()
    rpd = json.loads(report_resp)
    check("Budget report works", rpd.get("status") == "ok")
    check("Report shows $200 subscription", rpd.get("subscriptions", {}).get("monthly_total") == 200)
    check("Report shows $100 monthly limit", rpd.get("limits", {}).get("monthly") == 100)
    check("Block on exceed = True", rpd.get("limits", {}).get("block_on_exceed") is True)

    # 8. Analytics: verify it tracked our operations
    an_resp = await aris_analytics("24h")
    and_ = json.loads(an_resp)
    check("Analytics returns data", and_.get("status") == "ok")
    check("Analytics tracked route events", and_.get("tasks_routed", 0) >= 2)  # We routed 2 tasks

    # 9. Scout report
    scout_resp = await aris_scout_report()
    scd = json.loads(scout_resp)
    check("Scout report works (no crash)", scd.get("status") == "ok")

    # 10. Forge: create -> retrieve -> verify
    forge_resp = await aris_forge(
        skill_name="int-test-skill",
        description="Integration test skill",
        instructions="# Test Skill\nThis was created by the integration test.\n\nIt verifies Forge works end-to-end.",
        category="dev", tier="free", tags="test,integration"
    )
    fd = json.loads(forge_resp)
    check("Forge creates skill", fd.get("status") == "created")

    # Retrieve the forged skill
    forged_resp = await aris_get_skill("int-test-skill")
    fgd = json.loads(forged_resp)
    check("Forged skill retrievable", fgd.get("status") == "ok")
    check("Forged skill content correct", "integration test" in fgd.get("content", "").lower())

    # 11. Guardian (localhost only)
    guard_resp = await aris_guardian("")  # empty = localhost
    gd = json.loads(guard_resp)
    check("Guardian scans localhost", gd.get("status") == "ok")
    nodes = gd.get("nodes", [])
    if nodes:
        node = nodes[0]
        check("Guardian reports RAM", node.get("ram", {}).get("total_mb", 0) > 0)
        check("Guardian reports CPU cores", node.get("cpu_cores", 0) > 0)
        check("Guardian reports health", node.get("health") in ("healthy", "warning", "critical"))
        check("Guardian reports disk", node.get("disk_used_pct", -1) >= 0)

    # 12. CROSS-TOOL CHAIN: Full workflow simulation
    # Simulate: check health -> route task -> save decision -> recall it -> track analytics

    # a) Guardian check
    guard2 = json.loads(await aris_guardian(""))
    can_work = guard2.get("available_for_work", [])
    check("Cross-chain: Guardian available", len(can_work) > 0)

    # b) Route a task based on health
    route2 = json.loads(await aris_route_task("build and deploy a web application", "claude,gemini"))
    steps2 = route2.get("routing", {}).get("steps", [])
    check("Cross-chain: Route after Guardian", len(steps2) > 0)

    # c) Save the decision
    decision = f"Routed build+deploy with {len(steps2)} steps, models: {route2.get('models_used', [])}"
    save2 = json.loads(await aris_memory_save("cross-chain-test", decision, "decision", "test,cross-chain"))
    check("Cross-chain: Decision saved", save2.get("status") == "saved")

    # d) Recall the decision
    recall2 = json.loads(await aris_memory_recall("cross-chain-test"))
    check("Cross-chain: Decision recalled", "Routed" in recall2.get("value", ""))

    # e) Analytics should show all our activity
    an2 = json.loads(await aris_analytics("1h"))
    check("Cross-chain: Analytics tracked everything", an2.get("total_events", 0) >= 5)

    # Cleanup
    from aris_mcp.server import _memory as mem
    mem.delete("int-test-key")
    mem.delete("cross-chain-test")
    test_skill_path = os.path.join(registry._skills_dir, "free", "int-test-skill.md")
    if os.path.exists(test_skill_path):
        os.remove(test_skill_path)

    # Print results
    print(f"\n{sep}")
    print("ARIS Integration Test Results")
    print(sep)
    for t in results["tests"]:
        print(t)
    print(sep)
    total_tests = results["pass"] + results["fail"]
    print(f"PASSED: {results['pass']}/{total_tests}")
    if results["fail"] > 0:
        print(f"FAILED: {results['fail']}")
    else:
        print("ALL TESTS PASSED - ORGANISM FUNCTIONAL")
    return results


if __name__ == "__main__":
    results = asyncio.run(test_integration())
    sys.exit(1 if results["fail"] > 0 else 0)
