#!/usr/bin/env python3
"""Unabhängige Soll-Gegenproben; Produktcode und bestehende Tests bleiben unverändert."""
from pathlib import Path
import os
import subprocess
import tempfile

ROOT = next(p for p in Path(__file__).resolve().parents
            if (p / "Cargo.toml").is_file() and (p / "openspec").is_dir())
TBC = ROOT / "target/debug/tbc"


def run(*args, **kwargs):
    return subprocess.run(args, capture_output=True, text=True, timeout=60, **kwargs)


def main():
    subprocess.run(["cargo", "build", "-p", "tb-cli"], cwd=ROOT, check=True)
    failed = []

    def check(name, ok, evidence):
        print(f"{'PASS' if ok else 'FAIL'} {name}: {evidence}")
        if not ok:
            failed.append(name)

    with tempfile.TemporaryDirectory(prefix="tb-review-") as tmp:
        tmp = Path(tmp)
        for name, source in [("PSET", "PSET (1,1),2"),
                             ("PALETTE", "DIM a%(15)\nPALETTE USING a%(0)")]:
            path = tmp / "graphics.bas"
            path.write_text(source + "\n")
            out = run(str(TBC), "check", str(path))
            check(name + " Non-Feature", out.returncode != 0 and
                  "Feature unavailable" in out.stderr and name in out.stderr,
                  out.stderr.strip())

        path = tmp / "parent.frm"
        path.write_text('''VERSION 1.00
Begin Form Form1
 Begin Frame Group
  Index = 0
 End
 Begin Frame Group
  Index = 1
  Begin TextBox Probe
  End
 End
End
DIM p AS CONTROL
p=Probe.Parent
Form1.Hide
PRINT p.Index
END
''')
        out = run(str(TBC), "run", str(path))
        check("Indizierter Parent aus FRM", out.returncode == 0 and out.stdout.strip() == "1",
              f"Soll=1, Ist={out.stdout!r}, {out.stderr}")
        build = run(str(TBC), "build", str(path))
        assert build.returncode == 0, build.stderr
        path.unlink()
        out = run(str(TBC), "run", str(path.with_suffix(".tbc")))
        check("Indizierter Parent aus TBC ohne Quelle", out.returncode == 0 and out.stdout.strip() == "1",
              f"Soll=1, Ist={out.stdout!r}, {out.stderr}")

        # Kopie im Temp-Verzeichnis erlaubt Zugriff auf den privaten Prüfer.
        # Einzige Mutation: TIMEZONEKNOWN zeigt auf die gültige TIMER-Bindung.
        source = (ROOT / "crates/tb-cli/tests/inventar.rs").read_text()
        source = source.replace('include_str!("../../../tests/support/inventar-quellen.tsv")',
                                f'include_str!("{ROOT}/tests/support/inventar-quellen.tsv")')
        source += r'''
#[test]
fn review_falsches_laufzeitziel_muss_abgewiesen_werden() {
    let e=inventar().into_iter().find(|e|e.name=="TIMEZONEKNOWN").unwrap();
    let (src,catalog)=probe_source(&e);
    let mut module=tb_vm::compile_source_with_forms("FORM1",&src,&catalog).unwrap();
    let mut changed=false;
    for i in module.procs.iter_mut().flat_map(|p|&mut p.code) {
        if let tb_vm::bytecode::Instr::CallBuiltin(id,_) = i {
            if *id==tb_runtime::builtins::ids::TIMEZONEKNOWN {
                *id=tb_runtime::builtins::ids::TIMER;
                changed=true;
            }
        }
    }
    assert!(changed);
    let result=pruefe_kompilat(&e,Ok(module),|id|tb_runtime::builtins::builtin_table().get(id as usize).is_some());
    assert!(result.is_err(),"TIMEZONEKNOWN mit TIMER-Ziel wird akzeptiert: {result:?}");
}
'''
        probe = tmp / "inventar.rs"
        probe.write_text(source)
        # Cargo resolves a coherent dependency graph; selecting rlibs by mtime
        # can mix feature variants after a workspace test run.
        source = source.replace('env!("CARGO_MANIFEST_DIR")', f'"{ROOT}/crates/tb-cli"')
        probe.write_text(source)
        manifest = '[package]\nname = "tb-review-probes"\nversion = "0.0.0"\nedition = "2021"\n[workspace]\n'
        manifest += '[[test]]\nname = "inventar"\npath = "inventar.rs"\n[dependencies]\n'
        for name in ["tb-vm", "tb-frontend", "tb-runtime"]:
            manifest += f'{name} = {{ path = "{ROOT}/crates/{name}" }}\n'
        (tmp / "Cargo.toml").write_text(manifest)
        env = os.environ.copy()
        env["CARGO_BIN_EXE_tbc"] = str(TBC)
        out = run("cargo", "test", "--manifest-path", str(tmp / "Cargo.toml"),
                  "--offline", "--target-dir", str(ROOT / "target/review-probes"),
                  "--test", "inventar", "review_falsches", "--", "--nocapture", env=env)
        check("Inventar erkennt falsches Laufzeitziel", out.returncode == 0,
              out.stdout + out.stderr)
    print(f"{len(failed)} fehlgeschlagene Soll-Gegenproben")
    return bool(failed)


if __name__ == "__main__":
    raise SystemExit(main())
