#!/usr/bin/env python3
"""Scripted, synthetic demonstrations; no coding product or model is invoked."""
from __future__ import annotations

import argparse
from concurrent.futures import ThreadPoolExecutor
import hashlib
import importlib.util
import json
from pathlib import Path
import subprocess
import threading
import time

HERE = Path(__file__).resolve().parent
CONTRACT = json.loads((HERE / "contracts.json").read_text())


def run(argv, cwd, allowed=(0,)):
    result = subprocess.run(argv, cwd=cwd, capture_output=True, text=True, timeout=30)
    record = {"argv": argv, "exit_code": result.returncode,
              "stdout": result.stdout, "stderr": result.stderr}
    if result.returncode not in allowed:
        raise RuntimeError(json.dumps(record))
    return record


def module(path):
    # Execute exact text, avoiding stale .pyc files after a tiny same-size patch.
    spec = importlib.util.spec_from_loader("demo", loader=None)
    value = importlib.util.module_from_spec(spec)
    exec(compile(path.read_text(), str(path), "exec"), value.__dict__)
    return value


def shipping(output):
    source = output / "shipping.py"
    baseline = "def shipping_fee(subtotal):\n    return 0 if subtotal > 10000 else 500\n"
    source.write_text(baseline)
    weak_passes = module(source).shipping_fee(12000) == 0
    observed = [(x, module(source).shipping_fee(x), expected)
                for x, expected in CONTRACT["shipping"]["cases"]]
    failures = [item for item in observed if item[1] != item[2]]
    assert weak_passes and failures == [(10000, 500, 0)]
    source.write_text(baseline.replace("> 10000", ">= 10000"))
    assert all(module(source).shipping_fee(x) == expected
               for x, expected in CONTRACT["shipping"]["cases"])
    (output / "baseline.py").write_text(baseline)
    (output / "repair.diff").write_text("-    return 0 if subtotal > 10000 else 500\n+    return 0 if subtotal >= 10000 else 500\n")
    return {"intentionally_weak_test_passed_on_defect": weak_passes,
            "independent_oracle_failures_before": failures,
            "independent_oracle_failures_after": [],
            "intervention": "script applies the predeclared comparison-operator repair"}


def pagination(output):
    root = output / "fixture"
    root.mkdir()
    baseline = ("def page(items, offset, limit):\n"
                "    if offset < 0 or limit <= 0:\n        raise ValueError('invalid pagination')\n"
                "    return items[offset:limit]\n")
    path = root / "pagination.py"
    path.write_text(baseline)
    run(["git", "init", "-q"], root)
    for key, value in [("user.name", "Synthetic fixture"), ("user.email", "fixture@example.invalid")]:
        run(["git", "config", key, value], root)
    run(["git", "add", "pagination.py"], root)
    run(["git", "commit", "-qm", "Synthetic pagination baseline"], root)
    base = run(["git", "rev-parse", "HEAD"], root)["stdout"].strip()
    cases = CONTRACT["pagination"]["cases"]
    failures = [case for case in cases if module(path).page(*case[:3]) != case[3]]
    assert failures
    path.write_text(baseline.replace("items[offset:limit]", "items[offset:offset + limit]"))
    for items, offset, limit, expected in cases:
        original = list(items)
        assert module(path).page(items, offset, limit) == expected
        assert items == original
    for offset, limit in [(-1, 2), (0, 0), (0, -1)]:
        try:
            module(path).page([1, 2], offset, limit)
        except ValueError:
            continue
        raise AssertionError("invalid pagination was accepted")
    diff = run(["git", "diff", "--", "pagination.py"], root)["stdout"]
    (output / "repair.diff").write_text(diff)
    repaired = path.read_bytes()
    run(["git", "restore", "pagination.py"], root)
    assert path.read_text() == baseline
    path.write_bytes(repaired)
    return {"baseline_commit": base,
            "baseline_source_sha256": hashlib.sha256(baseline.encode()).hexdigest(),
            "failed_cases_before": failures, "failed_cases_after": [],
            "recovery": "git restore baseline exercised, then reviewed scripted repair restored",
            "intervention": "one predeclared line replacement by the script"}


def parallel(output):
    root = output / "fixture"
    root.mkdir()
    run(["git", "init", "-q"], root)
    for key, value in [("user.name", "Synthetic fixture"), ("user.email", "fixture@example.invalid")]:
        run(["git", "config", key, value], root)
    settings = root / "settings.json"
    settings.write_text('{"label":"queue","limit":20}\n')
    run(["git", "add", "settings.json"], root)
    run(["git", "commit", "-qm", "Synthetic parallel baseline"], root)
    base = run(["git", "rev-parse", "HEAD"], root)["stdout"].strip()
    worktrees = [output / "task-label", output / "task-limit"]
    for branch, path in zip(["task-label", "task-limit"], worktrees):
        run(["git", "worktree", "add", "-b", branch, str(path)], root)
    barrier = threading.Barrier(2, timeout=10)

    def worker(index):
        path = worktrees[index]
        other = worktrees[1-index]
        marker = path / f"private-{index}.txt"
        marker.write_text("uncommitted fixture marker")
        barrier.wait()
        assert not (other / marker.name).exists()
        value = {"label": "review" if index == 0 else "queue",
                 "limit": 20 if index == 0 else 50}
        (path / "settings.json").write_text(json.dumps(value, separators=(",", ":")) + "\n")
        run(["git", "add", "settings.json"], path)
        run(["git", "commit", "-qm", f"Scripted task {index}"], path)
        return {"task": index, "uncommitted_files_isolated": True}

    started = time.monotonic()
    with ThreadPoolExecutor(max_workers=2) as pool:
        records = list(pool.map(worker, [0, 1]))
    elapsed = time.monotonic() - started
    run(["git", "merge", "--ff-only", "task-label"], root)
    conflict = run(["git", "merge", "--no-edit", "task-limit"], root, allowed=(1,))
    assert "CONFLICT" in conflict["stdout"]
    (output / "injected-conflict.txt").write_text(settings.read_text())
    settings.write_text('{"label":"review","limit":50}\n')
    run(["git", "add", "settings.json"], root)
    run(["git", "commit", "-qm", "Resolve injected conflict preserving both tasks"], root)
    assert json.loads(settings.read_text()) == {"label": "review", "limit": 50}
    return {"baseline_commit": base, "scripted_workers": records,
            "scripted_parallel_wall_seconds": elapsed,
            "merge_exit_before_resolution": conflict["exit_code"],
            "resolved_settings": json.loads(settings.read_text()),
            "intervention": "script resolves the deliberately injected conflict"}


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("topic", choices=["tests", "brownfield", "parallel"])
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()
    output = args.output.resolve()
    output.mkdir(parents=True, exist_ok=False)
    result = {"status": "SCRIPTED_DEMONSTRATION", "coding_product_runs": "NOT_RUN",
              "model": None, "api_spend": 0, "human_review_time": None,
              "contract_sha256": hashlib.sha256((HERE / "contracts.json").read_bytes()).hexdigest()}
    result["observations"] = {"tests": shipping, "brownfield": pagination,
                              "parallel": parallel}[args.topic](output)
    (output / "result.json").write_text(json.dumps(result, indent=2) + "\n")
    print(json.dumps(result, indent=2))


if __name__ == "__main__":
    main()
