#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Независимая проверка результата розыгрыша.

Скрипт ничего не берёт с сайта организатора кроме списка участников:
случайное число он запрашивает напрямую у сети drand.

Запуск:
    python proverka.py participants.csv

Ожидаемый вывод для розыгрыша 18.08.2026: победитель №4615, @demon3635
"""
import hashlib
import hmac
import json
import sys
import urllib.request

# --- опубликованные до розыгрыша данные -------------------------------------
CHAIN = "52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971"
ROUND = 31420612                 # раунд drand, объявлен заранее (18.08.2026 17:00)
ERWARTETER_HASH = "e8b6ae85de85a5c90f1ceedcf2ba3525eeab6af630e54120aa0aac1c60847567"
ANZAHL_GEWINNER = 4              # победитель + 3 запасных

datei = sys.argv[1] if len(sys.argv) > 1 else "participants.csv"

# --- 1. контрольная сумма списка --------------------------------------------
with open(datei, "rb") as f:
    daten = f.read()
list_hash = hashlib.sha256(daten).hexdigest()

print("1) КОНТРОЛЬНАЯ СУММА СПИСКА")
print("   получилось:  ", list_hash)
print("   опубликовано:", ERWARTETER_HASH)
print("   совпадает:   ", "ДА" if list_hash == ERWARTETER_HASH else "НЕТ — файл не тот!")
print()

# --- 2. случайное число берём у самой сети drand ----------------------------
url = f"https://api.drand.sh/{CHAIN}/public/{ROUND}"
with urllib.request.urlopen(url, timeout=30) as r:
    beacon = json.load(r)
seed = beacon["randomness"]

print("2) СЛУЧАЙНОЕ ЧИСЛО (получено напрямую от drand)")
print("   раунд:", ROUND)
print("   число:", seed)
print()

# --- 3. участники -----------------------------------------------------------
zeilen = daten.decode("utf-8").replace("\r\n", "\n").strip().split("\n")
assert zeilen[0].strip().lower() == "nr;code;handle;lose", "неожиданный заголовок CSV"

# билеты в порядке файла: у каждого участника lose билетов (здесь у всех по 1)
lose = []
for zeile in zeilen[1:]:
    nr, code, handle, anzahl = zeile.split(";")
    for _ in range(int(anzahl)):
        lose.append((int(nr), code, handle))

print("3) УЧАСТНИКИ")
print("   строк в списке:", len(zeilen) - 1)
print("   билетов всего: ", len(lose))
print()

# --- 4. розыгрыш ------------------------------------------------------------
print("4) РАСЧЁТ")
pool = list(lose)
for runde in range(ANZAHL_GEWINNER):
    schluessel = bytes.fromhex(seed)
    nachricht = f"{list_hash}|{runde}".encode("utf-8")
    digest = hmac.new(schluessel, nachricht, hashlib.sha256).digest()

    zahl = int.from_bytes(digest[:16], "big")   # первые 16 байт, старший байт первым
    index = zahl % len(pool)                    # 0 … len(pool)-1
    nr, code, handle = pool[index]

    titel = "ПОБЕДИТЕЛЬ" if runde == 0 else f"запасной {runde}"
    print(f"   {titel}")
    print(f"     сообщение для HMAC: \"{list_hash}|{runde}\"")
    print(f"     HMAC-SHA256:        {digest.hex()}")
    print(f"     индекс билета:      {index}  из {len(pool)}")
    print(f"     номер в списке:     {nr}")
    print(f"     участник:           {handle}")
    print()

    # все билеты вышедшего участника убираются, счётчик увеличивается на 1
    pool = [t for t in pool if t[1] != code]
