#!/usr/bin/env python3
"""Retrieve only ten pinned public text references for Lab 11. Never execute templates or load models."""
import argparse
import datetime
import hashlib
import json
from pathlib import Path
import urllib.request

FILES = {'base-README.md': ('https://huggingface.co/Qwen/Qwen2.5-0.5B/resolve/060db6499f32faf8b98477b0a26969ef7d8b9987/README.md',
                    3850,
                    '3c93cbc9f60417337fcbf093da872007586b9d886b0f0187f21aec35b869616a'),
 'base-config.json': ('https://huggingface.co/Qwen/Qwen2.5-0.5B/resolve/060db6499f32faf8b98477b0a26969ef7d8b9987/config.json',
                      681,
                      '479dcf0c5286339e41ad3992cd08ae88a467c4187587936248e2b7c96283484b'),
 'base-tokenizer_config.json': ('https://huggingface.co/Qwen/Qwen2.5-0.5B/resolve/060db6499f32faf8b98477b0a26969ef7d8b9987/tokenizer_config.json',
                                7228,
                                'c91efca15ceff6e9ee9424db58a6f59cd41294e550a86cbd07e3c1fb500b34f9'),
 'base-generation_config.json': ('https://huggingface.co/Qwen/Qwen2.5-0.5B/resolve/060db6499f32faf8b98477b0a26969ef7d8b9987/generation_config.json',
                                 138,
                                 '8c970692323e3ea0e9b8b0a4dca79388d31226e41f83c9fd6014804280ebf6e8'),
 'base-LICENSE': ('https://huggingface.co/Qwen/Qwen2.5-0.5B/resolve/060db6499f32faf8b98477b0a26969ef7d8b9987/LICENSE',
                  11343,
                  '832dd9e00a68dd83b3c3fb9f5588dad7dcf337a0db50f7d9483f310cd292e92e'),
 'instruct-README.md': ('https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/resolve/7ae557604adf67be50417f59c2c2f167def9a775/README.md',
                        4917,
                        'b19c806a904db6dc878a0462e70b551f6b7ac78dfbb88c2eb966ca2b9109ae15'),
 'instruct-config.json': ('https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/resolve/7ae557604adf67be50417f59c2c2f167def9a775/config.json',
                          659,
                          '18e18afcaccafade98daf13a54092927904649e1dd4eba8299ab717d5d94ff45'),
 'instruct-tokenizer_config.json': ('https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/resolve/7ae557604adf67be50417f59c2c2f167def9a775/tokenizer_config.json',
                                    7305,
                                    '5b5d4f65d0acd3b2d56a35b56d374a36cbc1c8fa5cf3b3febbbfabf22f359583'),
 'instruct-generation_config.json': ('https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/resolve/7ae557604adf67be50417f59c2c2f167def9a775/generation_config.json',
                                     242,
                                     'e558847a8b4402616f1273797b015104dc266fe4b520056fca88823ba8f8ebe6'),
 'instruct-LICENSE': ('https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/resolve/7ae557604adf67be50417f59c2c2f167def9a775/LICENSE',
                      11343,
                      '832dd9e00a68dd83b3c3fb9f5588dad7dcf337a0db50f7d9483f310cd292e92e')}


def retrieve(destination, offline=False):
    destination = Path(destination)
    if destination.is_symlink():
        raise ValueError('Dedicated source directory must not be a symlink')
    destination.mkdir(parents=True, exist_ok=True)
    if set(p.name for p in destination.iterdir()) - set(FILES) - {'provenance.json'}:
        raise ValueError('Dedicated directory contains unexpected files')
    rows = []
    for name, (url, size, digest) in FILES.items():
        target = destination / name
        if target.is_symlink():
            raise ValueError('Reference must not be a symlink')
        if target.exists():
            data = target.read_bytes()
        elif offline:
            raise ValueError(f'Missing offline reference: {name}')
        else:
            with urllib.request.urlopen(url, timeout=30) as response:
                data = response.read(size + 1)
        if len(data) != size or hashlib.sha256(data).hexdigest() != digest:
            raise ValueError(f'Size/SHA-256 mismatch: {name}')
        data.decode('utf-8')
        if not target.exists():
            target.write_bytes(data)
        rows.append({'file': name, 'url': url, 'bytes': size, 'sha256': digest})
    report = {'kind': 'public reference text only; no execution or model loading',
              'verified_at_utc': datetime.datetime.now(datetime.timezone.utc).isoformat(),
              'files': rows, 'notices': 'Original downloaded bytes and embedded notices retained unchanged. Both repository LICENSE files are retained unchanged. The paper has separate terms; it is not downloaded or redistributed.'}
    provenance = destination / 'provenance.json'
    if provenance.is_symlink():
        raise ValueError('Provenance must not be a symlink')
    if not provenance.exists():
        provenance.write_text(json.dumps(report, indent=2) + '\n', encoding='utf-8')
    return report


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--output', type=Path, default=Path('training-evidence'))
    parser.add_argument('--offline', action='store_true')
    parser.add_argument('--plan', action='store_true')
    args = parser.parse_args()
    print(json.dumps({'files': FILES, 'total_bytes': sum(v[1] for v in FILES.values())} if args.plan else retrieve(args.output, args.offline), indent=2))


if __name__ == '__main__':
    main()
