import json, shutil, subprocess, time, sys
from pathlib import Path

REPO = Path(__file__).resolve().parents[2]
BACKUP_DIR = REPO / "scripts" / "qc_flag" / ".backups"
RECEIPTS_DIR = REPO / "scripts" / "qc_flag" / "receipts"


def run_single(src_path, mut_path, target="SilverSightRRC", timeout=60):
    """Backup → apply mutation → build → restore. Returns dict with result."""
    BACKUP_DIR.mkdir(parents=True, exist_ok=True)
    backup = BACKUP_DIR / src_path.name
    if not backup.exists():
        shutil.copy2(src_path, backup)

    orig = src_path.read_text()
    src_path.write_bytes(mut_path.read_bytes())

    t0 = time.perf_counter()
    try:
        r = subprocess.run(
            ["lake", "build", target],
            cwd=REPO, capture_output=True, text=True, timeout=timeout
        )
        exit_code = r.returncode
        output = (r.stdout + r.stderr)[-500:]
    except subprocess.TimeoutExpired:
        exit_code = -1
        output = "TIMEOUT"
    except FileNotFoundError:
        exit_code = -2
        output = "lake not found"

    src_path.write_text(orig)
    elapsed = round(time.perf_counter() - t0, 2)

    mut_id = mut_path.stem.split("_")[0]
    actual = "FAIL" if exit_code != 0 else "PASS"
    return {
        "mutation_id": mut_id,
        "source": str(src_path),
        "expected": "FAIL",
        "actual": actual,
        "exit_code": exit_code,
        "elapsed_s": elapsed,
        "build_log_snippet": output,
    }


def compute_coverage(results):
    total = len(results)
    failed = sum(1 for r in results if r["actual"] == "FAIL")
    return {
        "total": total, "failed_expected": failed,
        "passed_unexpectedly": total - failed,
        "coverage_ratio": round(failed / total, 4) if total else 0,
        "verdict": "PASS" if total > 0 and failed == total else "FAIL",
    }


def emit_receipt(results, coverage):
    RECEIPTS_DIR.mkdir(parents=True, exist_ok=True)
    path = RECEIPTS_DIR / f"coverage_{int(time.time())}.json"
    path.write_text(json.dumps({
        "schema": "mutation_coverage_receipt_v1",
        "generated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
        "coverage": coverage,
        "entries": results,
    }, indent=2))
    return path
