"""Construct small protocol-v1 fixtures and run only btrfs receive --dump.

No send, mount, receive-to-directory, device access or filesystem restoration.
Results describe the recorded executable, not all btrfs-progs versions.
"""
import argparse
import hashlib
import json
import os
import platform
import shutil
import struct
import subprocess
import tempfile
from datetime import datetime, timezone
from pathlib import Path


def crc32c(data, initial=0):
    value = initial
    for byte in data:
        value ^= byte
        for _ in range(8):
            value = (value >> 1) ^ (0x82F63B78 if value & 1 else 0)
    return value


def attribute(kind, data):
    return struct.pack("<HH", kind, len(data)) + data


def u64(value):
    return struct.pack("<Q", value)


def command(kind, payload=b""):
    header = struct.pack("<IHI", len(payload), kind, 0)
    checksum = crc32c(header + payload)
    return struct.pack("<IHI", len(payload), kind, checksum) + payload


HEADER = b"btrfs-stream\0" + struct.pack("<I", 1)
UUID = bytes.fromhex("00112233445566778899aabbccddeeff")
PARENT = bytes.fromhex("ffeeddccbbaa99887766554433221100")
SUBVOL = command(1, attribute(15, b"fixture") + attribute(1, UUID) + attribute(2, u64(1)))
MKFILE = command(3, attribute(15, b"payload") + attribute(3, u64(257)))
WRITE = command(15, attribute(15, b"payload") + attribute(18, u64(0)) + attribute(19, b"HESELA"))
END = command(21)
SNAPSHOT = command(2, attribute(15, b"fixture") + attribute(1, UUID) +
                   attribute(2, u64(2)) + attribute(20, PARENT) + attribute(21, u64(1)))


def fixtures():
    full = HEADER + SUBVOL + MKFILE + WRITE + END
    bad = bytearray(WRITE)
    bad[-1] ^= 1
    return [
        ("complete-file", full, 0, "write", "Six payload bytes in one WRITE command"),
        ("write-omitted", HEADER + SUBVOL + MKFILE + END, 0, "mkfile",
         "Whole WRITE removed; all remaining command checksums unchanged"),
        ("payload-bit-flipped", HEADER + SUBVOL + MKFILE + bytes(bad) + END, 1,
         "crc", "One payload bit flipped without updating its command checksum"),
        ("end-missing", full[:-len(END)], 1, "EOF", "END command removed"),
        ("command-truncated", HEADER + SUBVOL + MKFILE + WRITE[:-1], 1,
         "read", "Last payload byte and END absent"),
        ("unresolved-parent", HEADER + SNAPSHOT + END, 0, "snapshot",
         "Synthetic parent UUID; no destination or parent provided to dump"),
    ]


def run(binary):
    # Standard CRC32C check value cross-checks the polynomial and reflection.
    if (crc32c(b"123456789", 0xFFFFFFFF) ^ 0xFFFFFFFF) != 0xE3069283:
        raise RuntimeError("CRC32C check vector failed")
    executable = shutil.which(binary)
    if not executable:
        raise RuntimeError("btrfs executable not found")
    executable = str(Path(executable).resolve())
    version = subprocess.run([executable, "version"], check=True, capture_output=True,
                             text=True, timeout=10).stdout.strip()
    rows = []
    with tempfile.TemporaryDirectory(prefix="hesela-btrfs-dump-") as directory:
        for name, data, expected_code, marker, purpose in fixtures():
            argv = [executable, "receive", "--dump"]
            process = subprocess.run(argv, input=data, capture_output=True, cwd=directory,
                                     env={**os.environ, "LC_ALL": "C"}, timeout=10)
            stdout = process.stdout.decode("utf-8", errors="replace")
            stderr = process.stderr.decode("utf-8", errors="replace")
            if process.returncode != expected_code or marker.lower() not in (stdout + stderr).lower():
                raise RuntimeError(f"{name}: unexpected result {process.returncode}: {stdout} {stderr}")
            if list(Path(directory).iterdir()):
                raise RuntimeError("Dump unexpectedly created an entry in its empty working directory")
            rows.append({"case": name, "bytes": len(data), "sha256": hashlib.sha256(data).hexdigest(),
                         "purpose": purpose, "exitCode": process.returncode,
                         "stdout": stdout, "stderr": stderr})
    return {
        "schemaVersion": 1, "generatedAt": datetime.now(timezone.utc).isoformat(),
        "evidenceType": "controlled-software-experiment", "protocolVersion": 1,
        "command": ["btrfs", "receive", "--dump"],
        "environment": {"btrfs": version, "python": platform.python_version(),
                        "system": platform.system(), "machine": platform.machine(),
                        "binarySha256": hashlib.sha256(Path(executable).read_bytes()).hexdigest()},
        "scope": "Six synthetic parser controls, one invocation per case. No Btrfs filesystem mounted or restored. No frequency or security claim.",
        "construction": "Little-endian protocol-v1 commands; CRC32C seed zero, no final XOR, CRC field zero while calculating. Fixture source is original Hesela code.",
        "source": "https://github.com/kdave/btrfs-progs/blob/c03e29f083678f47a7d7d810db4d21d905979b77/kernel-shared/send.h",
        "license": "CC0-1.0 for this original harness and generated fixture observations; not upstream btrfs-progs.",
        "rows": rows,
    }


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--binary", default="btrfs")
    parser.add_argument("--output", type=Path)
    parser.add_argument("--verify", type=Path, help="Compare case bytes, exit codes and output to recorded JSON")
    args = parser.parse_args()
    result = run(args.binary)
    if args.verify:
        recorded = json.loads(args.verify.read_text())
        if result["rows"] != recorded["rows"]:
            raise RuntimeError("Observed cases differ from recorded results")
    if args.output:
        args.output.write_text(json.dumps(result, indent=2) + "\n")
    print(json.dumps(result, indent=2))


if __name__ == "__main__":
    main()
