#!/usr/bin/env python3
"""Verify the published Side Channel experiment outputs using the standard library."""

from __future__ import annotations

import csv
import hashlib
import json
import sqlite3
import wave
from pathlib import Path


ROOT = Path(__file__).resolve().parent
OUTPUTS = ROOT / "outputs"


def sha256(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def main() -> None:
    manifest = json.loads((OUTPUTS / "manifest.json").read_text(encoding="utf-8"))
    source = OUTPUTS / "source.sqlite"
    recovered = OUTPUTS / "recovered.sqlite"
    wav_path = OUTPUTS / "side-channel.wav"

    expected_hash = manifest["database_sha256"]
    source_hash = sha256(source)
    recovered_hash = sha256(recovered)
    assert source_hash == expected_hash, "source database hash does not match manifest"
    assert recovered_hash == expected_hash, "recovered database is not byte-identical"

    with sqlite3.connect(recovered) as connection:
        integrity = connection.execute("PRAGMA integrity_check").fetchone()[0]
        title = connection.execute("SELECT title FROM track WHERE id = 1").fetchone()[0]
        arrangement_rows = connection.execute(
            "SELECT COUNT(*) FROM arrangement"
        ).fetchone()[0]
        liner_notes = connection.execute(
            "SELECT COUNT(*) FROM liner_note"
        ).fetchone()[0]

    assert integrity == "ok", f"SQLite integrity check failed: {integrity}"
    assert title == manifest["title"]
    assert arrangement_rows > 0
    assert liner_notes == manifest["clean_recovery"]["liner_note_count"]

    with wave.open(str(wav_path), "rb") as audio:
        channels = audio.getnchannels()
        sample_rate = audio.getframerate()
        sample_width = audio.getsampwidth()
        frames = audio.getnframes()

    duration = frames / sample_rate
    assert channels == manifest["channels"] == 2
    assert sample_rate == manifest["sample_rate_hz"] == 48_000
    assert sample_width == 2, "artifact must be 16-bit PCM"
    assert abs(duration - manifest["duration_seconds"]) < 1 / sample_rate

    with (OUTPUTS / "benchmark.csv").open(
        newline="", encoding="utf-8"
    ) as handle:
        cases = list(csv.DictReader(handle))

    exact = [row for row in cases if row["sha256_match"] == "True"]
    failed = [row["case"] for row in cases if row["sha256_match"] != "True"]
    assert len(cases) == manifest["benchmark_cases"] == 12
    assert len(exact) == manifest["benchmark_exact_recoveries"] == 9
    assert failed == ["clipped_0_35", "lowpass_15khz", "mono_collapse"]

    print("Side Channel artifact verified")
    print(
        f"  WAV: {channels} channels, {sample_rate} Hz, "
        f"16-bit PCM, {duration:.2f} s"
    )
    print(f"  SQLite SHA-256: {recovered_hash}")
    print(f"  PRAGMA integrity_check: {integrity}")
    print(f"  Recovered title: {title}")
    print(f"  Benchmark: {len(exact)}/{len(cases)} exact recoveries")
    print(f"  Intentional failure modes: {', '.join(failed)}")


if __name__ == "__main__":
    main()
