#!/usr/bin/env python3
"""Vérificateur MCRI — recalcule la chaîne SHA-256 et contrôle les ancrages Bitcoin.

Usage :
    python3 verifier.py          # utilise les données locales (si exécuté sur le serveur)
    python3 verifier.py --remote # télécharge manifest/anchor depuis https://defi.odata.fr

Sortie : CHAINE OK / CHAINE CORROMPUE + liste des ancrages Bitcoin vérifiés.
Ne fait confiance à personne : il relit tout depuis zéro.
"""
import hashlib
import json
import sys
import urllib.request

BASE = "https://defi.odata.fr"


def load(name, remote):
    if remote:
        with urllib.request.urlopen(f"{BASE}/{name}", timeout=30) as r:
            return [json.loads(l) for l in r.read().decode().splitlines() if l.strip()]
    with open(f"data/{name}") as f:
        return [json.loads(l) for l in f if l.strip()]


def verify_chain(entries):
    prev = "0" * 64
    for e in entries:
        h = e["hash"]
        recomputed = hashlib.sha256((prev + e["payload"]).encode()).hexdigest()
        if h != recomputed:
            return False, f"Rupture à {e['ts']} (attendu {recomputed[:16]}, lu {h[:16]})"
        prev = h
    return True, prev


def verify_anchors(anchors, manifest_hashes):
    ok = 0
    manifest_hashes = {m["hash"] for m in manifest_hashes}
    for a in anchors:
        if a["root_hash"] not in manifest_hashes:
            print(f"  [AVERTISSEMENT] root {a['root_hash'][:16]} absent du manifest")
            continue
        # On ne peut pas réécrire un bloc Bitcoin : on contrôle que le hash de bloc
        # annoncé existe réellement en interrogeant Blockstream.
        url = f"https://blockstream.info/api/block-height/{a['btc_block_height']}"
        with urllib.request.urlopen(url, timeout=30) as r:
            real = r.read().decode().strip()
        match = (real == a["btc_block_hash"])
        print(f"  [{'OK' if match else 'ECHEC'}] bloc #{a['btc_block_height']} "
              f"{a['btc_block_hash'][:16]} {'=' if match else '!='} {real[:16]}")
        ok += match
    return ok


def main():
    remote = "--remote" in sys.argv
    manifest = load("data/manifest.jsonl", remote)
    anchors = load("data/anchor.jsonl", remote) if (remote or __import__("os").path.exists("data/anchor.jsonl")) else []
    chain_ok, last = verify_chain(manifest)
    print(("CHAINE OK" if chain_ok else "CHAINE CORROMPUE") + f" — {len(manifest)} entrées, dernier hash {last[:16]}")
    if not chain_ok:
        sys.exit(1)
    if anchors:
        n = verify_anchors(anchors, manifest)
        print(f"ANCRAGES BITCOIN : {n}/{len(anchors)} vérifiés")


if __name__ == "__main__":
    main()
