import io, json, os, contextlib

BASE = os.path.join(os.path.dirname(__file__), "..", "app", "src", "main", "assets")
EXPECT_FILL = {
    "l02": "350.0\n",
    "l04": "3\n",
    "l06": "C\n",
    "l08": "['a', 'b', 'c']\n",
    "l10": "42\n",
    "l12": "2\n",
    "l14": "[4, 16]\n",
    "l16": "1\n",
    "l18": "V\n",
    "l24": "b\n",
    "l26": "ERROR\n",
}
EXPECT_ORDER = {
    "l01": "系统自检…\n内存映射完成\n欢迎接入霓虹城\n",
    "l03": "Hi,neo\n",
    "l05": "夜\n",
    "l07": "64\n",
    "l09": "{'a': 2, 'b': 1, 'c': 1}\n",
    "l11": "MEOW!!!\n",
    "l13": "3\n",
    "l15": "-1\n",
    "l17": "True\n",
    "l19": "AB\n",
    "l21": "1\n2\n",
    "l23": "[('b', 2), ('a', 1)]\n",
    "l25": "365\n",
}


def run(src):
    buf = io.StringIO()
    with contextlib.redirect_stdout(buf):
        exec(src, {})
    return buf.getvalue()


fails = []
lessons = {}
for name in ["lessons_basic.json", "lessons_mid.json", "lessons_adv.json"]:
    with open(os.path.join(BASE, name), encoding="utf-8") as f:
        for l in json.load(f):
            lessons[l["id"]] = l["blocks"]
with open("content_packs/bonus-builtin.json", encoding="utf-8") as f:
    lessons["l27"] = json.load(f)[0]["blocks"]

for lid, blocks in sorted(lessons.items()):
    for b in blocks:
        if b.get("type") == "fill":
            code = b["code"].replace("____", b["answer"])
            try:
                out = run(code)
            except Exception as e:
                fails.append(f"{lid} FILL raised {type(e).__name__}: {e}")
                continue
            exp = EXPECT_FILL.get(lid)
            if exp is not None and out != exp:
                fails.append(f"{lid} FILL out={out!r} expected={exp!r}")
        if b.get("type") == "order":
            src = "\n".join(b["lines"])
            try:
                out = run(src)
            except Exception as e:
                fails.append(f"{lid} ORDER raised {type(e).__name__}: {e}")
                continue
            exp = EXPECT_ORDER.get(lid)
            if exp is not None and out != exp:
                fails.append(f"{lid} ORDER out={out!r} expected={exp!r}")

if fails:
    print("FAILURES:")
    for f_ in fails:
        print(" -", f_)
    raise SystemExit(1)
print(f"ALL fill/order verified OK ({len(EXPECT_FILL) + len(EXPECT_ORDER)} checked)")