"""Run a real SDK client/server session and retain results, not fabricated traces."""
import asyncio
import hashlib
import importlib.metadata
import json
import platform
import sys
from datetime import datetime, timezone
from pathlib import Path

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

ROOT = Path(__file__).resolve().parents[1]
INPUTS = ["scripts/mcp_course_server.py", "scripts/verify_mcp.py", "assets/examples/teacher-prep/course-materials.json", "requirements-mcp.txt"]


async def run():
    report = {"status": "running", "executedAt": datetime.now(timezone.utc).isoformat(), "platform": platform.platform(), "python": platform.python_version(), "sdk": importlib.metadata.version("mcp"), "transport": "stdio", "modelCalled": False, "inputHashes": {f: hashlib.sha256((ROOT / f).read_bytes()).hexdigest() for f in INPUTS}}
    params = StdioServerParameters(command=sys.executable, args=[str(ROOT / "scripts/mcp_course_server.py")])
    fixture_before = (ROOT / INPUTS[2]).read_bytes()
    stderr_file = ROOT / "docs/evidence/mcp-server-stderr.txt"
    with stderr_file.open("w") as errlog:
        async with stdio_client(params, errlog=errlog) as (read, write):
            async with ClientSession(read, write) as session:
                init = await session.initialize()
                report["initialize"] = init.model_dump(mode="json", exclude_none=True)
                tools = await session.list_tools()
                resources = await session.list_resources()
                prompts = await session.list_prompts()
                report["tools"] = tools.model_dump(mode="json", exclude_none=True)
                report["resources"] = resources.model_dump(mode="json", exclude_none=True)
                report["prompts"] = prompts.model_dump(mode="json", exclude_none=True)
                result = await session.call_tool("get_course_material", {"course_id": "silk-road-01"})
                report["toolResult"] = result.model_dump(mode="json", exclude_none=True)
                parsed = result.structuredContent or json.loads(result.content[0].text)
                fixture = json.loads(fixture_before)
                report["dataVerified"] = parsed["course"] == fixture["courses"][0]
                resource = await session.read_resource("course://catalog")
                report["resourceResult"] = resource.model_dump(mode="json", exclude_none=True)
                prompt = await session.get_prompt("prepare_lesson", {"course_id": "silk-road-01"})
                report["promptResult"] = prompt.model_dump(mode="json", exclude_none=True)
                missing = await session.call_tool("get_course_material", {"course_id": "not-found"})
                traversal = await session.call_tool("get_course_material", {"course_id": "../../private"})
                report["missingCourseResult"] = missing.model_dump(mode="json", exclude_none=True)
                report["pathInputResult"] = traversal.model_dump(mode="json", exclude_none=True)
                report["checks"] = {
                    "expectedToolOnly": [t.name for t in tools.tools] == ["get_course_material"],
                    "resourceRead": json.loads(resource.contents[0].text)["courses"][0]["id"] == "silk-road-01",
                    "promptRetrieved": "silk-road-01" in prompt.messages[0].content.text,
                    "missingCourseRejected": missing.isError is True,
                    "pathInputRejected": traversal.isError is True,
                    "fixtureUnchanged": (ROOT / INPUTS[2]).read_bytes() == fixture_before,
                    "scheduleIs40Minutes": sum(x["minutes"] for x in parsed["course"]["schedule"]) == 40,
                }
    # Exiting both contexts terminates the local server; no persistent connection is installed.
    report["checks"]["sessionClosed"] = True
    report["status"] = "passed" if report["dataVerified"] and all(report["checks"].values()) and not result.isError and init.protocolVersion == "2025-11-25" else "failed"
    (ROOT / "docs/evidence/mcp-run.json").write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
    text = [f"SDK: mcp {report['sdk']}", f"Protocol: {init.protocolVersion}", "Transport: stdio", "Tools: get_course_material", "Resources: course://catalog", "Prompts: prepare_lesson", f"Course: {parsed['course']['id']}", f"Title: {parsed['course']['title']}", f"Duration: {parsed['course']['durationMinutes']} minutes", "Source material IDs: M01, M02, M03", f"Result: {report['status']}", "Model called: no; this experiment verifies MCP communication, not generated teaching quality."]
    (ROOT / "docs/evidence/mcp-transcript.txt").write_text("\n".join(text) + "\n")
    print("\n".join(text))
    if report["status"] != "passed":
        raise RuntimeError("MCP verification failed; inspect mcp-run.json")


if __name__ == "__main__":
    asyncio.run(asyncio.wait_for(run(), timeout=30))
