#!/usr/bin/env python3
"""Verificador independiente de la urna Ñande Voto (sin dependencias).
Uso:  python verificador_nandevoto.py                      (busca urna.json aquí o en Descargas)
      python verificador_nandevoto.py ruta/urna.json
      python verificador_nandevoto.py https://SU-SITIO/auditoria/urna.json   (lo descarga)
Recalcula cada hash, comprueba el encadenamiento y recuenta los votos por cargo."""
import hashlib
import json
import sys
import urllib.request
from collections import Counter
from pathlib import Path

if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8")


def cargar():
    arg = sys.argv[1] if len(sys.argv) > 1 else None
    if arg and arg.startswith(("http://", "https://")):
        print(f"Descargando {arg} …")
        with urllib.request.urlopen(arg, timeout=30) as r:
            return json.loads(r.read().decode("utf-8"))
    candidatos = [Path(arg)] if arg else []
    aqui = Path(__file__).resolve().parent
    for carpeta in (Path.cwd(), aqui, Path.home() / "Downloads", Path.home() / "Descargas"):
        candidatos += sorted(carpeta.glob("urna_nandevoto*.json"), key=lambda p: p.stat().st_mtime, reverse=True)
        candidatos.append(carpeta / "urna.json")
    for p in candidatos:
        if p.is_file():
            print(f"Usando archivo: {p}")
            return json.load(open(p, encoding="utf-8"))
    print("No se encontró el archivo de la urna.\n"
          "1) En la página Auditoría pulse «urna.json» para descargarlo.\n"
          "2) Vuelva a ejecutar:  python verificador_nandevoto.py\n"
          "   o indique la ruta:  python verificador_nandevoto.py C:\\ruta\\urna_nandevoto.json\n"
          "   o la dirección:     python verificador_nandevoto.py https://SU-SITIO/auditoria/urna.json")
    sys.exit(1)


d = cargar()
prev, errores, conteo = "0" * 64, [], {}
for i, b in enumerate(d["boletas"], 1):
    calc = hashlib.sha256(f"{b['seq']}|{b['eleccion']}|{b['departamento']}|{b['payload']}|"
                          f"{b['comprobante_hash']}|{b['creado']}|{b['hash_prev']}".encode()).hexdigest()
    if b["seq"] != i:
        errores.append(f"secuencia rota en #{b['seq']}")
    if b["hash_prev"] != prev:
        errores.append(f"enlace roto en #{b['seq']}")
    if calc != b["hash"]:
        errores.append(f"hash alterado en #{b['seq']}")
    for cargo, cand in json.loads(b["payload"]).items():
        conteo.setdefault(cargo, Counter())[cand] += 1
    prev = b["hash"]

print(f"Elección: {d['eleccion']}\nBoletas: {len(d['boletas'])}\nHash de cabeza: {prev}")
print("RESULTADO:", "URNA ÍNTEGRA ✔" if not errores else f"{len(errores)} ERRORES ✖")
for e in errores[:50]:
    print("  -", e)
for c in d["cargos"]:
    cnt = conteo.get(str(c["id"]), Counter())
    total = sum(cnt.values())
    print(f"\n== {c['nombre']} ({total} votos) ==")
    for cand, n in cnt.most_common():
        nombre = "Voto en blanco" if cand is None else c["candidaturas"].get(str(cand), f"id {cand}")
        print(f"  {n:6d}  {100 * n / total:6.2f}%  {nombre}")
