"""Is the model you downloaded whole? Compare each file with the site's own numbers.

    python model_files.py

It reads the five files in the folder "model" beside pond.py. It asks the site once
for its list of files: each file's size and its fingerprint. Then it reads your
files and prints "whole", or what differs. It downloads nothing but that list.

A fingerprint is a long number worked out from every byte of a file. Two files with
the same fingerprint are the same file. The site gives a SHA-256 fingerprint for its
big files, and for its small files the fingerprint that git uses.
"""
import hashlib
import json
import pathlib
import sys
import urllib.request

ASSETS = pathlib.Path(__file__).resolve().parent.parent      # pond.py: one folder up from checks/
LIST = "https://huggingface.co/api/models/Mapika/decider-2b-GGUF/tree/main"
FILES = ["decider_config.json", "tokenizer_config.json", "chat_template.jinja",
         "tokenizer.json", "decider-2b-v11-Q4_K_M.gguf"]


def fingerprint_of(path, big):
    """SHA-256 of a big file. For a small file: git's fingerprint of it."""
    size = path.stat().st_size
    digest = hashlib.sha256()
    if not big:
        # git puts "blob", the size and a zero byte in front of the file's bytes.
        digest = hashlib.sha1(b"blob " + str(size).encode() + b"\0")
    with open(path, "rb") as file:
        piece = file.read(1 << 22)
        while piece:
            digest.update(piece)
            piece = file.read(1 << 22)
    return digest.hexdigest()


def main():
    with urllib.request.urlopen(LIST, timeout=60) as reply:
        on_site = {entry["path"]: entry for entry in json.load(reply)}
    folder = ASSETS / "model"
    problems = 0
    for name in FILES:
        path = folder / name
        if not path.exists():
            print(f"MISSING    {name}")
            problems += 1
            continue
        entry = on_site[name]
        mine = path.stat().st_size
        if mine != entry["size"]:
            print(f"NOT WHOLE  {name}: {mine:,} bytes here, {entry['size']:,} on the site")
            problems += 1
            continue
        big = "lfs" in entry and entry["lfs"] is not None
        wanted = entry["lfs"]["oid"] if big else entry["oid"]
        if fingerprint_of(path, big) != wanted:
            print(f"DIFFERENT  {name}: the size is right, but the fingerprint is not")
            problems += 1
            continue
        print(f"whole      {name}: {mine:,} bytes, and the same fingerprint as the site's")
    print("All five files are whole." if not problems else f"{problems} files have a problem.")
    return 1 if problems else 0


if __name__ == "__main__":
    sys.exit(main())
