#!/usr/bin/env python3
# CL True Path Range (TPR-72) — Sealed Track Record: независимая проверка прогнозов. Нужен только Python 3 и интернет.
#   python3 verify.py                   — проверить всю цепочку печатей
#   python3 verify.py BTCUSDT 2026-10-07T10:00   — пересчитать вердикт одного прогноза по свечам Binance
# Время печати вне нашего сервера: файлы /forecast/log/anchor/*.txt + .ots проверяются на opentimestamps.org (блок Bitcoin)
import hashlib, json, sys, urllib.request  # noqa
from datetime import datetime, timezone
SITE = 'https://cryptologixbot.com/forecast/log/'
get = lambda u: urllib.request.urlopen(urllib.request.Request(u, headers={'User-Agent': 'Mozilla/5.0 (er-verify)'}), timeout=30).read().decode()
chain = [json.loads(l) for l in get(SITE + 'chain.jsonl').splitlines() if l.strip()]
days, by = {}, {}
for c in chain:
    d = datetime.fromtimestamp(c['ts'] / 1000, timezone.utc).strftime('%Y-%m-%d')
    if d not in days:
        days[d] = get(SITE + d + '.jsonl').splitlines()
        for l in days[d]:
            if l.strip():
                by.setdefault(json.loads(l)['ts'], []).append(l)
prev = '0' * 64
for c in chain:
    sha = hashlib.sha256((prev + '\n' + '\n'.join(sorted(by.get(c['ts'], [])))).encode()).hexdigest()
    if c['prev'] != prev or sha != c['sha']:
        sys.exit('ОШИБКА в часе %s' % datetime.fromtimestamp(c['ts'] / 1000, timezone.utc))
    prev = sha
print('цепочка цела: %d часов, последняя печать %s' % (len(chain), prev))
if len(sys.argv) > 2:
    s = sys.argv[1].upper()
    ts = int(datetime.fromisoformat(sys.argv[2]).replace(tzinfo=timezone.utc).timestamp() * 1000)
    x = next(json.loads(l) for l in by.get(ts, []) if json.loads(l)['s'] == s)
    if datetime.now(timezone.utc).timestamp() * 1000 < ts + 72 * 3600 * 1000:
        sys.exit('проверка будет ' + datetime.fromtimestamp(ts / 1000 + 72 * 3600, timezone.utc).strftime('%Y-%m-%d %H:%M UTC'))
    k = json.loads(get('https://fapi.binance.com/fapi/v1/klines?symbol=%s&interval=1h&startTime=%d&limit=72' % (s, ts)))
    if len(k) < 72 or int(k[0][0]) != ts:
        sys.exit('нет свечей Binance за это окно')
    hi, lo = max(float(r[2]) for r in k), min(float(r[3]) for r in k)
    a, b = x['c'] * (1 - x['h80'] / 100), x['c'] * (1 + x['h80'] / 100)
    print('прогноз %s от %s: цена %s, диапазон 80%%: %.6g – %.6g' % (s, sys.argv[2], x['c'], a, b))
    print('факт за 72ч: максимум %.6g, минимум %.6g ->' % (hi, lo), 'ВНУТРИ' if lo >= a and hi <= b else 'ВЫШЛА')
