"""Verificador independiente: solo biblioteca estándar; SHA es integridad, nunca selección.
Uso: python verify-direct-fair-independent.py prueba.json [informe.json]
Acepta el JSON público ?proof=... y reproduce política, evento y número.
La elegibilidad comercial privada NO puede probarse con este archivo público.
"""
import hashlib,json,sys

def calculate(first,second,count,start=0):
    assert all(isinstance(x,str) and len(x)==5 and x.isascii() and x.isdecimal() and 1<=int(x)<=60000 for x in (first,second))
    assert first!=second and type(count)==int and 1<=count<=1000000 and type(start)==int and start==0
    a,b=first[-3:],second[-3:]
    base=a+b
    limit=(1000000//count)*count
    first_block,second_block=(int(first)-1)//1000,(int(second)-1)//1000
    block_ok=first_block!=second_block
    range_ok=int(base)<limit if block_ok else None
    number=int(base)%count if block_ok and range_ok else None
    return dict(firstBlock=first_block,secondBlock=second_block,blockAccepted=block_ok,rangeAccepted=range_ok,rejectionReason='same_official_block' if not block_ok else 'base_rejected' if not range_ok else None,first=first,second=second,firstTail=a,secondTail=b,combined=base,limit=limit,accepted=number is not None,number=number,formattedNumber=str(number).zfill(len(str(start+count-1))) if number is not None else None)

def verify(data):
    evidence=data.get('evidence',data)
    proof=evidence['proof'];p=json.loads(proof['policyCanonical']);e=json.loads(proof['eventCanonical'])
    assert (p['algorithm'],p['version'])==('rh-ln-tail3-pair-rejection',2)
    assert (e['authority'],e['game'],e['drawNumber'],e['officialDate'])==(p['source']['authority'],p['source']['game'],p['source']['drawNumber'],p['source']['officialDate'])
    assert [x['rank'] for x in e['prizes']]==[1,2]
    result=calculate(e['prizes'][0]['number'],e['prizes'][1]['number'],int(p['range']['count']),int(p['range']['start']))
    assert result==proof['calculation']
    source=evidence['source']
    assert (source['primero'],source['segundo'],str(source['sorteo']),source['fecha'])==(e['prizes'][0]['number'],e['prizes'][1]['number'],e['drawNumber'],e['officialDate'])
    assert len(p['prizes'])==1 and p['unsoldPolicy']=='redraw'
    assert proof['results'][0]['calculatedNumber']==(str(result['number']) if result['accepted'] else None)
    assert proof['policySha256']==hashlib.sha256(('RH-LN-TAIL3/v2/policy\0'+proof['policyCanonical']).encode()).hexdigest()
    assert proof['eventSha256']==hashlib.sha256(('RH-LN-TAIL3/v2/event\0'+proof['eventCanonical']).encode()).hexdigest()
    return dict(calculationValid=True,integrityValid=True,eligibility='private_snapshot_not_independently_available',commercialActivation=False,calculation=result)

if __name__=='__main__':
    report=verify(json.load(open(sys.argv[1],encoding='utf-8-sig')))
    if len(sys.argv)>2:json.dump(report,open(sys.argv[2],'w',encoding='utf-8'),indent=2,ensure_ascii=False)
    print(json.dumps(report,ensure_ascii=False))
